Java常碰到的关键字详解

关键字:html

  • final finalize finally
  • throws和throw
  • static关键字的做用
  • abstract和 interface
  • super和 this
  • synchronize和 volatile
  • String、StringBuffer、StringBuilder

1. final、finalize、finally对比java

(1)性质不一样api

  • final为关键字;
  • finalize为方法;
  • finally为为区块标志,用于try语句中;

(2)做用不一样数组

  • final:用于标识常量的关键字,final标识的关键字存储在常量池中(在这里final常量的具体用法将在下面进行介绍);final定义的变量值不可变,方法不可覆写,类不可继承。
  • 定义变量:一旦初始化(声明处或构造函数中)便不可改变。对基本类型是其值不可变,对引用类型是引用不可变;(String天生就是final的)
  • 定义方法:1)使用final定义的方法,不容许覆写,认为其功能知足要求无需扩展时;2)容许编译器将全部对此方法的调用转化为inline(行内机制),便可以将此方法直接复制在调用处,而不是进行例行的方法调用(保存断点、压栈),能够提升效率。但若是过多的话,会形成代码膨胀,反而会影响效率,慎用。
  • 定义类:没法被继承,这也就意味着此类在一个继承树中是一个叶子类;类成员是否是final均可以。
  • finalize:方法在Object中进行了定义,用于在对象“消失”时,由JVM进行调用用于对对象进行垃圾回收,相似于C++中的析构函数;用户自定义时,用于释放对象占用的资源(好比进行I/0操做);
  • finally{}:用于标识代码块,与try{}进行配合,是异常处理模型的补充,不论try中的代码执行完或没有执行完(这里指有异常),该代码块之中的程序一定会进行;不可单独使用,在一个try...catch...finally语句块中最多只有一个finally;通常用来维护对象的内部状态,清理非内存资源。

 

2. throws和throw对比  (Java中throws和throw的区别讲解安全

(1)使用位置不一样多线程

  • throw位于方法体内部,能够做为单独语句使用;
  • throws位于方法头部的参数列表后面,不能单独使用;

(2)内容不一样app

  • throw抛出一个具体的异常对象,并且只能是一个;
  • throws声明抛出的异常类,能够同时声明多个;

(3)做用不一样jvm

  • throw用于在程序中抛出异常,一旦执行说明必定有异常抛出,由方法体内部语句处理异常;
  • throws用于声明在该方法内可能抛出的异常类,若是抛出了异常,由该方法的调用者处理,层层上抛;

总结:函数调用时,若是须要向上层抛出异常,就必须在函数头部显式地声明(throws Exception1, Exception2)异常类型;若是仅须要在方法体内部处理异常,方法体内部可自行处理该异常,thorw抛出具体的异常实例(catch(Exception1 e){...})。函数

3. static关键字的做用性能

    static关键字可用来修饰属性、方法、代码块,目的是把对象相关的变成类相关的,即:不加static的成员是对象相关的,归单个对象全部;加static修饰的成员是类成员,能够经过类名直接调用,归全部对象全部。

static修饰的成员变量和成员方法习惯上称为静态变量和静态方法,能够直接经过类名来访问,访问语法为:

  • 类名.静态方法名(参数列表…)
  • 类名.静态变量名

(1)static修饰属性(类变量、静态变量)

  • 被static修饰的变量,叫静态变量或类变量,可经过类名直接访问;没有被static修饰的变量,叫实例变量。
  • 静态变量为本类全部对象共享;实例变量只属于单个对象。
  • 静态变量在内存中只有一个拷贝,在类加载时被建立和初始化,JVM只为其分配一次内存(节省内存)。类加载过程只进行一次,所以静态变量也只会被建立一次;实例变量在建立对象时被初始化,在内存中有多个拷贝,每建立一个对象就会为其分配一次内存,各实例变量间互不影响(灵活)。

        因此通常在须要实现如下两个功能时使用静态变量:

            1)在对象之间共享值时;2)方便访问变量时

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

  • static修饰的方法,叫静态方法,可经过类名直接访问,为本类全部对象共享;
  • 静态方法不能访问本类的非静态成员(包括实例变量和方法,由于非静态则和特定的对象关联,就不能全类共享了),可是非静态方法能够访问静态成员(ofcourse,静态成员全类共享);
  • 静态方法中不能出现this和super关键字(由于this是指向当前对象,super.成员名调用父类成员);
  • 由于static方法独立于任何实例,所以static方法必须被实现,而不能是抽象的abstract;
  • 子类覆盖父类的静态方法时,只能依然覆盖为静态方法(一日static终生static),可是没有多态。

        Java中main方法必须为static的缘由:

            在类加载时没法建立对象,而静态方法能够不经过对象调用,因此在类加载时能够经过main方法入口运行程序。

