1. 面向对象的特征有哪些方面?
    • 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。
    • 继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类、基类);得到继承信息的类被称为子类(派生类)。继承让变化中的软件系统有了一定的延续性,同时继承也是封装程序中可变因素的重要手段。
    • 封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。面向对象的本质就是将现实世界描绘成一系列完全自治、封闭的对象。我们在类中编写的方法就是对实现细节的一种封装;我们编写一个类就是对数据和数据操作的封装。可以说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程接口。
    • 多态性:多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象引用调用同样的方法但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。如果将对象的方法视为对象向外界提供的服务,那么运行时的多态性可以解释为:当 A 系统访问 B 系统提供的服务时,B系统有多种提供服务的方式,但一切对 A 系统来说都是透明的(就像电动剃须刀是 A 系统,它的供电系统是 B 系统,B 系统可以使用电池供电或者用交流电,甚至还有可能是太阳能,A 系统只会通过 B 类对象调用供电的方法,但并不知道供电系统的底层实现是什么,究竟通过何种方式获得了动力)。方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。运行时的多态是面向对象最精髓的东西,要实现多态需要做两件事:1). 方法重写(子类继承父类并重写父类中已有的或抽象的方法);2). 对象造型(用父类型引用引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)。
    1. 访问修饰符 public,private,protected,以及不写(默认)时的区别? | 修饰符 | 当前类 | 同个包 | 子类 | 其他类 | | —- | —- | —- | —- | —- | | public | √ | √ | √ | √ | | protected | √ | √ | √ | × | | default | √ | √ | × | × | | private | √ | × | × | × |

    2. String 和 StringBuilder、StringBuffer 的区别?

    • String 和 StringBuffer/StringBuilder,它们可以储存和操作字符串。其中 String 是只读字符串,也就意味着 String 引用的字符串内容是不能被改变的。而 StringBuffer/StringBuilder 类表示的字符串对象可以直接进行修改。
    • StringBuilder效率比StringBuffer要高,因为没有使用synchronized 修饰,线程不安全。
    1. 重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?
    • 方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。
    • 重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求。
    1. 抽象类(abstract class)和接口(interface)有什么异同?
    • 抽象类和接口都不能够实例化,但可以定义抽象类和接口类型的引用。一个类如果继承了某个抽象类或者实现了某个接口都需要对其中的抽象方法全部进行实现,否则该类仍然需要被声明为抽象类。
    • 接口比抽象类更加抽象,因为抽象类中可以定义构造器,可以有抽象方法和具体方法,而接口中不能定义构造器而且其中的方法全部都是抽象方法。
    • 抽象类中的成员可以是 private、默认、protected、public 的,而接口中的成员全都是 public 的。
    • 抽象类中可以定义成员变量,而接口中定义的成员变量实际上都是常量。有抽象方法的类必须被声明为抽象类,而抽象类未必要有抽象方法。
    1. 静态变量和实例变量的区别。
    • 静态变量是被 static 修饰符修饰的变量,也称为类变量,它属于类,不属于类的任何一个对象,一个类不管创建多少个对象,静态变量在内存中有且仅有一个拷贝;
    • 实例变量必须依存于某一实例,需要先创建对象然后通过对象才能访问到它。静态变量可以实现让多个对象共享内存。
    1. 如何实现对象克隆?
    • 实现 Cloneable 接口并重写 Object 类中的 clone()方法;
    • 实现 Serializable 接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆
    1. String s = new String(“xyz”);创建了几个字符串对象?
    • 两个对象,一个是静态区的”xyz”,一个是用 new 创建在堆上的对象。
    1. Java 中的 final 关键字有哪些用法?
    • 修饰类:表示该类不能被继承;
    • 修饰方法:表示方法不能被重写;
    • 修饰变量:表示变量只能一次赋值以后值不能被修改(常量)。
    1. 实现字符串的反转及替换?

      1. //使用递归将字符串反转拼接
      2. public static String reverse(String originStr) {
      3. if(originStr == null || originStr.length() <= 1)
      4. return originStr;
      5. return reverse(originStr.substring(1)) + originStr.charAt(0);
      6. }
    2. Error 和 Exception 有什么区别?

    • Error 表示系统级的错误和程序不必处理的异常,是恢复不是不可能但很困难的情况下的一种严重问题;比如内存溢出,不可能指望程序能处理这样的情况;
    • Exception 表示需要捕捉或者需要程序进行处理的异常,是一种设计或实现问题;也就是说,它表示如果程序运行正常,从不会发生的情况。
    1. 列出一些你常见的运行时异常?
    • ArithmeticException(算术异常)
    • ClassCastException (类转换异常)
    • IllegalArgumentException (非法参数异常)
    • IndexOutOfBoundsException (下标越界异常)
    • NullPointerException (空指针异常)
    • SecurityException (安全异常)
    1. 阐述 ArrayList、Vector、LinkedList 的存储性能和特性。
    • ArrayList 和 Vector 都是使用数组方式存储数据,此数组元素数大于实际存储的 数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉 及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector 中的方法由 于添加了 synchronized 修饰,因此 Vector 是线程安全的容器,但性能上较 ArrayList 差,因此已经是 Java 中的遗留容器。
    • LinkedList 使用双向链表实现存 储(将内存中零散的内存单元通过附加的引用关联起来,形成一个可以按序号索 引的线性结构,这种链式存储方式与数组的连续存储方式相比,内存的利用率更 高),按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本 项的前后项即可,所以插入速度较快。
    • 由于 ArrayList 和 LinkedListed 都是非 线程安全的,如果遇到多个线程操作同一个容器的场景,则可以通过工具类 Collections 中的 synchronizedList 方法将其转换成线程安全的容器后再使用。
    1. List、Map、Set 三个接口存取元素时,各有什么特点?
    • List 以特定索引来存取元素,可以有重复元素。
    • Set 不能存放重复元素(用对象的 equals()方法来区分元素是否重复)。
    • Map 保存键值对(key-value pair)映射, 映射关系可以是一对一或多对一。
    • Set 和 Map 容器都有基于哈希存储和排序树的 两种实现版本,基于哈希存储的版本理论存取时间复杂度为 O(1),而基于排序树 版本的实现在插入或删除元素时会按照元素或元素的键(key)构成排序树从而达 到排序和去重的效果。
    1. Thread 类的 sleep()方法和对象的 wait()方法都可以让线 程暂停执行,它们有什么区别?
    • sleep()方法(休眠)是线程类(Thread)的静态方法,调用此方法会让当前线程 暂停执行指定的时间,将执行机会(CPU)让给其他线程,但是对象的锁依然保 持,因此休眠时间结束后会自动恢复。
    • wait()是 Object 类的方法,调用对象的 wait()方法导致当前线 程放弃对象的锁(线程暂停执行),进入对象的等待池(wait pool),只有调用 对象的 notify()方法(或 notifyAll()方法)时才能唤醒等待池中的线程进入等锁池 (lock pool),如果线程重新获得对象的锁就可以进入就绪状态。