Java中的static、final、abstract含义及使用方法

一、static、final、abstract三者的使用场景与注意事项

    static关键字可用于修饰成员变量和成员函数,想要实现对象中的共性数据的对象共享,可以将这个数据进行静态修饰,被静态修饰的成员可以直接被类名调用,静态随着类的加载而加载,而且优先于对象存在。静态方法只能访问静态成员(静态方法和静态变量),不可以访问非静态成员,这是因为静态方法加载时,优先于对象存在,所以没有办法访问对象中的成员。

    静态方法中不能使用this和super关键字,因为this代表本类对象,super代表父类对象,而静态内容执行时,有可能因为对象内容不存在(如对象还未创建),所以this和super无法使用。

    final关键字可用于修饰类,方法,变量(成员变量内,局部变量,静态变量),被final修饰的类是一个最终类,不可以被继承。被final修饰的方法是一个最终方法,不可以被覆盖,但是可以被继承。被final修饰的变量只能是一个常量,只能赋值一次。内部类被定义在类中的局部位置上时,只能访问局部被final修饰的局部变量。

    abstract关键字只能用于修饰类和方法,不能修饰变量。抽象方法只能定义在抽象类中,抽象方法和抽象类必须由abstract修饰,抽象方法只定义方法声明,不定义方法实现。抽象类不可以被实例化(创建对象),只有通过子类继承抽象类并覆盖抽象类中的所有抽象方法后,该子类才可以被实例化,否则该子类还是一个抽象类。抽象类中有构造函数用于给子类对象进行初始化,同时抽象类中可以含有非抽象方法。

    注意事项:abstract关键字不可以与final、private、static关键字共存,因为被final修饰的方法不可以被重写,意味着子类不可以重写该方法,如果abstract和final共同修饰父类中的方法,子类要实现抽象方法(abstract的作用),而final又不让该方法重写,这相互矛盾。如果private和abstract共同修饰父类中的方法,private修饰则该方法不可以被子类访问,但是abstract修饰需要子类去实现,两者产生矛盾。如果static和abstract共同修饰父类中的方法,static表示是静态的方法,随着类的加载而加载,则该方法不需要在子类中去实现,这与abstract关键字矛盾。

二、static 修饰属性、方法和代码块

    1.static修饰属性

    这个属性就可以用“类名.属性名”来访问,也就是使这个属性成为本类的类变量,为本类对象所共有。这个属性就是全类公有。类加载的过程,类本身保存在文件中(字节码文件保存着类的信息)的,java会通过I/O流把类的文件(字节码文件)读入JVM(java虚拟机),这个过程称为类的加载过程。

    JVM(java虚拟机)会通过类路径(CLASSPATH)来找字节码文件。

    类变量,会在加载时自动初始化,初始化规则和实例变量相同。

    注意:

    类中的实例变量是在创建对象时被初始化的,被static修饰的属性(类变量),是在类加载时被创建并进行初始化,类加载的过程是进行一次。也就是类变量只会被创建一次。

    2.static修饰方法(静态方法)

    static在这种情况下会使这个方法成为整个类所公有的方法,可以用“类名.方法名”访问。

    "类名.属性名"以及"类名.方法"访问举例: 

/**
 * 文件名:StaticTest.java
 * 功能描述:static修饰符的测试类
 */
class StaticTest{
    private static int count = 0 ;//用于统计实例化了多少个本类的对象
    public StaticTest(){
        count ++;
        System.out.printf("正在实例化第%d个对象……\n",count);
    }

    public static void show() {
        System.out.println("count="+count);
    }
}

    测试类 :

public class MyTest{
    public static void main(String args[]){
        //1、通过类名调用静态方法,通过类名调用静态成员变量或静态成员方法并不会实例化对象
        StaticTest.show();
        StaticTest.show();

        System.out.println("-------------------------");

        //2、通过对象调用静态方法
        StaticTest myTest1 = new StaticTest();
        myTest1.show();
        StaticTest myTest2 = new StaticTest();
        myTest2.show();

        StaticTest.show();
    }
}

