Java中的关键字很多,至多有50个左右,常见的new,final,try,catch等等,其中大多数关键字的意义都很简略,基本上依据英文意思就能晓得其性能,本文不会对那些简略的关键字做介绍,仅筛选了几个应用频率较高,但又可能导致“蛊惑”的关键字来探讨。

1 transient

transient关键字可润饰于类成员变量,作用是当类的对象产生序列化的时候,最终的序列化内容不包含被润饰的成员变量。上面的代码演示了transient的性能:
《2020最新Java根底精讲视频教程和学习路线!》

public class User implements Serializable {    private String username;    private transient String password;        @Override    public String toString() {        return "User{" +                "username='" + username + ''' +                ", password='" + password + ''' +                '}';    }    //setter and getter}public class TransientTest {    public static void main(String[] args) {        User user = new User();        user.setUsername("yeonon");        user.setPassword("admin");        System.out.println("在序列化之前:");        System.out.println(user);        System.out.println("----------------------");        try (ObjectOutputStream oos = new ObjectOutputStream(                new FileOutputStream(                        "E:Java_projecteffective-javasrctopyeononch11user.txt"))){            oos.writeObject(user);            oos.flush();        } catch (IOException e) {            e.printStackTrace();        }        try (ObjectInputStream ois = new ObjectInputStream(                new FileInputStream("E:Java_projecteffective-javasrctopyeononch11user.txt"))){            User user1 = (User) ois.readObject();            System.out.println("序列化之后读取到的:");            System.out.println(user1);        } catch (IOException  | ClassNotFoundException e) {            e.printStackTrace();        }    }}复制代码

User类首先得实现Serializable接口,而后我在password成员变量上减少了transient关键字,在主类中,用ObjectOutputStream和ObjectInputStream来做序列化和反序列化。

执行后的输入后果如下:

在序列化之前:User{username='yeonon', password='admin'}----------------------序列化之后读取到的:User{username='yeonon', password='null'}复制代码

发现序列化之后,再读取时,password是null,这阐明序列化的内容没有包含password。

顺便说一下,在理论写代码的时候最好不要应用user1这种变量名,这里只是为了不便,顺手写的。

2 instanceof

这是一个二元操作符,也算是关键字,作用是判断右边的对象是否是左边类的实例。如下所示:

User user = new User();if (user instanceof User) {    System.out.println("user object is instance of User class");} else {    System.out.println("user object is'n instance of User class");}复制代码

这里必定会输入user object is instance of User class。如果咱们将User替换成Object,也一样会输入这段话,这阐明instanceof还能够用于继承体系,即能够用来判断继承体系中子类的实例是否是父类的实现。

3 volatile

这个多用于并发环境下,性能有两个:

  • 禁止指令重排
  • 保障可见性

对于volatile的介绍,在我之前的文章 Java虚拟机(二):Java内存模型 有具体解释,在此不再赘述。

4 synchronized

和volatile一样,多用于并发环境下,其作用就是给某个代码段或者办法加上内置锁。拿并发编程中的“Hello,World”来举个例子:

public class SyncTest {    private int count = 0;    public void add() {        count += 1;    }    public int getCount() {        return count;    }    public static void main(String[] args) throws InterruptedException, TimeoutException, ExecutionException {        ExecutorService service = Executors.newFixedThreadPool(4);        SyncTest syncTest = new SyncTest();        for (int j = 0; j < 4; j++) {            service.execute(() -> {                for (int i = 0; i < 10000; i++) {                    syncTest.add();                }            });        }        service.shutdown();        service.awaitTermination(1000, TimeUnit.SECONDS);        System.out.println(syncTest.getCount());    }}复制代码

这里输入的后果会是什么呢?40000?答案是不肯定,可能是40000,也可能是比40000小的数,但必定不会比40000大,因为这里至多有4个线程在并发的对count进行批改,而又没有什么同步措施,故答案不对。如果在add办法上退出synchronized关键字,就能够保障线程平安了,如下所示:

public synchronized void add() {    count += 1;}复制代码

这样之后,无论运行多少次代码,后果都会是40000。因为synchronized实际上是内置锁,同一时刻仅有一个线程能获取到锁,并对其进行批改,最初执行结束开释锁,其余线程可再次竞争锁,而后如此往返,晓得工作实现。

那synchronized除了作用在办法还能作用在哪呢?上面是synchronized的应用形式:

  • 作用在实例办法上(没有static润饰的办法),相当于给对应的对象加锁,即也不能拜访该对象其余的有synchronized润饰的办法,其余实例对象不受影响。
  • 作用静态方法上,相当于给类加锁,此时的作用范畴就是该类的所有实例对象,即该类的所有对象同一时刻只能拜访有一个对象能拜访到synchronized静态方法,而且不能拜访该类的其余synchronized静态方法。
  • 作用在代码块中,如下所示:

    private String lock = "lock";synchronized(lock) {    //do something}//或者synchronized(Test.class) {    //do something}复制代码

    这又有两种状况,一种是括号里的是对象实例,这种状况是对对象实例加锁,对其余对象没有影响。另一种是括号里的是类对象,这种状况是对类加锁,该类的其余对象都会受到影响。

对于synchronized的其余内容(例如在虚拟机里是如何实现的?有哪些相应的指令?)就不多说了,比拟本文不是专门讲并发的。

5 final

final最容易让人记住的性能就是将一个变量申明成常量了,但实际上它的作用不仅仅是这个,还能够避免指令重排,在我之前的文章Java虚拟机(二):Java内存模型%EF%BC%9AJava%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/)有比拟具体的介绍,在此不再赘述。

6 static

static的作用也比拟显著,就是将类、办法、成员变量申明成动态的。

  • 作用在类上。不能作用在外部类,只能作用在内部类上。表明该类是外部类所领有的,而不是外部类的对象实例领有的。能够在类里定义动态成员,而非动态外部类则不行。
  • 作用在办法上,表明该办法是一个类办法,和实例对象没有关系,能够间接通过类.办法的模式调用。在静态方法外部,能间接调用静态方法,但不能间接调用实例办法。
  • 作用在成员变量上,表明该成员变量是一个类成员变量,拜访规定同静态方法。

动态类作用就是方便使用,如果一个类不依赖外部类的成员变量、办法等,那么最好将其申明成动态类。

静态方法其实也是为了方便使用,在调用的时候能够间接通过类名.办法的模式调用而不须要创立一个新的实例对象,动态工厂模式就十分依赖这个个性。

动态成员变量还是为了方便使用,咱们常常能在程序源代码中看到相似public static final String XXX = "YYY"的申明,这是因为动态变量能够间接拜访,无论是在实例办法里,还是静态方法里都一样,这样就能防止通过参数传递了。

7 小结

本文简略的介绍了几个罕用的关键字,但实际上它们的性能或者原理都远远不止于此,如果想深刻理解,倡议到网上搜寻材料进行学习。