# Java

# 说一说Java

Sun 公司在 1995 创建 Java 的一些特点?

  • Object Oriented 面向对象
  • Platform Independent 平台独立
  • Interpreted 解释性语言
  • Multi-threaded 多线程

但是 Java 最重要的特点是平台独立

平台独立意味着我们可以在一个系统编译它然后在另外一个系统使用它

# 编译型语言和解释型语言的定义:

  • 编译型语言:把做好的源程序全部编译成二进制代码的可运行程序。然后,可直接运行这个程序。

  • 解释型语言:把做好的源程序翻译一句,然后执行一句,直至结束!

PS:java是解释型的语言,因为虽然java也需要编译,编译成.class文件,但是并不是机器可以识别的语言,而是字节码,最终还是需要 jvm的解释,才能在各个平台执行,这同时也是java跨平台的原因。所以可是说java即是编译型的,也是解释型,但是假如非要归类的话,从概念上的定义,恐怕java应该归到解释型的语言中。

# Java 为什么是高效的 ( High Performance )?

  • 因为 Java 使用 Just-In-Time (即时) 编译器把java字节码直接转换成可以直接发送给处理器的指令的程序。

# 面向对象的特征有哪些方面?

  • 封装

让变量和访问这个变量的方法放在一起,将一个类中的成员变量全部定义成私有的,只有这个类自己的方法才可以访问到这些成员变量

  • 抽象

声明方法的存在而不去实现它的类被叫做抽象类

  • 继承

继承是子类自动共享父类数据和方法的机制,这是类之间的一种关系,提高了软件的可重用性和可扩展性

  • 多态

多态就是指一个变量, 一个方法或者一个对象可以有不同的形式.

# JDK JRE JVM?

  • 解释它们的区别

# JDK

Java Development Kit 用作开发, 包含了JRE, 编译器和其他的工具(比如: JavaDoc,Java调试器), 可以让开发者开发、编译、执行Java应用程序.

# JRE

Java Runtime Environment java运行时环境,包含了java虚拟机,java基础类库。是使用java语言编写的程序运行所需要的软件环境,是提供给想运行java程序的用户使用的。

# JVM

Java virtual machine (Java 虚拟机) 是一个可以执行 Java 编译产生的 Java class 文件 (bytecode) 的虚拟机进程, 是一个纯的运行环境.

# 反射机制

Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的放射机制。

# 主要作用

  • 运行时获取类的方法和字段相关信息
  • 创建某个类的新实例
  • 取得字段引用直接获取和设置对象字段,无论访问修饰符是什么

# 设计模式

# 单例模式

Java中单例模式定义:“一个类有且仅有一个实例,并且自行实例化向整个系统提供。”

# 懒汉式(线程不安全)

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
    public static Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
      return instance;  
    }  
}
1
2
3
4
5
6
7
8
9
10

懒加载,这种写法在多线程环境不能正常工作

# 懒汉式(线程安全)

public class Singleton {  
    private static Singleton instance;  

    private Singleton (){}  

    public static synchronized Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
      return instance;  
    }  

}
1
2
3
4
5
6
7
8
9
10
11
12
13

这种写法能够在多线程中很好的工作,也具有懒加载,但是,效率很低,99%情况下不需要同步。

# 饿汉式

public class Singleton {  
    private static Singleton instance = new Singleton();  

    private Singleton (){}  

    public static Singleton getInstance() {  
      return instance;  
    }  

}
1
2
3
4
5
6
7
8
9
10

这种方式基于classloder机制避免了多线程的同步问题,不过,instance在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用getInstance方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化instance显然没有达到lazy loading的效果。

# 饿汉,变种

public class Singleton {  
    private Singleton instance = null;  

    static {  
    instance = new Singleton();  
    }  

    private Singleton (){}  

    public static Singleton getInstance() {  
      return this.instance;  
    }  

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 静态内部类

public class Singleton {  
    private static class SingletonHolder {  

    private static final Singleton INSTANCE = new Singleton();  

    }  

    private Singleton (){}  