注意:

    (1)static修饰的方法,不直接能访问本类中的非静态(static)成员(包括方法和属性),本类的非静态方法可以访问本类的静态成员(包括方法和属性)静态方法要慎重使用(原因是静态变量会一直存在,占用资源),且在静态方法中不能出现this关键字。

    (2)父类中是静态方法,子类中不能覆盖为非静态方法;在符合覆盖规则的前提下,在父子类中,父类中的静态方法可以被子类中的静态方法覆盖,但无多态。(在使用对象调用静态方法时,实则是调用编译时类型的静态方法)

    (3)父子类中,静态方法只能被静态方法覆盖,父子类中,非静态方法只能被非静态方法覆盖。

   例:java中的main方法必须写成static的,因为在类加载时无法创建对象,静态方法可以不通过对象调用所以在类的main方法。

    所在在类加载时就可以通过main方法入口来运行程序。

    3.static修饰初始代码块

    由static修饰的代码块就叫做静态初始代码块,该代码块只在类加载时被执行一次。

    通常情况我们初始代码块,写在类体中的“{}”,这个代码块是在生成对象的初始化属性时运行,这种代码块叫动态初始代码块。

    也可以用静态初始代码块初始化一个类,如:

    类在什么时候会被加载,创建对象时会加载类,调用类中静态方法或访问静态属性也是会加载类的。在加载子类时必会先加载父类,类加载会有延迟加载原则,只有在必须加载时才会加载。

三、final修饰变量、方法和类

    1.final修饰变量

    变量被final修饰,就会变成常量(常量应大写),一旦赋值不能改变(可以在初始化时直接赋值,也可以在构造方法里也可以赋值,只能在这两种方法里二选一,必须为常量赋值);final的常量不会有默认初始值,对于直接在初始化是赋值时final修饰符常和static修饰符一起使用。

    2.final修饰方法

    被final修饰的方法将不能被其子类覆盖,保持方法的稳定不能被覆盖。

    3.final修饰类

    被final修饰的类将不能被继承。final类中的方法也都是final的。

    注意一:

    final,不能用来修饰构造方法,在父类中如果有常量属性,在子类中使用常量属性时是不会进行父类的类加载。

    对象一旦创建属性就不会改变。用final修饰属性,也用final修饰类(强不变模式),用final修饰属性(弱不变模式)。

    如:java.lang.String类,不变模式可以实现对象的共享(可以用一个对象实例赋值给多个对象变量)池化的思想,把需要共享的数据放在池中(节省资源空间,共享数据)

    注意二:

    只有String类可以用“”中的字面值创建对象。在String类中,以字面值创建时,会到Java方法空间的串池空间中去查找,如果有就返回串池中字符串的地址,并把这个地址付给对象变量。如果没有则会在串池里创建一个字符串对象,并返回其地址付购对象变量,当另一个以字面时,创建对象时则会重复上述过程。如果是new在堆空间中创建String类的对象,则不会有上述的过程。

     String类中的intern()方法会将在堆空间中创建的String类对象中的字符串和串池中的比对,如果有相同的串就返回这个串的串池中的地址。不变模式在对于对象进行修改,添加操作是相当麻烦的,它会产生很多的中间垃圾对象。创建和销毁的资源的开销是相当大的。这就是推荐大量使用StringBuffer,而不建议使用String的原因!

     String类在字符串连接时会先的效率很低,就是因为它所产生的对象的属性不能被修改的,当连接字符串时也就是只能创建新的对象。造成很多无用的资源开销和浪费!

一句话概述:final修饰的东西不能被修改,不能被继承。

四、abstract修饰类和方法

    1.abstract修饰类

    使这个类成为一个抽象类,类将不能生成对象实例,但可以做为对象变量声明的类型,也就是编译时类型,抽象类就像当于一类的半成品,需要子类继承并覆盖其中的抽象方法。

    2.abstract修饰方法

    使这个方法变成抽象方法,即只有声明(定义)而没有实现,实现部分以";"代替。需要子类继承实现(覆盖)。

    注意:

    (1)有抽象方法的类一定是抽象类。但是抽象类中不一定都是抽象方法,也可以全是具体方法。abstract修饰符在修饰类时必须放在类名前。

    abstract修饰方法就是要求其子类覆盖(实现)这个方法。调用时可以以多态方式调用子类覆盖(实现)后的方法,即抽象方法必须在其子类中实现,除非子类本身也是抽象类。

    (2)父类是抽象类,其中有抽象方法,那么子类继承父类,并把父类中的所有抽象方法都实现(覆盖)了,子类才有创建对象的实例的能 力,否则子类也必须是抽象类。抽象类中可以有构造方法,是子类在构造子类对象时需要调用的父类(抽象类)的构造方法。

    (3)不能放在一起的修饰符:final和abstract,private和abstract,static和abstract,因为abstract修饰的方法是必须在其子类中实现(覆盖),才能以多态方式调用,以上修饰符在修饰一个方法时它的子类都修改不了这个方法,final是不可以覆盖,private是不能够继承,所以也就不能覆盖,static是可以覆盖的,但是在调用时会调用编译时类型的方法,因为调用的是父类的方法,而父类的方法又是抽象的方法,又不能够调用,所以上述的修饰符不能放在一起。

    一句话概述:抽象类的目的就是为了让其子类实现它本身的方法!

 

  • 12
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值