Loading

Java语言中的修饰符

Java语言中的修饰符

修饰符 成员方法 构造方法 成员变量 局部变量
abstract
static
public
protected(受保护的)
private(私有的)
synchronized(同步的)
native(本地的)
transient(暂时的)
volatile(易失的)
final(不可改变)
  • 修饰顶层:abstract public final(static protected private不能)
  • 成员方法和成员变量可以有多种修饰符,局部变量只能用final修饰

7.1 访问控制修饰符

访问级别 访问控制修饰符 同类 同包 子类 不同的包
公开 Public
受保护 Protected
默认 没有访问控制修饰符
私有 Private

7.2 abstract修饰符

abstract修饰符可用来修饰类和成员方法:

  • 用abstract修饰的类表示抽象类,抽象类位于继承树的抽象层,抽象类不能被实例化,即不允许创建抽象类本身的实例。没有用abstract修饰的类称为具体类,具体类可以被实例化。
  • 用abstract修饰的方法表示抽象方法,抽象方法没有方法体。抽象方法用来描述系统具有什么功能,但不提供具体的实现。没有用abstract修饰的方法称为具体方法,具体方法具有方法体。

使用abstarct修饰符需要遵循以下语法规则:

  1. 抽象类中可以没有抽象方法,但包含了抽象方法的类必须被定义为抽象类。如果子类没有实现父类中所有的抽象方法,那么子类也必须定义为抽象类,否则编译出错。例如,以下代码中Sub类继承了Base类,但Sub类仅实现了Base类中的method1()抽象方法,而没有实现method2()抽象方法,因此Sub类必须声明为抽象类,否则编译出错:
abstract class Base{
    abstract void method1();
    abstract void method2();
}
//编译出错,Sub必须声明为抽象类
Class Sub extends Base{
    void method1(){
        System.out.println("method1")
    }
}
  1. 没有抽象静态方法
abstract class Base{
	static abstract void method10;//编译出错,static和abstract修饰符不能连用
	static void method2(){···}//合法,抽象类中可以有静态方法
}    
  1. 抽象类中可以有非抽象的构造方法,创建子类的实例时可能会调用这些构造方法,关于父类构造方法的调用规则参见本书第11章的11.2.3节(子类调用父类的构造方法)。抽象类不能被实例化,然而可以创建一个引用变量,其类型是一个抽象类,并让它引用非抽象的子类的一个实例。例如:
abstract class Base{}
class Sub extends Base{
    public static void main(String[] args) {
        Base base1 = new Base();//错误:Base是抽象的; 无法实例化
        Base base2 = new Sub();
    }
}
  1. 抽象类及抽象方法不能被final修饰符修饰。abstract修饰符与final修饰符不能连用,因为抽象类只有允许创建其子类,它的抽象方法才能被实现,并且只有它的具体子类才能被实例化,而用final修饰的类不允许拥有子类,用final修饰的方法不允许被子类方法覆盖,两此把abstract修饰符与final修饰符连用,会导致自相矛盾。
  2. 抽象方法不能被private修饰符修饰。这是因为如果方法是抽象的,表示父类只声明具备某种功能,但没有提供实现。这种方法有待于某个子类去实现它。则abstract必须可见。假如Java允许把父类的方法同时用abstract和private修饰,那就意味着在父类中声明一个永远无法实现的方法,所以在Java中不允许出现这一情况。

7.3 final修饰符

final具有“不可改变的”的含义,它可以修饰非抽象类、非抽象成员方法和变量:

  • 用final修饰的类不能被继承,没有子类。
  • 用final修饰的方法不能被子类的方法覆盖。
  • 用final修饰的变量表示常量,只能被赋一次值。

final不能用来修饰构造方法,因为“方法覆盖”这一概念仅适用于类的成员方法,而不适用于类的构造方法,父类的构造方法和子类构造方法之间不存在覆盖关系,因此private类型的方法默认为final

7.3.1 final类

在第6章的6.7.3节(继承关系的最大弱点:打破封装)曾经指出,继承关系的弱点是打破封装,子类能够

访问父类的实现细节,而且能以方法覆盖的方式修改实现细节。在以下情况,可以考虑把类定义为final类型,使得这个类不能被继承:

  • 不是专门为继承而设计的类,类本身的方法之间有复杂的调用关系。假如随意创建这些类的子类,子类有可能会错误地修改父类的实现细节。
  • 出于安全的原因,类的实现细节不允许有任何改动。
  • 在创建对象模型时,确信这个类不会再被扩展。

7.3.2 final方法

在某些情况下,出于安全的原因,父类不允许子类覆盖某个方法,此时可以把这个方法声明为final类型。

7.3.3 final 变量

用final修饰的变量表示取值不会改变的常量。final变量具有以下特征:

  1. final修饰符可以修饰静态变量实例变量局部变量,分别表示静态常量、实例常量和局部常量。例如,某个中学的学生都有出生日期、姓名和年龄这些属性,其中学生的出生日期永远不会改变,姓名有可能改变,年龄每年都会变化。此外,该中学在招收学生时,对学生的年龄做了限制,只会招收年龄在10~23岁的学生。以下
    是Student类的源程序,其中学生的最大年龄及最小年龄为静态常量,学生的出生日期为实例常量。
  2. final类型的变量都必须显式初始化
  3. final变量只能赋一次值。例如,以下程序代码试图给var1实例常量和var局部常量赋两次值,并且试图改变final类型的参数param的值,这会导致编译错误:
