final关键字 -----JAVA基础-------

来源:互联网 发布:网店美工毕业论文 编辑:程序博客网 时间:2024/05/16 12:09

1. 修饰变量


 该变量既可以是局部变量也可以是成员变量,final关键字修饰的成员变量即常量,可以被继承或者覆盖和隐藏!主要从以下两方面来说明问题。

 <1> 修饰基本数据类型


 final修饰的该变量就是常量,一旦赋值不可以改变其值。

一般情况,final修饰成员变量的话与static结合,使该常量可以被类直接调用,而不必创建对象,节省空间。再者,如果该常量中不含不确定因素,就称之为编译时期常量,反之为运行期常量。编译时期常量被调用时不会加载该类。

例子:

    package mark.zhang;  
    public class Linux {  
    // 修饰成员变量  
    public static final String NAME = "LINUX";  
    static {  
    System.out.println("--Linux---静态代码块");  
    }  
    {  
    System.out.println("--Linux---动态代码块");  
    }  
    public Linux() {  
    }  
    public void getName() {  
    // 修饰局部变量  
    final int i = 7;  
    }  
    }  
    class Test {  
    public static void main(String[] args) {  
    System.out.println(Linux.NAME);  
    }  
    }  

 

结果:

    LINUX  

 

还有这样一种情况,不想在声明常量的时候,给其赋值,那么怎么办?

我们知道,如果在声明常量的同时不将其赋值,编译器会给我们一个类似The blank final field NAME may not have been initialized的错误。

第一种办法,在静态代码块中给常量赋值。

    package mark.zhang;  
    public class Linux {  
    // 修饰成员变量  
    public static final String NAME;  
    static {  
      System.out.println("--Linux---静态代码块");  
      NAME = "LINUX";  
      }  
    {  
      System.out.println("--Linux---动态代码块");  
    }  
      public Linux() {  
      }  
    }  
    class Test {  
      public static void main(String[] args) {  
        System.out.println(Linux.NAME);  
      }  
    }  

 

结果:
   --Linux---静态代码块  
    LINUX  

 

分析:由于NAME是含有不确定因素,所以会加载静态代码块,从而将其初始化。

注意:动态代码块无法完成final变量的初始化

第二种方法,在构造方法中初始化

如果这样做,那么成员常量不可以被static修饰。

static无法修饰构造方法,因为构造方法是在创建对象时被调用的,而static修饰的,只会在加载该类时被加载一次。

    package mark.zhang;  
    public class Linux {  
        // 修饰成员变量,这里没有static  
        public final String NAME;  
        static {  
            System.out.println("--Linux---静态代码块");  
        }  
        {  
            System.out.println("--Linux---动态代码块");  
        }  
        public Linux() {  
            NAME = "LINUX";  
        }  
    }  
    class Test {  
        public static void main(String[] args) {  
            System.out.println(new Linux().NAME);  
        }  
    }  

 

结果:
    --Linux---静态代码块  
    --Linux---动态代码块  
    LINUX  

 

那么,有人说了,现在只有一个构造方法,如果再加一个或者n个构造方法呢,难道还要初始化吗???yes,恭喜你,答对了。必须的,否则你得到类似这样一个错误:


    The blank final field NAME may not have been initialized  

 
例子:

        public Linux() {  
        NAME = "LINUX";  
    }  
    public Linux(String name) {  
        NAME = "LINUX--LINUX";  
    }  
 

所以,正常情况下,不会使用这种方式。

<2> 修饰引用类型数据


注意:数组也是引用类型。

final修饰的引用不变指的是它的栈内存地址不变,即永远指向那个堆里的对象,但是堆里的对象(属性)是可变的!

示例:

    package mark.zhang;  
    public class Linux {  
        private String name = "linux OS";  
        static {  
            System.out.println("--Linux---静态代码块");  
        }  
        {  
            System.out.println("--Linux---动态代码块");  
        }  
        public Linux() {  
        }  
        public void setName(String name) {  
            this.name = name;  
        }  
        public String getName() {  
            return name;  
        }  
    }  

 

测试方法:

    class Test {  
        public static void main(String[] args) {  
            final Linux linux = new Linux();  
            System.out.println("linux's name : " + linux.getName());  
            // error: The final local variable linux cannot be assigned. It must be  
            // blank and not using a compound assignment  
            // linux = new Linux();  
        }  
    }  

 

但是我们可以修改其属性值。

   class Test {  
        public static void main(String[] args) {  
            final Linux linux = new Linux();  
            System.out.println("before--" + "linux's name : " + linux.getName());  
            linux.setName("ubuntu10.10");  
            System.out.println("after--" + "linux's name : " + linux.getName());  
        }  
    }  

 

结果:

    --Linux---静态代码块  
    --Linux---动态代码块  
    before--linux's name : linux OS  
    after--linux's name : ubuntu10.10  

 

2. 修饰类


final关键字修饰的类,类中成员方法默认为final,无法被继承!Java提供的包中,String类就是一个用关键字final修饰的类,所以其他类无法继承他!但是final关键字修饰的类可以作为子类,即可以继承其他类!


3. 修饰方法


final关键字修饰的方法,可以被继承,但是不能被覆盖!这样可以保证代码的安全性。

注意:final和static一样不可以修饰构造方法。

    package mark.zhang;  
    public class Linux {  
        static {  
            System.out.println("--Linux---静态代码块");  
        }  
        {  
            System.out.println("--Linux---动态代码块");  
        }  
        public Linux() {  
        }  
        /**
         * final修饰的方法可以被子类继承,但是不可以被子类重写 子类中也不可以与同名的该方法
         */  
        public final void getInfo() {  
            System.out.println("linux2.38");  
        }  
    }  
    class Ubuntu extends Linux {  
        // 一下两种方式均会报类似下面的错误  
        // Cannot override the final method from Linux  
        /*
         * public final void getInfo() { System.out.println("ubuntu10.10"); }
         */  
        /*
         * public void getInfo() { System.out.println("ubuntu10.10"); }
         */  
    }  
    class Test {  
        public static void main(String[] args) {  
            Ubuntu ubuntu = new Ubuntu();  
            // 可以继承父类的final方法  
            ubuntu.getInfo();  
        }  
    }  

 

4. final与abstract


final修饰的类不可以被继承,然而abstract修饰的类本意就是希望子类去继承。所以,在Java中不允许final修饰abstract,无论是abstract方法还是abstract类。

如果你这样子去修饰一个抽象类的话:

    final abstract class Ubuntu {  
        abstract void get();  
    }  

 

编译器毫不客气的给你一个错误信息:

    The class Ubuntu can be either abstract or final, not both  

 

同样的道理,final也不可以修饰abstract方法,如:

    abstract class Ubuntu {  
        final public abstract void get();  
    }  

 

错误:

    The abstract method get in type Ubuntu can only set a visibility modifier, one of public or protected  

 

从这句话中我们也可以得出结论:抽象方法不可以是private的,可以是default或者public或者protected。因为private方法子类不可见,更无法继承或者重写。

 

5. final与接口


final不能修饰interface接口

6. final与构造方法


final不可以修饰构造方法
0 0