(3)static修饰代码块(初始化块、静态代码块)

    格式: static{...}

    static代码块也叫静态代码块,是在类中独立于类成员的static语句块,能够有多个,位置能够随便放,它不在任何的方法体内,JVM加载类时会执行这些静态的代码块,若是static代码块有多个,JVM将按照它们在类中出现的前后顺序依次执行它们,每一个代码块只会被执行一次。

初始化总结(静态变量->实例变量->按声明初始化->执行构造方法)

    1)首次使用某个类时,JVM查找相应的类文件并加载(Java只有在必要时才会逐步载入相应的类文件)

    首先为全部的静态变量分配存储空间并初始化为默认值(全局变量),而后按照声明静态变量时指定的初始化动做的顺序,以及静态初始化块中的语句在类定义中出现的顺序依次执行。这些静态的初始化动做只会在其所属类的类文件加载时执行一次。

    2)类文件加载完毕后,若是须要建立类的对象,则进行以下初始化动做

    JVM为全部的实例变量分配足够的存储空间并初始化为默认值(局部变量);而后按声明实例变量时指定初值的初始化动做和实例初始化块中的语句在类中出现的顺序依次执行,以后再调用相应的构造方法。

4. abstract和 interface对比

    abstract class和interface是支持抽象类定义的两种机制。正是因为这两种机制的存在,才赋予了Java强大的面向对象能力。abstract class和interface之间在对于抽象类定义的支持方面具备很大的类似性,区别:

抽象类(Abstract Class):

    (1)只能做为其余类的基类,不能被实例化(new);

    (2)抽象类中的成员是否是abstract无所谓,并非必须的。(能够有抽象成员,也能够没有任何抽象成员)

    (3)抽象类不能同时是final的。抽象的老是但愿被继承,而final类不可被继承。final和abstract不可同时存在。

    (4)非抽象类继承抽象类,必须覆盖其全部的抽象成员。抽象类继承抽象类,能够不覆盖全部的抽象成员。

    (5)抽象类容许被声明

接口(interface):

    接口的本质是一种特殊的抽象类,用来描述系统对外提供的全部服务。

    (1)接口中,全部方法都是公开、抽象的:public abstract。(都必须被继承)

    (2)接口中,全部属性都是公开、静态、常量:public static final,且必须赋初值。(全部实现类共享且不可改变)

    接口老是但愿被实现被访问的,所以全部成员都必须是公开的(public),确保外界能够访问。接口仅仅描述系统能够作什么,但不指明如何去作,具体操做由实现类完成,所以方法都是abstract的,都必须被继承;接口不涉及任何的实现细节,所以无构造方法,接口不能被实例化;无变量,只有静态常量(static final),由于要被全部的实现类共享;类的继承只能单继承,可是接口能够一次实现多个,用“,”隔开。

5. super和 this对比

super:

    super能够理解为是指向本身父类对象的一个指针,指的是离本身最近的一个父类。

用法:

  • super.成员名(变量名或者方法名):显式调用父类的同名成员,固然成员不能是private的(不容许子类访问)。由于当子类和父类存在同名成员时,由于子类成员优先级更高,此时会隐藏父类的相应成员。
  • super(参数列表);:调用父类的构造函数,注意super语句必定要放在函数体的第一条 :

this:

    this能够理解为指向当前对象自身的一个指针,即当前正在执行本方法的那个对象实例。位于函数体内部。

用法:

  • this.成员名:引用成员变量。由于函数参数或者函数中的局部变量和成员变量同名的话,成员变量被屏蔽,此时要访问成员变量则须要使用“this.成员变量”的方式引用。
  • this(参数列表);:调用本类中参数表一致的另外一个构造函数,注意应做为构造函数中的第一条语句。

