首页 > 技术文章 > 修饰符

endless-process 2021-09-27 22:30 原文

修饰符

1.static修饰符

1.static变量

在类中,使用static修饰的成员变量,就是静态变量,反之为非静态变量。

静态变量和非静态变量的区别

静态变量属于类的,"可以"使用类名来访问,非静态变量是属于对象的,"必须"使用对象来访问.

静态变量对于类而言在内存中只有一个,能被类的所有实例所共享。实例变量对于类的每个实例都有一份,
它们之间互不影响.

在加载类的过程中为静态变量分配内存,实例变量在创建对象时分配内存,所以静态变量可以使用类名来
直接访问,而不需要使用对象来访问.

2.static方法

在类中,使用static修饰的成员方法,就是静态方法,反之为非静态方法。
静态方法和非静态方法的区别

静态方法数属于类的, "可以"使用类名来调用, 非静态方法是属于对象的, "必须"使用对象来调用.

静态方法"不可以"直接访问类中的非静态变量和非静态方法,但是"可以"直接访问类中的静态变量和静态
方法
注意:this和super在类中属于非静态的变量.(静态方法中不能使用)

非静态方法"可以"直接访问类中的非静态变量和非静态方法,也"可以"直接访问类中的静态变量和静态方

父类的静态方法可以被子类继承,但是不能被子类重写

父类的非静态方法不能被子类重写为静态方法 ;

3.代码块和静态代码块

【类中可以编写代码块和静态代码块】

package com.oop.Demo4;

public class Demo4 {
    {
        System.out.println("匿名代码块");
    }
    static {
        System.out.println("静态代码块");
    }
    public Demo4(){
        System.out.println("构造器");
    }

    public static void main(String[] args) {
        Demo4 demo4 = new Demo4();
        System.out.println("=========");
        //静态代码块只执行一次
        Demo4 demo41 = new Demo4();
    }
}

【匿名代码块和静态代码块的执行】

因为没有名字,在程序并不能主动调用这些代码块。

匿名代码块是在创建对象的时候自动执行的,并且在构造器执行之前。同时匿名代码块在每次创建对象的
时候都会自动执行.

静态代码块是在类加载完成之后就自动执行,并且只执行一次.

注:每个类在第一次被使用的时候就会被加载,并且一般只会加载一次.

【匿名代码块和静态代码块的作用】

匿名代码块的作用是给对象的成员变量初始化赋值,但是因为构造器也能完成这项工作,所以匿名代码块
使用的并不多。

静态代码块的作用是给类中的静态成员变量初始化赋值。

注:在构造器中给静态变量赋值,并不能保证能赋值成功,因为构造器是在创建对象的时候才指向,但是静
态变量可以不创建对象而直接使用类名来访问.

4.创建和初始化对象的过程

Student s = new Student() ;

【Student类之前没有进行类加载】
1.类加载,同时初始化类中静态的属性
2.执行静态代码块
3.分配内存空间,同时初始化非静态的属性(赋默认值,0/false/null)
4.调用Student的父类构造器
5.对Student中的属性进行显示赋值(如果有的话)
6.执行匿名代码块
7.执行构造器
8.返回内存地址
注:子类中非静态属性的显示赋值是在父类构造器执行完之后和子类中的匿名代码块执行之前的时候

5.静态导入

静态导包就是java包的静态导入,用import static代替import静态导入包是JDK1.5中的新特性。
意思是导入这个类里的静态方法。

好处:这种方法的好处就是可以简化一些操作,例如打印操作System.out.println(…);就可以将其写入一
个静态方法print(…),在使用时直接print(…)就可以了。

但是这种方法建议在有很多重复调用的时候使用,如果仅有一到两次调用,不如直接写来的方便。

2.final修饰符

1.修饰类

用final修饰的类不能被继承,没有子类。

例如:我们是无法写一个类去继承String类,然后对String类型扩展的,因为API中已经被String类定义为final
的了.

2.修饰方法

用final修饰的方法可以被继承,但是不能被子类的重写。

例如:每个类都是Object类的子类,继承了Object中的众多方法,在子类中可以重写toString方法、 equals方
法等,但是不能重写getClass方法 wait方法等,因为这些方法都是使用fianl修饰的。

3.修饰变量

用final修饰的变量表示常量,只能被赋一次值.其实使用final修饰的变量也就成了常量了,因为值不会再变
了。

【修饰局部变量】

public class Person{
public void print(final int a) {
//编译报错, 不能再次赋值, 传参的时候已经赋过了
a = 1;
	}
}
	public class Person{
		public void print() {
			final int a;
				a = 1;
		//编译报错, 不能再次赋值
				a = 2;
	}
}

【修饰成员变量-非静态成员变量】

public class Person{
private final int a;
}
只有一次机会, 可以给此变量a赋值的位置:
声明的同时赋值
匿名代码块中赋值
构造器中赋值(类中出现的所有构造器都要写)

【修饰成员变量-静态成员变量】

public class Person{
private static final int a;
}
只有一次机会, 可以给此变量a赋值的位置:
声明的同时赋值
静态代码块中赋值

【修饰引用变量】

main:
final Student s = new Student() ;
//编译通过
s.setName("tom") ;
s.setName("zs") ;
//编译报错, 不能修改引 用s指向的内存地址
s = new Student() ;

3.abstract修饰符

abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那
么该类就是抽象类。

1. 抽象类和抽象方法的关系

抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。

2. 语法

public abstract class Action{
public abstract void doSomething() ;
}
public void doSomething() {. . . }

对于这个普通方法来讲:
"public void doSomething()"这部分是方法的声明
"{...}"这部分是方法的实现,如果大括号中什么都没写,就叫方法的空实现
声明类的同时,加上abstract修饰符就是抽象类
声明方法的时候,加上abstract修饰符,并且去掉方法的大口号,同时结尾加上分号,该方法就是抽象方法。

3. 特点及作用

抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。

抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。

注:子类继承抽象类后,需要实现抽象类中没有实现的抽象方法,否则这个子类也要声明为抽象类。

4. 思考

思考1 : 抽象类不能new对象,那么抽象类中有没有构造器?

	抽象类是不能被实例化, 抽象类的目 的就是为实现多态中的共同点, 抽象类的构造器会在子类实例化时调用, 因此它也是用来实现多态中的共同点构造, 不建议这样使用!

思考2 : 抽象类和抽象方法意义(为什么要编写抽象类、抽象方法)

打个比方,要做一个游戏。如果要创建一个角色,如果反复创建类和方法会很繁琐和麻烦。 建一个抽象类后。若要创建角色可直接继承抽象类中的字段和方法,而抽象类中又有抽象方法。如果一个角色有很多种职业,每个职业又有很多技能,要是依次实例这些技能方法会显得想当笨拙。 定义抽象方法,在需要时继承后重写调用,可以省去很多代码。
总之抽象类和抽象方法起到一个框架作用。 很方便后期的调用和重写
抽象方法是为了程序的可扩展性。 重写抽象方法时即可实现同名方法但又非同目的的要求。

推荐阅读