读者可订阅专栏:Java开发指南 |【CSDN@秋说】
文章目录
- JAVA修饰符
- 访问修饰符
- 非访问修饰符
- static 修饰符
- final 修饰符
- abstract 修饰符
- synchronized 修饰符
- transient 修饰符
- volatile 修饰符
JAVA修饰符
修饰符用来定义类、方法或者变量,通常放在语句的最前端。
访问修饰符
default
如果在类、变量、方法或构造函数的定义中没有指定任何访问修饰符,那么它们就默认具有默认访问修饰符。
默认访问修饰符的访问级别是包级别(package-level),即只能被同一包中的其他类访问。
class A{
int a=10;
}
public class Ice{
public static void main(String[] args){
A ii = new A();
System.out.println(ii.a);
}
}
private
声明为私有访问类型的变量只能通过类中公共的 getter 方法被外部类访问。
class A {
private int a = 10; // 将变量声明为私有访问类型
// 公共的 getter 方法用于访问私有变量
public int getA() {
return a;
}
}
public class Ice {
public static void main(String[] args) {
A ii = new A();
// 通过公共的 getter 方法访问私有变量
System.out.println(ii.getA());
}
}
在类 Ice
的 main
方法中尝试直接访问了类 A
中的私有成员变量 a
,而没有使用公共方法,导致报错:
class A {
private int a = 10; // 将变量声明为私有访问类型
}
}
public class Ice {
public static void main(String[] args) {
A ii = new A();
System.out.println(ii.a);
}
}
public
被声明为 public 的类、方法、构造方法和接口能够被任何其他类访问。
package ice;
public class a{
public int aa;
public a(){
this.aa=10;
}
public void aaa(){
System.out.println("A");
}
}
package ice;
//访问a类
public class Ice{
public static void main(String[] args)
{
ice.a obj = new ice.a();
System.out.println(obj.aa);
obj.aaa();
}
}
protected
protected 需要从以下两个点来分析说明:
- 子类与基类在同一包中:被声明为 protected 的变量、方法和构造器能被同一个包中的任何其他类访问;
- 子类与基类不在同一包中:那么在子类中,子类实例可以访问其从基类继承而来的 protected 方法,而不能访问基类实例的protected方法。
举例:
假设我们有一个基类 Base
和一个子类 Subclass
,它们都在同一个包 example
中。
Base.java:
package example;
public class Base {
protected int protectedVariable;
protected void protectedMethod() {
System.out.println("This is a protected method.");
}
}
Subclass.java:
package example;
public class Subclass extends Base {
public void accessProtectedMember() {
// 在同一包中,子类可以直接访问基类的 protected 成员
protectedVariable = 10;
System.out.println("protectedVariable value set by subclass: " + protectedVariable);
protectedMethod();
}
}
在这个例子中,Subclass
类继承自 Base
类。由于它们在同一个包中,Subclass
类可以直接访问 Base
类中被声明为 protected
的变量和方法。
现在假设我们将 Subclass
类移到一个不同的包 anotherpackage
中。
Subclass.java:
package anotherpackage;
import example.Base;
public class Subclass extends Base {
public void accessProtectedMember() {
// 子类实例可以访问其从基类继承而来的 protected 变量和方法
protectedVariable = 10;
System.out.println("protectedVariable value set by subclass: " + protectedVariable);
protectedMethod();
}
}
在这个例子中,Subclass
类仍然继承自 Base
类。尽管它们不在同一个包中,但是Subclass
类可以访问 Base
类中被声明为 protected
的变量和方法,因为 protected
访问修饰符允许子类访问其继承的成员。
注意:
- protected 可以修饰数据成员,构造方法,方法成员,不能修饰类(内部类除外)。
- 接口及接口的成员变量和成员方法不能声明为 protected。
修饰符 | 当前类 | 同一包内 | 子孙类(同一包) | 子孙类(不同包) | 其他包 |
---|---|---|---|---|---|
public | Y | Y | Y | Y | Y |
protected | Y | Y | Y | Y/N | N |
default | Y | Y | Y | N | N |
private | Y | N | N | N | N |
非访问修饰符
static 修饰符
-
静态变量:
static 关键字用来声明独立于对象的静态变量,无论一个类实例化多少对象,它的静态变量只有一份拷贝。 静态变量也被称为类变量。局部变量不能被声明为 static 变量。
public class ice {
// 静态变量
public static int staticVariable = 10;
public static void main(String[] args) {
// 通过类名直接访问静态变量
System.out.println("Static variable value: " + ice.staticVariable);
}
}
-
静态方法:
static 关键字用来声明独立于对象的静态方法。静态方法不能使用类的非静态变量。静态方法从参数列表得到数据,然后计算这些数据。
public class ice {
// 静态方法
public static void staticMethod() {
System.out.println("This is a static method.");
}
public static void main(String[] args) {
// 调用静态方法
ice.staticMethod();
// 通过对象实例调用静态方法(不推荐,因为静态方法与对象实例无关)
ice obj = new ice();
obj.staticMethod();
}
}
final 修饰符
final 变量:
final 表示"最后的、最终的"含义,变量一旦赋值后,不能被重新赋值。被 final 修饰的实例变量必须显式指定初始值。
public class ice {
// final变量,一旦赋值就不能被修改
final int finalVariable = 10;
public static void main(String[] args) {
ice obj = new ice();
// final变量的值不能被修改,否则会编译错误
// obj.finalVariable = 20;
System.out.println("Final variable value: " + obj.finalVariable);
}
}
如图:
final 方法
父类中的 final 方法可以被子类继承,但是不能被子类重写。
声明 final 方法的主要目的是防止该方法的内容被修改。
public class Parent {
// final方法,子类不能重写该方法
public final void finalMethod() {
System.out.println("This is a final method.");
}
}
public class Child extends Parent {
// 尝试重写final方法会导致编译错误
/*
@Override
public void finalMethod() {
System.out.println("Trying to override final method.");
}
*/
public static void main(String[] args) {
Child obj = new Child();
obj.finalMethod();
}
}
final 类
final 类不能被继承,没有类能够继承 final 类的任何特性。
// final类,不能被继承
final public class ice {
public void display() {
System.out.println("This is a final class.");
}
public static void main(String[] args) {
ice obj = new ice();
obj.display();
}
}
abstract 修饰符
抽象类:
抽象类不能用来实例化对象,声明抽象类的唯一目的是为了将来对该类进行扩充。
一个类不能同时被 abstract 和 final 修饰。如果一个类包含抽象方法,那么该类一定要声明为抽象类,否则将出现编译错误。
抽象类可以包含抽象方法和非抽象方法。
抽象方法
抽象方法是一种没有任何实现的方法,该方法的具体实现由子类提供。
规则如下:
-
抽象方法不能被声明成 final 和 static。
-
任何继承抽象类的子类必须实现父类的所有抽象方法,除非该子类也是抽象类。
abstract class Animal {
// 抽象方法,动物发出声音
abstract void makeSound();
}
class Dog extends Animal {
// Dog类没有实现父类的抽象方法
}
public class ice {
public static void main(String[] args) {
// 尝试实例化Dog类,但由于没有实现抽象方法,会导致编译错误
Dog dog = new Dog();
}
}
- 如果一个类包含若干个抽象方法,那么该类必须声明为抽象类。抽象类可以不包含抽象方法。
Shape类包含了一个抽象方法,所以它必须为抽象类:
- 抽象方法的声明以分号结尾,例如:public abstract sample();。
synchronized 修饰符
在 Java 中,synchronized 修饰符用于确保多个线程访问共享资源时的同步性。当一个方法或者一个代码块被 synchronized 修饰时,它只能被一个线程访问,其他线程需要等待直到该线程执行完毕释放锁。这样可以防止多个线程同时访问共享资源而导致的数据不一致或者并发问题。
例如:
public synchronized void synchronizedMethod() {
// 同步的方法体
}
public void someMethod() {
synchronized(this) {
// 同步的代码块
}
}
transient 修饰符
在 Java 中,当对象需要被序列化为字节流以便存储或者传输时,使用 transient 关键字可以标记某些不需要被序列化的成员变量,这样可以提高序列化的效率,也可以保护一些敏感信息不被序列化。
例如:
public class MyClass implements Serializable {
private transient int sensitiveData; // 这个成员变量不会被序列化
private int normalData; // 这个成员变量会被序列化
}
volatile 修饰符
volatile 修饰符用于声明一个变量是“易变”的。在 Java 中,当一个变量被 volatile 修饰时,它的值会立即被写入主内存,并且对其他线程可见。这样可以确保多个线程对该变量的读写操作是同步的,从而避免了由于多线程之间的可见性问题而导致的数据不一致性。
例如:
public class SharedResource {
private volatile int count;
public void increment() {
count++;
}
public int getCount() {
return count;
}
}
如果没有将 count
变量声明为 volatile
,则在多线程环境中,一个线程对 count
的修改可能不会立即被其他线程看到,导致不一致的结果。而使用了 volatile
关键字,则可以确保每次读取 count
都能得到最新的值。