java:final和static初学

来源:互联网 发布:递归算法解决迷宫问题 编辑:程序博客网 时间:2024/05/29 15:23
package com.jvmfinalstatic;参考文献:http://lavasoft.blog.51cto.com/62575/18771//*本节学习java中的final关键字 * 1.final 从字面上理解:最后的,无可改变的、也就是有些API中的“终态”; * 2.final修饰不同东西的不同效果 *  2.1修饰类  *      final类不能被继承,如果这个类不需要有子类,类也不想再扩展了就可以定义为final的; *      final类中成员 域: *          其域可以是 final 的也可以 不是final的 根据需求定义即可; *      final类中成员 方法: *          因此final类的成员方法没有机会被覆盖,默认都是 final 的。 *      示例代码:示例2.1 *  2.2修饰成员变量: *      final修饰基本数据类型变量(局部变量): *          用final修饰的成员变量表示常量,值一旦给定就无法改变! *          final变量定义的时候,可以先声明,而不给初值,这中变量也称为final空白, *          无论什么情况,编译器都确保空白final在使用之前必须被初始化. *      final修饰引用变量: *          则对其初试化之后就不能再指向另一个对象;引用不可以改变,但是它所指向的对象的内容可以改变 *      final小贴士: *          public static final int VALUE_THREE = 39; *          VALUE_THREE是一种更加典型的对常量进行定义的方式:定义为public,可以被任何人访问;定义为static, *          则强调只有一份;定义为fianl,这说明它是个常量。请注意带有恒定初始值(即,编译期常量) *          的final static基本类型全用大写字母命名,并且字母与字母之间用下划线隔开。 *  *  2.3修饰参数: *      1.java中允许在参数列表中以声明的方式将参数指明为final,这就意味着无法在方法中更改参数引用所指向的对象; *      2.匿名内部类的应用; *  2.4修饰方法: *      1.不让继承了修改它的含义;即不可以被覆盖 *      2.效率高点; *  2.5final和private *      1.类中的private方法隐式地指定为final的,由于无法取用private方法,所以也就无法覆盖它,因此对private方法 *        添加final修饰符什么作用也不起; *  * 3.java中的static用法: *  3.1static修饰的成员变量和成员方法 *      它不依赖类特定的实例,被类的所有实例共享。只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内 *      定找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。 *      静态变量:对于静态变量在内存中只有一个拷贝,JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配, *      可用类名直接访问。 *      静态方法:静态方法可以直接通过类名调用,任何的实例也都可以调用,因此静态方法中不能用this和super关键字,不能直 *      接访问所属类的实例变量和实例方法(就是不带static的成员变量和成员成员方法),只能访问所属类的静态成员变量和成员 *      方法。因为实例成员与特定的对象关联! *  3.2用public修饰的static成员变量和成员方法本质是全局变量和全局方法,(java中没有全局变量的定义)当声明它类的对象市, *      不生成static变量的副本,而是类的所有实例共享同一个static变量。 *  3.3static变量前可以有private修饰,表示这个变量可以在类的静态代码块中,或者类的其他静态成员方法中使用,但是不能 *      在其他类中通过类名来直接引用,这一点很重要。 *  3.4 用static修饰的代码块表示静态代码块,当Java虚拟机(JVM)加载类时,就会执行该代码块 *   *  * *///示例类2.1final class FinalClass{    int noFinalField = 2;    final int finalField = 4;    public void  show(){        System.out.println("i was a default final method ,because the class name is modified by final keyword"+" :"+noFinalField);    }}/*class SonFinalClass extends FinalClass{    // Error:The type SonFinalClass cannot subclass the final class FinalClass    //remove the final modifier of FinalClass}*///示例类2.2class FinalField{    //第一种情况:a 为常量    private final int a = 10;    //第二种情况:final空白;    private final int b ;    //第三种情况:c: 一个即是static又是fianl的域只占一段不能改变的存储空间,将用大写表示    public static final int C =20;    FinalField(int b){        this.b=b;        System.out.println("a:"+a+" b:"+b+" c:"+C);    }    //第四种情况:    public void importMethod1(){        String a = "hello2";         final String b = "hello";        String c = "hello";        String d = b + 2;         String e = c + 2;        System.out.println((a == d));//true        System.out.println((a == e));//flase;        /*这里面就是final变量和普通变量的区别了,当final变量是基本数据类型以及String类型时,         * 如果在编译期间 能知道 它的确切值,则编译器会把它当做编译期常量使用。也就是说在用到该final变         * 量的地方,相当于直接访问的这个常量,不需要在运行时确定。因此在上面的一段代码中,由于变量b         * 被final修饰,因此会被当做编译器常量,所以在使用到b的地方会直接将变量b替换为它的值;         * 而对于变量 c 的访问却需要在运行时通过  链接来进行。不过要注意,只有在编译期间能确切知道final         * 变量值的情况下,编译器才会进行这样的优化.         * 补注:         * 而我们知道String类型实现常量池技术,(结合反射一博文) 比如String st1 ="hellojava";         * String st2 ="hellojava";这是"hellojava"会存在方法区内的常量池中,又因为常量池是共享的         * ,所以只会存储一份,符号 st1和st2会存贮在栈中,并且俩个符号会指向同一个地址(及“hellojava"在常量池中的地址);         * */         Integer aa = 10;        Integer bb = 5;        Integer cc = 5;        Integer dd = bb+cc;        System.out.println(aa==dd);//输出结果为true;        //Java的数学计算是在内存栈里操作的其实比较的是基本类型(10=5+5),他们的值相同,因此结果为True    }    //第五种情况    public void importMethod2(){        String a = "hello2";         final String b = getHello();        String c = "hello";        String d = b + 2;         String e = c + 2;        System.out.println((a == d));//flase        //因为对于变量  b 和 c 的访问却需要在运行时通过  链接来进行,编译器就不会进行上述优化        System.out.println((a == e));//flase;    }    public static String getHello() {        return "hello";    }}//final 参数class FinalArgument{    void with(final FinalClass fc){        //fc = new FinalClass(); 这样是不对的,因为fc是final,        fc.noFinalField = 100;//其所指向的对象的内容是可以改的,虽然在才并不影响原来的值;       }}//final方法;class PrivateMethod{    public void  show(){        System.out.println("privateMethod"+" :"+"show()");    }    private void f(){        System.out.println("privateMethod"+" :"+"f()");    }}class PrivateFinalMethod extends PrivateMethod{    private void f(){        System.out.println("privateFinalMethod"+" :"+"f()");    }}class PrivateFinalMethod2 extends PrivateFinalMethod{    public void f(){        System.out.println("privateFinalMethod"+" :"+"f()");    }}//主函数:public class FinalModifierStudy {    public static void showFinalClass(){        FinalClass fc = new FinalClass();        //The final field FinalClass.finalField cannot be assigned        //fc.finalField = 44;        fc.noFinalField =22;        fc.show();        //输出结果:        //i was a default final method ,because the class name is modified by final keyword :22    }    public static void showFinalField(){        FinalField ff = new FinalField(40);        ff.importMethod1();    }    public static void showFinalMethod(){        PrivateFinalMethod2 pfm2 = new PrivateFinalMethod2();        pfm2.f();//就是调用PrivateFinalMethod2中的方法 其不是继承来的也不是覆盖了父类的;        //采用多态的形式会出错:        PrivateFinalMethod pfm = new PrivateFinalMethod2();        //pfm.f();就会出错 因为private f()就相当于隐藏在类中的代码,只不过形式和父类有点像        //其既不是继承来的也不是覆盖父类的;    }    public static void main(String[] args) {        //showFinalClass();        showFinalField();    }}
0 0
原创粉丝点击