引用构造函数时:

    super(参数):调用父类中的某一个构造函数(应该为构造函数中的第一条语句)。this(参数):调用本类中另外一种形式的构造函数(应该为构造函数中的第一条语句)。

    this和super都无需声明。

6. synchronize和 volatile对比

(1)做用范围:volatile仅能使用在变量级别;synchronized则可使用在变量、方法、和类级别;

(2)volatile本质是在告诉jvm当前变量在寄存器(工做内存)中的值是不肯定的,须要从主存中读取;synchronized则是锁定当前变量,只有当前线程能够访问该变量,其余线程被阻塞住。

(3)volatile不会形成线程的阻塞;synchronized可能会形成线程的阻塞。

(4)volatile只能在线程内存和主内存之间同步一个变量的值,而synchronized则同步在线程内存和主内存之间的全部变量的值,经过锁住和释放监听器来实现。

(5)volatile标记的变量不会被编译器优化;synchronized标记的变量能够被编译器优化

(6)显然,synchronized在性能上将比volatile更加有所消耗

(7)volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则能够保证变量的修改可见性和原子性

7. String、StringBuffer、StringBuilder对比

(1)可变与不可变

  String类中使用字符数组保存字符串,以下就是,由于有“final”修饰符,因此能够知道string对象是不可变的。

    private final char value[];

  StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,以下就是,可知这两种对象都是可变的。

    char[] value;

(2)是否多线程安全

  String中的对象是不可变的,也就能够理解为常量,显然线程安全

  AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操做,如expandCapacity、append、insert、indexOf等公共方法。

  StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,因此是线程安全的。看以下源码:

public synchronized StringBuffer reverse() {

    super.reverse();

    return this;

}

public int indexOf(String str) {

    //存在 public synchronized int indexOf(String str, int fromIndex) 方法

    return indexOf(str, 0);       

}

  StringBuilder并无对方法进行加同步锁,因此是非线程安全的

 (3)StringBuilder与StringBuffer共同点

  StringBuilder与StringBuffer有公共父类AbstractStringBuilder(抽象类)。

  抽象类与接口的其中一个区别是:抽象类中能够定义一些子类的公共方法,子类只须要增长新的功能,不须要重复写已经存在的方法;而接口中只是对方法的申明和常量的定义。

  StringBuilder、StringBuffer的方法都会调用AbstractStringBuilder中的公共方法,如super.append(...)。只是StringBuffer会在方法上加synchronized关键字,进行同步。

  最后,若是程序不是多线程的,那么使用StringBuilder效率高于StringBuffer。

关于String、StringBuffer、StringBuilder

参考转载:http://www.cnblogs.com/xudong-bupt/p/3961159.html

                 http://www.cnblogs.com/xudong-bupt/p/3961159.html

Java中String、StringBuffer、StringBuilder区别与理解

1、先比较String、StringBuffer、StringBuilder变量的HashCode值

使用System.out.println(obj.hashcode())输出的时对象的哈希码,
而非内存地址。在Java中是不可能获得对象真正的内存地址的,由于Java中堆是由JVM管理的不能直接操做。 
只能说此时打印出的Hash码表示了该对象在JAVA虚拟机中的内存位置,
Java虚拟机会根据该hash码最终在真正的的堆空间中给该对象分配一个地址. 
可是该地址 是不能经过java提供的api获取的

String变量链接新字符串会改变hashCode值,变量是在JVM中“链接——断开”;
StringBuffer变量链接新字符串不会改变hashCode值,由于变量的堆地址不变。
StringBuilder变量链接新字符串不会改变hashCode值,由于变量的堆地址不变。

小结:哈希码相同的变量,其内容不必定相同;内容向同变量,哈希码不必定相同;

