③面向对象
1、wait 方法底层原理
考察点:基础
参考回答:
ObjectSynchronizer::wait 方法通过 object 的对象中找到 ObjectMonitor 对象调用方法 void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS)
通过ObjectMonitor::AddWaiter调用把新建立的ObjectWaiter对象放入到 _WaitSet 的队 列的末尾中然后在 ObjectMonitor::exit 释放锁,接着 thread_ParkEvent->park 也就是 wait。
Wait()方法和notify()方法:当一个线程执行到wait()方法时,它就进入到一个和该对象相关的等待池中,同时失去了对象的机锁。当它被一个notify()方法唤醒时,等待池中的线程就被放到了锁池中。该线程从锁池中获得机锁,然后回到wait()前的中断现场。
2、Java 有哪些特性,举个多态的例子。
考察点:语言特性
参考回答:
封装、继承、多态。多态:指允许不同类的对象对同一消息做出响应。即同一消息可以根据 发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)
3、String 为啥不可变?
考察点:面向对象
参考回答:
不可变对象是指一个对象的状态在对象被创建之后就不再变化。不可改变的意思就是说:不 能改变对象内的成员变量,包括基本数据类型的值不能改变,引用类型的变量不能指向其他的对 象,引用类型指向的对象的状态也不能改变。
String 不可变是因为在 JDK 中 String 类被声明为一个 final 类,且类内部的 value 字 节数组也是 final 的,只有当字符串是不可变时字符串池才有可能实现,字符串池的实现可以 在运行时节约很多 heap 空间,因为不同的字符串变量都指向池中的同一个字符串;如果字符串 是可变的则会引起很严重的安全问题,譬如数据库的用户名密码都是以字符串的形式传入来获得 数据库的连接,或者在 socket 编程中主机名和端口都是以字符串的形式传入,因为字符串是不 可变的,所以它的值是不可改变的,否则黑客们可以钻到空子改变字符串指向的对象的值造成安 全漏洞;因为字符串是不可变的,所以是多线程安全的,同一个字符串实例可以被多个线程共享, 这样便不用因为线程安全问题而使用同步,字符串自己便是线程安全的;因为字符串是不可变的 所以在它创建的时候 hashcode 就被缓存了,不变性也保证了 hash 码的唯一性,不需要重新计 算,这就使得字符串很适合作为 Map 的键,字符串的处理速度要快过其它的键对象,这就是 HashMap 中的键往往都使用字符串的原因。
4、类和对象的区别
考察点:面向对象
参考回答:
1.类是对某一类事物的描述,是抽象的;而对象是一个实实在在的个体,是类的一个实例。
比如:“人”是一个类,而“教师”则是“人”的一个实例。
2.对象是函数、变量的集合体;而类是一组函数和变量的集合体,即类是一组具有相同属性 的对象集合体。
5、请列举你所知道的 Object 类的方法。
考察点:面向对象
参考回答:
Object()默认构造方法。clone() 创建并返回此对象的一个副本。equals(Object obj) 指 示某个其他对象是否与此对象“相等”。**finalize()**当垃圾回收器确定不存在对该对象的更多引 用时,由对象的垃圾回收器调用此方法。getClass()返回一个对象的运行时类。hashCode()返回 该对象的哈希码值。 **notify()**唤醒在此对象监视器上等待的单个线程。 notifyAll()唤醒在此 对象监视器上等待的所有线程。toString()返回该对象的字符串表示。**wait()**导致当前的线程等 待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。wait(long timeout)导 致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超 过指定的时间量。wait(long timeout, int nanos) 导致当前的线程等待,直到其他线程调用此 对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某 个实际时间量。
6、重载和重写的区别?相同参数不同返回值能重载吗?
考察点:重载
参考回答:
重载(Overloading)
(1) 方法重载是让类以统一的方式处理不同类型数据的一种手段。多个同名函数同时存在, 具有不同的参数个数/类型。
重载 Overloading 是一个类中多态性的一种表现。
(2) Java 的方法重载,就是在类中可以创建多个方法,它们具有相同的名字,但具有不同 的参数和不同的定义。
调用方法时通过传递给它们的不同参数个数和参数类型来决定具体使用哪个方法, 这就是 多态性。
(3) 重载的时候,方法名要一样,但是参数类型和个数不一样,返回值类型可以相同也可 以不相同。无法以返回型别作为重载函数的区分标准。
重写(Overriding)
(1) 父类与子类之间的多态性,对父类的函数进行重新定义。如果在子类中定义某方法与 其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。在 Java 中,子类可继承父类 中的方法,而不需要重新编写相同的方法。
但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的 重写。
方法重写又称方法覆盖。
(2)若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法 将覆盖原有的方法。
如需父类中原有的方法,可使用 super 关键字,该关键字引用了当前类的父类。
(3)子类函数的访问修饰权限不能少于父类的。
7、”static”关键字是什么意思?Java 中是否可以覆盖(override)一个 private 或者是 static 的方法?
考察点:static 变量
参考回答:
“static”关键字表明一个成员变量或者是成员方法可以在没有所属的类的实例变量的情 况下被访问。 Java 中 static 方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,而 static 方法是编 译时静态绑定的。static 方法跟类的任何实例都不相关,所以概念上不适用。
8、String 能继承吗?
考察点:String
参考回答:
不能,char 数组用 final 修饰的。
9、StringBuffer 和 StringBuilder 有什么区别,底层实现上呢?
考察点:类
参考回答:
StringBuffer 线程安全,StringBuilder 线程不安全,底层实现上的话,StringBuffer 其 实就是比 StringBuilder 多了 Synchronized 修饰符。
StringBuilder在能力上和StringBuffer没有区别,但是它去掉了线程安全的部分,有效减少了开销,绝大部分情况下进行字符串拼接的首选
10、类加载机制,双亲委派模型,好处是什么?
考察点:类
参考回答:
某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归, 如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才 自己去加载。
使用双亲委派模型的好处在于 Java 类随着它的类加载器一起具备了一种带有优先级的层次 关系。例如类 java.lang.Object,它存在在 rt.jar 中,无论哪一个类加载器要加载这个类,最 终都是委派给处于模型最顶端的 Bootstrap ClassLoader 进行加载,因此 Object 类在程序的各 种类加载器环境中都是同一个类。相反,如果没有双亲委派模型而是由各个类加载器自行加载的 话,如果用户编写了一个 java.lang.Object 的同名类并放在 ClassPath 中,那系统中将会出现
多个不同的 Object 类,程序将混乱。因此,如果开发者尝试编写一个与 rt.jar 类库中重名的 Java 类,可以正常编译,但是永远无法被加载运行。