第7天

2023/6/15

# 第7天

今天说说什么是修饰符

# 修饰符

修饰符用于定义类、方法、变量等元素的访问权限和特性。

Java 中的修饰符主要有以下几种:

  1. 访问修饰符:用于控制类、方法、变量等元素的访问权限。Java 中有四种访问修饰符:public、protected、默认(无修饰符)和 private。
  2. 非访问修饰符:用于定义类、方法、变量等元素的特性。Java 中有几种非访问修饰符,如 static、final、abstract、synchronized、volatile 等。
  3. 注解修饰符:用于为类、方法、变量等元素添加元数据。Java 中有几种注解修饰符,如 @Override、@Deprecated、@SuppressWarnings 等。
  4. 泛型修饰符:用于定义泛型类、泛型方法、泛型接口等元素。Java 中有几种泛型修饰符,如 等。
  5. 枚举修饰符:用于定义枚举类。Java 中有几种枚举修饰符,如 enum 等。
  6. 异常修饰符:用于定义异常类。Java 中有几种异常修饰符,如 throws、throw 等。
  7. 同步修饰符:用于定义同步方法或同步代码块。Java 中有几种同步修饰符,如 synchronized 等。
  8. 其他修饰符:如 native、strictfp、transient 等。

但Java语言提供了很多修饰符,主要分为以下两类:(先记录两个)

  1. 访问修饰符
  2. 非访问修饰符

例子来说明:

public class MyClass {
    private int myPrivateVariable;
    public void myPublicMethod() {
        // ...
    }
}

# 访问修饰符

访问修饰符用于控制类、方法、变量等元素的访问权限。Java 中有四种访问修饰符:public、protected、默认(无修饰符)和 private。

  1. public:表示公共的,任何其他类都可以访问。例如,public class MyClass 表示 MyClass 类是公共的,任何其他类都可以访问它。示例访问
public class MyClass {
    public int myPublicVariable;
    public void myPublicMethod() {
        // ...
    }
}
  1. protected:表示受保护的,只有同一个包中的类和子类可以访问。例如,protected int myProtectedVariable 表示 myProtectedVariable 变量是受保护的,只有同一个包中的类和子类可以访问它。示例访问
public class MyClass {
    protected int myProtectedVariable;
    protected void myProtectedMethod() {
        // ...
    }
}
  1. 默认(无修饰符):表示默认的,只有同一个包中的类可以访问。例如,int myDefaultVariable 表示 myDefaultVariable 变量是默认的,只有同一个包中的类可以访问它。
  2. private:表示私有的,只有同一个类中的方法可以访问。例如,private void myPrivateMethod() 表示 myPrivateMethod 方法是私有的,只有同一个类中的方法可以访问它。

# 访问控制修饰符

Java 支持 4 种不同的访问权限。

default: 在同一包内可见(文件夹),不使用任何修饰符。使用对象:类、接口、变量、方法。

private:在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)

public : 对所有类可见。使用对象:类、接口、变量、方法

protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。

# 默认访问修饰符-不使用任何关键字

示例:

class AccessDefault {
    void display() {
        System.out.println("默认访问修饰符");
    }
}
public class MyClass {
    public static void main(String[] args) {
        AccessDefault obj = new AccessDefault();
        obj.display();
    }
}

输出结果:

默认访问修饰符

# 私有访问修饰符-private

私有访问修饰符是最严格的访问级别,所以被声明为 private 的变量、方法和构造器只能被所属类访问,并且类和接口不能声明为 private。

示例:

public class AccessPrivate {
    private String name = "哪吒";

    private void display() {
        System.out.println("私有访问修饰符");
    }
}
public class MyClass {
    public static void main(String[] args) {
        AccessPrivate obj = new AccessPrivate();
        //obj.display(); //编译错误
        //System.out.println(obj.name); //编译错误
    }
}

# 公共访问修饰符-public

被声明为 public 的类、方法、构造器和接口都能被任何其他类访问。

示例:

public class AccessPublic {
    public String name = "哪吒";

    public void display() {
        System.out.println("公共访问修饰符");
    }
}

# protected

protected 对同一个包内的类和所有子类可见。

示例:

public class AccessProtected {
    protected String name = "哪吒";

    protected void display() {
        System.out.println("受保护的访问修饰符");
    }
}
public class MyClass {
    public static void main(String[] args) {
        AccessProtected obj = new AccessProtected();
        //obj.display(); //编译错误
        //System.out.println(obj.name); //编译错误
    }
}