public class Sample{
	private final int varl=1;//定义并初始化varl实例常量
	public Sample(){
		varl=2;//编译出错,不允许改变varl实例常量的值
		public void method(final int param){
			final int var2=1;//定义并初始化var2局部常量
			var2++;//编译出错,不允许改变var2局部常量的值
			param++;//编译出错,不允许改变final类型参数的值
        }
    } 
}    
  1. 如果将引用类型的变量用final修饰,那么该变量只能始终引用一个对象,但可以改变对象的内容,例如:
public class Sample{
    public int var;
    public Sample(int var){
        this.var = var;
    }
    public static void main(String args[]) {
        final Sample s = new Sample(1);
        //合法,定义并初始化 final类型的引用变量s
        s.var = 2;
        //合法,修改引用变量s所引用的Sample对象的var属性
        s = new Sample(2);
        //编译出错,不能改变引用变量s所引用的Sample对象
    }
}

7.4 static 修饰符

static修饰符可以用来修饰类的成员变量、成员方法和代码块:

  • 用static修饰的成员变量表示静态变量,可以直接通过类名来访问。
  • 用static修饰的成员方法表示静态方法,可以直接通过类名来访问。
  • 用static修饰的程序代码块表示静态代码块,当Java虚拟机加载类时,就会执行该代码块。

7.4.1 static 变量

  • 类的成员变量有两种:一种是被static修饰的变量,叫类变量,或静态变量;一种是没有被static修饰的变量,叫实例变量

  • 在类的内部,可以在任何方法内直接访问静态变量;在其他类中,可以通过某个
    类的类名来访问它的静态变量。

  • static变量在某种程度上与其他语言(如C语言)中的全局变量相似。Java语言不支持不属于任何类的全局变量,静态变量提供了这一功能,它有两个作用:

    • 能被类的所有实例共享,可作为实例之间进行交流的共享数据。

    • 如果类的所有实例都包含一个相同的常量属性,可把这个属性定义为静态常量类型,从而节省内存空间。例如某种类型的变压器Transformer类,它所接受的最小输入电压为110V,最大输入电压为220V,输出电压为15V,这是对所有变压器Transformer对象适用的属性,可在Transformer类中按如下方式定义它们:

      static final int MAX INPUT VOLTAGE=220;
      static final int MIN_INPUT_VOLTAGE=110;
      static final int OUTPUT_VOLTAGE=15;
      

7.4.2 staic方法

成员方法分为静态方法和实例方法。用static修饰的方法叫静态方法或类方法。青态方法也和静态变量一样,不需创建类的实例,可以直接通过类名来访问.

7.4.3 static 代码块

类中可以包含静态代码块,它不存在于任何方法体中。Java虚拟机加载类时,会执行这些静态代码块。如果类中包含多个静态块,那么Java虚拟机按它们在类中出现的顺序依次执行它们,每个静态代码块只会被执行一次。例如以下Sample类中包含两个静态代码块。运行Sample类的main()方法时,Java虚拟机首先加载Sample类,在加载的过程中依次执行两个静态代码块。Java虚拟机机载Sample类后,再执行main()方法:

7.4.4 用 static 进行静态导入

从JDK5开始引入了静态导入语法(import static),其目的是为了在需要经常访问同一个类的方法或成员变量的场合,简化程序代码。

7.5 小结

  1. 访问控制修饰符
    • public的访问级别最高,其次是protected、默认和private。
    • 成员变量和成员方法可以处于4个访问级别中的一个:公开、受保护、默认或私有。
    • 顶层类可以处于公开或默认级别,顶层类不能被protected和private修饰。
    • 局部变量不能被访问控制修饰符修饰。
  2. abstract修饰符
    • 抽象类不能被实例化
    • 抽象类中可以没有抽象方法,但包含抽象方法的类必须为抽象方法
    • 如果子类没有实现父类中所有的抽象方法,则子类也必须定义为抽象类
    • 抽象类不能定义为final和static类型
    • 抽象方法不能定义为private,final,static类型
    • 没有抽象构造方法
    • 抽象方法没有方法体
  3. final修饰符
    • 用final修饰的类不能被继承。
    • 用final修饰的方法不能被子类的方法覆盖。
    • private类型的方法都默认为final方法,因而不能被子类的方法覆盖。
    • final类型的变量必须被显式初始化,并且只能被赋一次值。
  4. static修饰符
    • 静态变量在内存中只有一个备份,在类的所有实例中共享。
    • 在静态方法中不能直接访问实例方法和实例变量。
    • 静态方法中不能使用this和super关键字。
    • 静态方法不能被 abstract 修饰。
    • 静态方法和静态变量都可以通过类名直接被访问。
    • 当类被加载时,静态代码块只被执行一次。类中不同的静态代码块按它们在类中出现的顺序被依次执行。
posted @ 2023-09-11 11:00  AmorFati404  阅读(65)  评论(0)    收藏  举报