    public static final Singleton getInstance() {  
      return SingletonHolder.INSTANCE;  
    }  

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

这种方式同样利用了classloder的机制来保证初始化instance时只有一个线程,它跟饿汉和饿汉,变种方式不同的是(很细微的差别):饿汉和饿汉,变种方式是只要Singleton类被装载了,那么instance就会被实例化(没有达到lazy loading效果),而这种方式是Singleton类被装载了,instance不一定被初始化。因为SingletonHolder类没有被主动使用,只有显示通过调用getInstance方法时,才会显示装载SingletonHolder类,从而实例化instance。想象一下,如果实例化instance很消耗资源,我想让他延迟加载,另外一方面,我不希望在Singleton类加载时就实例化,因为我不能确保Singleton类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化instance显然是不合适的。这个时候,这种方式相比饿汉和饿汉,变种方式就显得很合理。

# 枚举

public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  

    }  

}
1
2
3
4
5
6
7

这种方式是Effective Java作者Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象

# 双重校验锁

public class Singleton {  
    private volatile static Singleton singleton;  

    private Singleton (){}  

    public static Singleton getSingleton() {  
      if (singleton == null) {  
            synchronized (Singleton.class) {  
         if (singleton == null) {  
            singleton = new Singleton();  
          }  
        }  
    }  
      return singleton;  
    }  
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

在JDK1.5之后,双重检查锁定才能够正常达到单例效果。

# 异常

异常树

# 类的层次

  • 所有的异常类是从 java.lang.Exception 类继承的子类。
  • Exception 类是 Throwable 类的子类。除了Exception类外,Throwable还有一个子类Error 。
  • Java 程序通常不捕获错误。错误一般发生在严重故障时,它们在Java程序处理的范畴之外。
  • Error 用来指示运行时环境发生的错误。

# Java内置异常类

异常 描述
ArithmeticException 当出现异常的运算条件时,抛出此异常。例如,一个整数"除以零"时,抛出此类的一个实例。
ArrayIndexOutOfBoundsException 用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引。
ArrayStoreException 试图将错误类型的对象存储到一个对象数组时抛出的异常。
ClassCastException 当试图将对象强制转换为不是实例的子类时,抛出该异常。
IllegalArgumentException 抛出的异常表明向方法传递了一个不合法或不正确的参数。
IllegalMonitorStateException 抛出的异常表明某一线程已经试图等待对象的监视器,或者试图通知其他正在等待对象的监视器而本身没有指定监视器的线程。
IllegalStateException 在非法或不适当的时间调用方法时产生的信号。换句话说,即 Java 环境或 Java 应用程序没有处于请求操作所要求的适当状态下。
IllegalThreadStateException 线程没有处于请求操作所要求的适当状态时抛出的异常。
IndexOutOfBoundsException 指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。
NegativeArraySizeException 如果应用程序试图创建大小为负的数组,则抛出该异常。
NullPointerException 当应用程序试图在需要对象的地方使用 null 时,抛出该异常
NumberFormatException 当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。
SecurityException 由安全管理器抛出的异常,指示存在安全侵犯。
StringIndexOutOfBoundsException 此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。
UnsupportedOperationException 当不支持请求的操作时,抛出该异常。

下面的表中列出了 Java 定义在 java.lang 包中的检查性异常类。

异常 描述
ClassNotFoundException 应用程序试图加载类时,找不到相应的类,抛出该异常。
CloneNotSupportedException 当调用 Object 类中的 clone 方法克隆对象,但该对象的类无法实现 Cloneable 接口时,抛出该异常。
IllegalAccessException 拒绝访问一个类的时候,抛出该异常。
InstantiationException 当试图使用 Class 类中的 newInstance 方法创建一个类的实例,而指定的类对象因为是一个接口或是一个抽象类而无法实例化时,抛出该异常。
InterruptedException 一个线程被另一个线程中断,抛出该异常。
NoSuchFieldException 请求的变量不存在
NoSuchMethodException 请求的方法不存在

# 线程

# Synchronized关键字

# 一句话说出Synchronized的作用

能够保证在同一时刻最多只有一个线程执行该段代码,以达到保证并发安全的效果

# Synchronized的两个用法

  • 对象锁

    包括方法锁(默认锁对象为this当前实例对象)和同步代码块锁(自己指定锁对象)

  • 类锁

    指Synchronized修饰静态的方法或指定锁为Class对象。

Last Updated: 3/15/2019, 4:45:17 PM