java:final和static初学

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.1
final 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.2
class 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值