public class Buffer_HashCode01 {
    public static void main(String[] args) {

        String str1="学海无涯苦做舟";
        System.out.println("String 的 str1的hascode"+str1.hashCode());
        str1=str1+"人间正道是沧桑";      //注意此str1的存储地址已发生变化
        System.out.println("String 的 str1的hascode"+str1.hashCode());
        System.out.println(str1);
        StringBuffer sb1=new StringBuffer("弟子规");
        System.out.println("原来StringBuffer 的 hascode:"+sb1.hashCode());
        StringBuffer sb2=sb1.append("圣人教");    //注意sb1和sb2指向同一个地址
        System.out.println("添加字符串后StringBuffer 的 hascode:"+sb2.hashCode());
        sb2.insert(6,"海纳百川");
        StringBuilder sb=new StringBuilder("这显然是上半年");
        System.out.println("改变前StringBuilder变量的hashCode值"+sb.hashCode());
        sb.append("哦是的啊");
        System.out.println("改变后StringBuilder变量的hashCode值"+sb.hashCode());
    }
}

    结果:
        String 的 str1的hascode-2054942391
        String 的 str1的hascode895667206
        学海无涯苦做舟人间正道是沧桑
        原来 StringBuffer 的 hascode:1311053135
        添加字符串后StringBuffer 的 hascode:1311053135
        改变前StringBuilder变量的hashCode值118352462
        改变后StringBuilder变量的hashCode值118352462

 

2、比较String、StringBuffer、StringBuilder性能(仅在繁复操做)

String类因为Java中的共享设计,在修改变量值时使其反复改变栈中的对于堆的引用地址,因此性能低。

StringBuffer和StringBuilder类设计时改变其值,其堆内存的地址不变,避免了反复修改栈引用的地址,其性能高。

其中StringBuilder是专门相似于StringBuffer类的非线性安全类,即StringBuffer是线性安全的,适合于多线程操做;

StringBuilder是线性不安全的,适合于单线程操做,其性能比StringBuffer略高。

public class Xing_Neng_SSS01 {
    public static void main(String[] args) {

        long begin1 = System.currentTimeMillis();
        String str = "";
        for(int i=0;i<10000;i++){
            str = str+i;
        }

        long end1 = System.currentTimeMillis();
        long time1 = end1 - begin1;
        System.out.println("一、String + time="+time1);   

        long begin2 = System.currentTimeMillis();
        String str2 = "";
        for(int i=0;i<10000;i++){
            str2 = str2.concat(i+"");
        }

        long end2 = System.currentTimeMillis();
        long time2 = end2 - begin2;
        System.out.println("二、String concat time="+time2); 

        long begin3 = System.currentTimeMillis();
        StringBuffer str3 = new StringBuffer();
        for(int i=0;i<10000;i++){
            str3.append(""+i);
        }

        long end3 = System.currentTimeMillis();
        long time3 = end3 - begin3;
        System.out.println("三、StringBuffer time="+time3);  

        long begin4 = System.currentTimeMillis();
        StringBuilder str4 = new StringBuilder();
        for(int i=0;i<10000;i++){
            str4.append(""+i);
        }

        long end4 = System.currentTimeMillis();
        long time4 = end4 - begin4;
        System.out.println("四、StringBuilder time="+time4);
    }
}

    结果:
        一、String + time=241
        二、String concat time=92
        三、StringBuffer time=4
        四、StringBuilder time=2

 

3、String共享设计

当String使用引号建立字符串时,会先去字符串池中找,找到了就返回,找不到就在字符串池中增长一个而后返回,这样因为共享提升了性能。

 而new String()不管内容是否已经存在,都会开辟新的堆空间,栈中的堆内存也会改变。

下面是==来比较地址是否相等。

public class String_Equals01 {
    public static void main(String[] args) {

        String str1="学海无涯苦做舟人间正道是沧桑";
        String str11=str1;
        String str12="学海无涯苦做舟人间正道是沧桑";
        String str13=new String("学海无涯苦做舟人间正道是沧桑");

        System.out.println("String 的 str1 的hascode"+str1.hashCode());
        System.out.println("String 的 str11的hascode"+str11.hashCode());
        System.out.println("String 的 str12的hascode"+str12.hashCode());
        System.out.println("String 的 str13的hascode"+str13.hashCode());
        System.out.println("str1==str11  "+(str1==str11));
        System.out.println("str1==str12  "+(str1==str12));
        System.out.println("str1==str13  "+(str1==str13));
    }
}

    结果:
        String 的 str1 的hascode895667206
        String 的 str11的hascode895667206
        String 的 str12的hascode895667206
        String 的 str13的hascode895667206
        str1==str11 true
        str1==str12 true
        str1==str13 false
相关文章
相关标签/搜索