Java基础知识(3)- Java 修饰符、运算符
1. Java 修饰符
Java 语言提供了很多修饰符,主要分为以下两类: 访问控制修饰符,非访问控制修饰符
1) 访问控制修饰符
Java 中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。Java 支持4种不同的访问权限。
(1) default - 默认访问修饰符(不使用任何关键字):
使用默认访问修饰符声明的变量和方法,同一个包内的类可访问。接口里的变量都隐式声明为 public static final, 而接口里的方法默认情况下访问权限为 public。
(2) private - 私有访问修饰符
私有访问修饰符是最严格的访问级别,被声明为 private 的方法、变量和构造方法只能被所属类访问,并且类和接口不能声明为 private。
声明为私有访问类型的变量只能通过类中公共的 getter 方法被外部类访问。
Private 访问修饰符的使用主要用来隐藏类的实现细节和保护类的数据。
(3) protected - 受保护的访问修饰符
被声明为 protected 的变量、方法和构造器能被同一个包中的任何其他类访问,也能够被不同包中的子类访问。
Protected 访问修饰符不能修饰类和接口,方法和成员变量能够声明为 protected,但是接口的成员变量和成员方法不能声明为 protected。
子类能访问 Protected 修饰符声明的方法和变量,这样就能保护不相关的类使用这些方法和变量。
(4) public - 公有访问修饰符
被声明为 public 的类、方法、构造方法和接口能够被任何其他类访问。
如果几个相互访问的 public 类分布在不同的包中,则需要导入相应 public 类所在的包。由于类的继承性,类所有的公有方法和变量都能被其子类继承。
访问控制和继承, 请注意以下方法继承的规则:
a) 父类中声明为 public 的方法在子类中也必须为 public。
b) 父类中声明为 protected 的方法在子类中要么声明为 protected,要么声明为 public。不能声明为 private。
c) 父类中声明为 private 的方法,不能够被继承。
(5) 访问控制权限列表
本类 | 本包 | 子类 | 外部包 | |
public | Y | Y | Y | Y |
protected | Y | Y | Y | X |
default | Y | Y | X | X |
private | Y | X | X | X |
实例:
1 interface Modifier { 2 3 String name = "modifier name"; // 接口里的变量都隐式声明为 public static final, 需要初始化 4 //protected int a = 1; // 接口的成员变量和成员方法不能声明为 protected 5 //private int b = 2; // 接口的成员变量和成员方法不能声明为 private 6 7 String getName(); // 接口里的方法默认情况下访问权限为 public 8 9 } 10 11 class ModifierImpl implements Modifier { 12 13 String label = "modifier label"; // default 访问权限, 同一个包内的类可访问 14 protected int x = 3; // 同一个包中的其他类能访问,也能够被不同包中的子类访问 15 private int y = 4; // 同一个包中的其他类不能访问 16 public int z = 5; 17 18 @Override 19 public String getName() { 20 return name; 21 } 22 23 } 24 25 public class App { 26 public static void main( String[] args ) { 27 ModifierImpl modifierImpl = new ModifierImpl(); 28 System.out.println("Name is: " + modifierImpl.getName()); 29 System.out.println("Label is: " + modifierImpl.label); 30 System.out.println("x is: " + modifierImpl.x); 31 //System.out.println("y is: " + modifierImpl.y); 32 System.out.println("z is: " + modifierImpl.z); 33 } 34 }
输出:
Name is: modifier name
Label is: modifier label
x is: 3
z is: 5
2) 非访问控制修饰符
(1) static 修饰符 (静态)
a) 静态变量:
static 关键字用来声明独立于对象的静态变量,无论一个类实例化多少对象,它的静态变量只有一份拷贝。静态变量也被称为类变量。局部变量不能被声明为static变量。
b) 静态方法:
static 关键字用来声明独立于对象的静态方法。静态方法不能使用类的非静态变量,也不能被子类重写 (@Override)。
对类变量和方法的访问可以直接使用 classname.variablename 和 classname.methodname 的方式访问。
(2) final 修饰符
a) final 变量:
final 变量能被显式地初始化并且只能初始化一次。被声明为 final 的对象的引用不能指向不同的对象。但是 final 对象里的数据可以被改变。也就是说 final 对象的引用不能改变,但是里面的值可以改变。
final 修饰符通常和 static 修饰符一起使用来创建类常量。
b) final 方法:
类中的 Final 方法可以被子类继承,但是不能被子类重写(@Override)。 声明 final 方法的主要目的是防止该方法的内容被重写。
c) final 类:
final 类不能被继承,没有类能够继承 final 类的任何特性。
(3) abstract 修饰符
a) 抽象类:
抽象类不能用来实例化对象,声明抽象类的唯一目的是为了将来对该类进行扩充。
一个类不能同时被 abstract 和 final 修饰。如果一个类包含抽象方法,那么该类一定要声明为抽象类,否则将出现编译错误。
抽象类可以包含抽象方法和非抽象方法。
b) 抽象方法
抽象方法是一种没有任何实现的方法,该方法的的具体实现由子类提供。抽象方法不能被声明成 final 和 static。
任何继承抽象类的子类必须实现父类的所有抽象方法,除非该子类也是抽象类。
如果一个类包含若干个抽象方法,那么该类必须声明为抽象类。抽象类可以不包含抽象方法。
抽象方法的声明以分号结尾。
(4) synchronized 修饰符
synchronized 关键字声明的方法同一时间只能被一个线程访问。Synchronized 修饰符可以应用于四个访问修饰符。
(5) transient 修饰符
序列化的对象包含被 transient 修饰的实例变量时,java 虚拟机 (JVM) 跳过该特定的变量。
该修饰符包含在定义变量的语句中,用来预处理类和变量的数据类型。
(6) volatile 修饰符
volatile 修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。
一个 volatile 对象引用可能是 null。
实例:
1 class Modifier2 { 2 3 static String name = "modifier2 name"; 4 static String label = "modifier2 label"; 5 String label2 = "modifier2 label 2"; 6 7 static String getName() { 8 return name; 9 } 10 11 static String getLabel() { 12 return label; 13 //return label2; // 静态方法不能使用类的非静态变量 14 } 15 16 String getLabel2() { 17 return label2; 18 } 19 20 } 21 22 // final 修饰的 Modifier3 类不能被继承 23 final class Modifier3 extends Modifier2 { 24 25 static String label = "modifier3 label"; 26 27 // final 方法可以被子类继承,但是不能被子类重写(@Override) 28 @Override 29 final String getLabel2() { 30 return label; 31 } 32 33 } 34 35 public class App { 36 public static void main( String[] args ) { 37 Modifier3 modifier3 = new Modifier3(); 38 System.out.println("Name is: " + modifier3.getName()); 39 System.out.println("Label is: " + modifier3.getLabel()); 40 System.out.println("Label2 is: " + modifier3.getLabel2()); 41 } 42 }
输出:
Name is: modifier2 name
Label is: modifier2 label
Label2 is: modifier3 label
2. Java 运算符
计算机的最基本用途之一就是执行数学运算,作为一门计算机语言,Java也提供了一套丰富的运算符来操纵变量。
1) 算术运算符
算术运算符用在数学表达式中,它们的作用和在数学中的作用一样。下表列出了所有的算术运算符。
操作符 描述
+ 加法 - 相加运算符两侧的值
- 减法 - 左操作数减去右操作数
* 乘法 - 相乘操作符两侧的值
/ 除法 - 左操作数除以右操作数
% 取模 - 左操作数除以右操作数的余数
++ 自增 - 操作数的值增加1
-- 自减 - 操作数的值减少1
2) 关系运算符
运算符 描述
== 检查如果两个操作数的值是否相等,如果相等则条件为真。
!= 检查如果两个操作数的值是否相等,如果值不相等则条件为真。
> 检查左操作数的值是否大于右操作数的值,如果是那么条件为真。
< 检查左操作数的值是否小于右操作数的值,如果是那么条件为真。
>= 检查左操作数的值是否大于或等于右操作数的值,如果是那么条件为真。
<= 检查左操作数的值是否小于或等于右操作数的值,如果是那么条件为真。
3)位运算符
操作符 描述
& 按位与操作符,当且仅当两个操作数的某一位都非0时候结果的该位才为1。
| 按位或操作符,只要两个操作数的某一位有一个非0时候结果的该位就为1。
^ 按位异或操作符,两个操作数的某一位不相同时候结果的该位就为1。
〜 按位补运算符翻转操作数的每一位。
<< 按位左移运算符。左操作数按位左移右操作数指定的位数。
>> 按位右移运算符。左操作数按位右移右操作数指定的位数。
>>> 按位右移补零操作符。左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。
4)逻辑运算符
操作符 描述
&& 称为逻辑与运算符。当且仅当两个操作数都为真,条件才为真。
| | 称为逻辑或操作符。如果任何两个操作数任何一个为真,条件为真。
! 称为逻辑非运算符。用来反转操作数的逻辑状态。如果条件为true,则逻辑非运算符将得到false。
5)赋值运算符
操作符 描述
= 简单的赋值运算符,将右操作数的值赋给左侧操作数
+ = 加和赋值操作符,它把左操作数和右操作数相加赋值给左操作数
- = 减和赋值操作符,它把左操作数和右操作数相减赋值给左操作数
* = 乘和赋值操作符,它把左操作数和右操作数相乘赋值给左操作数
/ = 除和赋值操作符,它把左操作数和右操作数相除赋值给左操作数
%= 取模和赋值操作符,它把左操作数和右操作数取模后赋值给左操作数
<< = 左移位赋值运算符
>> = 右移位赋值运算符
&= 按位与赋值运算符
^ = 按位异或赋值操作符
| = 按位或赋值操作符
6)条件运算符(?:)
条件运算符也被称为三元运算符。该运算符有3个操作数,并且需要判断布尔表达式的值。该运算符的主要是决定哪个值应该赋值给变量。
variable x = (expression) ? value if true : value if false
7)instanceof 运算符
该运算符用于操作对象实例,检查该对象是否是一个特定类型(类类型或接口类型)。
instanceof 运算符使用格式如下:
( Object reference variable ) instanceof (class/interface type)
8)Java运算符优先级
下表中具有最高优先级的运算符在的表的最上面,最低优先级的在表的底部。
类别 | 操作符 | 关联性 |
后缀 | () [] . (点操作符) | 从左到右 |
一元 | ! + - ~ ++ -- | 从右到左 |
乘性 | * / % | 从左到右 |
加性 | + - | 从左到右 |
移位 | << >> >>> | 从左到右 |
关系 | < <= > >= instanceof | 从左到右 |
相等 | == != | 从左到右 |
按位与 | & | 从左到右 |
按位异或 | ^ | 从左到右 |
按位或 | | | 从左到右 |
逻辑与 | && | 从左到右 |
逻辑或 | || | 从左到右 |
条件 | ?: | 从左到右 |
赋值 | = += -= *= /= %= |= ^= ~= <<= >>= >>>= | 从右到左 |
逗号 | , | 从左到右 |
实例:
1 public class App { 2 public static void main( String[] args ) { 3 4 int a = 10; 5 int b = 20; 6 int c = 25; 7 int d = 25; 8 9 System.out.println("算术运算符:"); 10 System.out.println("a = " + a + ", b = " + b + ", c = " + c + ", d = " + d); 11 System.out.println("a + b = " + (a + b) ); 12 System.out.println("a - b = " + (a - b) ); 13 System.out.println("a * b = " + (a * b) ); 14 System.out.println("b / a = " + (b / a) ); 15 System.out.println("b % a = " + (b % a) ); 16 System.out.println("c % a = " + (c % a) ); 17 System.out.println("a++ = " + (a++) ); 18 System.out.println("a-- = " + (a--) ); 19 System.out.println("d++ = " + (d++) ); 20 System.out.println("d = " + d); 21 System.out.println("++d = " + (++d) ); 22 23 System.out.println("关系运算符:"); 24 System.out.println("a == b = " + (a == b) ); 25 System.out.println("a != b = " + (a != b) ); 26 System.out.println("a > b = " + (a > b) ); 27 System.out.println("a < b = " + (a < b) ); 28 System.out.println("b >= a = " + (b >= a) ); 29 System.out.println("b <= a = " + (b <= a) ); 30 31 System.out.println("位运算符:"); 32 a = 60; // 60 = 0011 1100 33 b = 13; // 13 = 0000 1101 34 c = 0; 35 System.out.println("a = " + a + ", b = " + b + ", c = " + c); 36 c = a & b; // 12 = 0000 1100 37 System.out.println("a & b = " + c ); 38 c = a | b; // 61 = 0011 1101 39 System.out.println("a | b = " + c ); 40 c = a ^ b; // 49 = 0011 0001 41 System.out.println("a ^ b = " + c ); 42 c = ~a; //-61 = 1100 0011 43 System.out.println("~a = " + c ); 44 c = a << 2; // 240 = 1111 0000 45 System.out.println("a << 2 = " + c ); 46 c = a >> 2; // 215 = 1111 47 System.out.println("a >> 2 = " + c ); 48 c = a >>> 2; // 215 = 0000 1111 49 System.out.println("a >>> 2 = " + c ); 50 51 System.out.println("逻辑运算符:"); 52 boolean x = true; 53 boolean y = false; 54 System.out.println("x = " + x + ", y = " + y ); 55 System.out.println("x && y = " + (x && y)); 56 System.out.println("x || y = " + (x || y) ); 57 System.out.println("!(x && y) = " + !(x && y)); 58 59 System.out.println("赋值运算符:"); 60 a = 10; 61 b = 20; 62 c = 0; 63 System.out.println("a = " + a + ", b = " + b + ", c = " + c); 64 c = a + b; 65 System.out.println("c = a + b = " + c ); 66 c += a ; 67 System.out.println("c += a = " + c ); 68 c -= a ; 69 System.out.println("c -= a = " + c ); 70 c *= a ; 71 System.out.println("c *= a = " + c ); 72 a = 10; 73 c = 15; 74 System.out.println("a = " + a + ", b = " + b + ", c = " + c); 75 c /= a ; 76 System.out.println("c /= a = " + c ); 77 a = 10; 78 c = 15; 79 System.out.println("a = " + a + ", b = " + b + ", c = " + c); 80 c %= a ; 81 System.out.println("c %= a = " + c ); 82 c <<= 2 ; 83 System.out.println("c <<= 2 = " + c ); 84 c >>= 2 ; 85 System.out.println("c >>= 2 = " + c ); 86 c >>= 2 ; 87 System.out.println("c >>= a = " + c ); 88 c &= a ; 89 System.out.println("c &= a = " + c ); 90 c ^= a ; 91 System.out.println("c ^= a = " + c ); 92 c |= a ; 93 System.out.println("c |= a = " + c ); 94 95 } 96 }
输出:
算术运算符:
a = 10, b = 20, c = 25, d = 25
a + b = 30
a - b = -10
a * b = 200
b / a = 2
b % a = 0
c % a = 5
a++ = 10
a-- = 11
d++ = 25
d = 26
++d = 27
关系运算符:
a == b = false
a != b = true
a > b = false
a < b = true
b >= a = true
b <= a = false
位运算符:
a = 60, b = 13, c = 0
a & b = 12
a | b = 61
a ^ b = 49
~a = -61
a << 2 = 240
a >> 2 = 15
a >>> 2 = 15
逻辑运算符:
x = true, y = false
x && y = false
x || y = true
!(x && y) = true
赋值运算符:
a = 10, b = 20, c = 0
c = a + b = 30
c += a = 40
c -= a = 30
c *= a = 300
a = 10, b = 20, c = 15
c /= a = 1
a = 10, b = 20, c = 15
c %= a = 5
c <<= 2 = 20
c >>= 2 = 5
c >>= a = 1
c &= a = 0
c ^= a = 10
c |= a = 10
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)