# 访问控制和继承

  • 当子类继承父类时,子类可以继承父类的 public 和 protected 成员,但不能继承父类的 private 成员。如果子类和父类不在同一个包中,子类只能继承父类的 public 成员。
  • 父类中声明为 public 的方法在子类中也必须为 public。
  • 父类中声明为 protected 的方法在子类中要么声明为 protected,要么声明为 public,不能声明为 private。
  • 父类中声明为 private 的方法,不能够被子类继承。

# 非访问修饰符

非访问修饰符用于定义类、方法、变量等元素的特性。Java 中有几种非访问修饰符,如 static、final、abstract、synchronized、volatile 等。

  1. static: 表示静态的,用于定义静态变量、静态方法和静态代码块。静态变量和方法属于类,而不是某个具体的对象。静态变量在类加载时初始化,并且只有一个副本。静态方法不能访问非静态变量和方法,只能访问静态变量和方法。
  2. final: 表示最终的,用于定义常量、方法和类。常量一旦被初始化,就不能再被修改。方法被声明为 final,就不能被重写。类被声明为 final,就不能被继承。
  3. abstract: 表示抽象的,用于定义抽象类和抽象方法。抽象类不能被实例化,只能被继承。抽象方法没有方法体,必须在子类中实现。
  4. synchronized: 表示同步的,用于定义同步方法或同步代码块。同步方法或代码块在同一时间只能被一个线程访问,以保证线程安全。
  5. volatile: 表示易变的,用于定义易变变量。易变变量可以被多个线程同时访问和修改,并且每次访问时都会从主内存中读取最新的值,而不是从线程的本地缓存中读取。
  6. transient: 表示瞬态的,用于定义瞬态变量。瞬态变量在序列化时不会被保存,即不会被写入到序列化文件中。
  7. native: 表示本地的,用于定义本地方法。本地方法是用其他语言(如 C 或 C++)编写的,并且不能在 Java 中实现。
  8. strictfp: 表示严格浮点,用于定义严格浮点计算的方法或类。严格浮点计算遵循 IEEE 754 标准,以保证计算结果的一致性。

简单易懂:

  1. static 修饰符,用来修饰类方法和类变量。
  2. final 修饰符,用来修饰类、方法和变量,final 修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的。
  3. abstract 修饰符,用来创建抽象类和抽象方法。
  4. synchronized 和 volatile 修饰符,主要用于线程的编程。

# 静态变量:

static 关键字用来声明独立于对象的静态变量,无论一个类实例化多少对象,它的静态变量只有一份拷贝。 静态变量也被称为类变量。局部变量不能被声明为 static 变量。

# 静态方法:

static 关键字用来声明独立于对象的静态方法。静态方法不能使用类的非静态变量。静态方法从参数列表得到数据,然后计算这些数据。

# static 修饰符用来创建类方法和类变量

示例:

public class MyClass {
    static int myStaticVariable = 10;

    static void myStaticMethod() {
        System.out.println("静态方法");
    }

    public static void main(String[] args) {
        MyClass.myStaticMethod();
        System.out.println(MyClass.myStaticVariable);
    }
}

输出结果:

静态方法
10

# final 修饰符

示例:

public class MyClass {
    final int myFinalVariable = 10;

    final void myFinalMethod() {
        System.out.println("final 方法");
    }

    public static void main(String[] args) {
        MyClass obj = new MyClass();
        //obj.myFinalVariable = 20; //编译错误
        //obj.myFinalMethod(); //编译错误
    }
}

输出结果:

final 方法

# abstract 修饰符

示例:

public abstract class MyClass {
    abstract void myAbstractMethod();
}

输出结果:

abstract 方法
abstract class Caravan{
   private double price;
   private String model;
   private String year;
   public abstract void goFast(); //抽象方法
   public abstract void changeColor();
}
public abstract class SuperClass{
    abstract void m(); //抽象方法
}
 
class SubClass extends SuperClass{
     //实现抽象方法
      void m(){
          .........
      }
}

# synchronized 修饰符

synchronized 关键字声明的方法同一时间只能被一个线程访问。synchronized 修饰符可以应用于四个访问修饰符。

示例:

public class MyClass {
    synchronized void mySynchronizedMethod() {
        System.out.println("同步方法");
    }

    public static void main(String[] args) {
        MyClass obj = new MyClass();
        obj.mySynchronizedMethod();
    }
}

输出结果:

同步方法

# volatile 修饰符

volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。而且,当成员变量发生变化时,会强制线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。

一个 volatile 对象引用可能是 null。

示例:

public class MyClass {
    volatile boolean myVolatileVariable = true;

    public static void main(String[] args) {
        MyClass obj = new MyClass();
        //obj.myVolatileVariable = false; //编译错误
    }
}

输出结果:

volatile 变