Java面试中最常被问知识点
- (进阶篇)Java面试中最常被问的知识
(进阶篇)Java面试中最常被问的知识
1、深复制和浅复制的区别
深复制:将指向内容复制到给当前对象新分配的缓冲区中的一种复制方式。
被复制的对象的所有变量都含有与原来对象相同的值,除了那些引用其他对象
的变量。那些引用其他对象的变量将指向被赋值的新对象,而不再是原有的那
些被引用的对象。
浅复制:指当对象的字段值被复制时,字段引用的对象不会被复制。
用以下类来说明深复制和浅复制
public class Main {
public StringBuffer str;
public int num;
}
2、为什么Java中有些接口没有任何方法?
没有声明任何方法的接口叫做标识接口,标识接口对实现它的类没有任何语义上的
要求,仅仅充当标识的作用,用来表明实现它的类属于一个特定的类型。这个标签
类类似于某个品牌的Logo,当我们见到这个logo,就它属于哪个品牌。
3、什么是反射机制?
反射是Java语言中的一个非常重要的特性,主要是指程序可以访问、检测
和修改它本身状态或行为的一种能力。同时也允许对其内部的成员进行操作。由
于反射机制能够实现在运行时对类进行装载,所以间接的增加了程序的灵活性。
同时,如果不恰当的使用反射,也会严重的影响系统性能。
反射的功能
1、得到一个对象所属的类
2、获取一个类的所有属性和方法(包括private权限)
3、在运行时创建对象
4、在运行时调用对象的方法
4、Java有几种创建对象的方法?
共有四种方法,分别是:
用new关键字创建
调用对象的clone方法
利用反射,调用Class类的或者是Constructor类的newInstance()方法
用反序列化,调用ObjectInputStream类的readObject()方法
5、简述final、finally、finalize的区别
(1) final
用于声明类和类中的方法、属性。
a、使用final声明类时,表示该类不可被继承。
b、使用final声明方法时,表示方法不可被重写
c、使用final声明属性时,表示属性不可再改变
a、使用final声明属性时,表示属性不可再改变 ,且必须被初始化。
public class Main {
public static void main(String[] args) {
int x=10;
x=20;
System.out.println(x);
}
}
输出 20
当用final修饰x,当再次为x赋值时,编译器将报错
public class Main {
public static void main(String[] args) {
final int x;
x=20;
System.out.println(x);
}
}
b、使用final声明方法时,表示方法不可被重写
class fu{
public final void fun(){
System.out.println("Java精灵儿");
}
}
class zi extends fu{
public void fun(){
System.out.println("Java精灵");
}
}
public class Main {
public static void main(String args[]){
zi z=new zi();
z.fun();
}
}
运行后报错: class zi overrides final method fun.()
说明子类不可重写final修饰的方法。
c、使用final声明类时,表示该类不可被继承。
final class fu{
public void fun(){
System.out.println("Java精灵儿");
}
}
class zi extends fu{//这里会报错,因为继承了final修饰的类
public void fun(){
System.out.println("Java精灵");
}
}
public class Main {
public static void main(String args[]){
zi z=new zi();
z.fun();
}
}
(2) finally
作为异常处理的一部分。
它只能出现在try...catch语句中,后跟一个语句块。
无论异常是否抓到,finally后的代码块最终一定会被执行。
public class Main {
public static void main(String args[]){
int x=6,y=2;
try{
x=3;
y=x/0;//将会抛出除数为0的异常
}catch(Exception e){
e.printStackTrace();
}finally{
System.out.println(y);
}
}
}
输出结果
2
java.lang.ArithmeticException: / by zero
at t.Main.main(Main.java:8)
(3) finalize
属于Object中的方法,用于垃圾回收。
垃圾回收器准备释放内存的时候,JVM会先调用回收对象的finalize()方法。
finalize()函数是在垃圾回收器准备释放对象占用的存储空间的时候被调用
的,绝对不能直接调用finalize(),所以应尽量避免用它垃圾回收。
6、instanceof的作用是什么?
该运算符用于操作对象实例,检查该对象是否是一个特定类型(类类型或
接口类型)。即它左边的对象是否是他右边的类的实例,若是,则返回True,
否则返回False
使用格式如下
( Object reference variable ) instanceof (class/interface type)
举例
class fu {
}
class zi extends fu{
}
public class Main {
public static void main(String args[]){
fu f1 = new fu();
fu f2 = new zi();
zi m1 = new zi();
System.out.println(f1 instanceof zi);//false
System.out.println(f2 instanceof zi);//true
System.out.println(m1 instanceof zi);//true
}
}
f1 instanceof zi ,zi 是 fu 的子类,fu 不是 zi 的子类,所以
返回结果为 false。
7、i++和++i的区别?
1、i++ 返回原来的值,++i 返回加1后的值。
2、++i 可以放在表达式的左边,而i++不可以。
3、i++,是先使用原始的i,然后再+1;++i,是先+1,后使用变化后的i。
i--和--i类似
8、不使用第三者能否实现两值的互换?
能!用 异或(^) 运算符
举例:
public class Main {
public static void main(String args[]){
int x=2,y=3;
x=x^y;
y=x^y;
x=x^y;
System.out.println("x= "+x);
System.out.println("y= "+y);
}
}
运行结果:
x= 3
y= 2
我这篇文章有详细讲解“不使用第三者实现两个变量值的互换”
8、什么是GC
GC(Garbage Collection)是垃圾回收的意思,在JAVA语言中是一个很重
要的概念,他的主要作用是回收程序中不再使用的内存。在C++中内存的释放
需要程序员手动释放,如果忘记释放内存,可能会导致内存泄漏,严重情况
下可能会导致系统崩溃。而Java语言自身提供了垃圾自动回收,不必由程序
员来手动释放内存,降低内存泄漏的风险,同时增加了系统的安全性。
垃圾回收负责完成2项任务
(1)、内存的分配
(2)、内存的正确回收
9、Collection 和Collections的区别
Collection是一个集合接口
其提供了对集合对象进行基本操作的接口方法。
Collections是集合的包装类
其包提供各种有关集合操作的静态方法,实现对各种集合的查找和排序等操作。
主要有
1)、sort排序方法
public static <T extends Comparable<? super T>> void sort(List<T> list)
public static <T> void sort(List<T> list,Comparator<? super T> c)
2)、 reverse()反转集合中元素的顺序
public static void reverse(List<?> list)
3)、copy将集合n中的元素全部复制到m中,并且覆盖相应索引的元素
public static <T> void copy(List<? super T> dest,List<? extends T> src)
10、有几种方法实现Java多线程
有三种方法实现多线程
1)、继承Tread类
2)、实现Runnable接口
3)、实现Callable()接口
4)、使用线程池创建线程
(1)、继承Tread类
class MyThread extends Thread{
public void run(){
System.out.println("MyThread运行了...");
}
}
public class Main {
public static void main(String args[]){
MyThread t1=new MyThread();
t1.run();
}
}
MyThread运行了...
(2)实现Runnable接口
class MyThread2 implements Runnable{
public void run(){
System.out.println("MyThread2运行了...");
}
}
public class Main {
public static void main(String args[]){
// 实现Runnable接口创建线
MyThread2 thread=new MyThread2();
Thread t2=new Thread(thread);
t2.run();
}
}
MyThread2运行了...
(3)、实现Callable()接口
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
* 一、创建执行线程的方式三:实现Callable接口。相较于实现Runnable接口的方式,方法可以有返回值,并且可以抛出异常
* 二、执行Callable方式,需要FutureTask实现类的支持,用于接收运算结果
*/
public class Main {
public static void main(String[] args) {
MyThread3 td = new MyThread3();
// 1.执行Callable方式,需要FutureTask实现类的支持,用于接收运算结果
FutureTask<Integer> result = new FutureTask<>(td);
new Thread(result).
start();
}
}
class MyThread3 implements Callable<Integer> {
public Integer call() throws Exception {
System.out.println("MyThread3被运行了......");
return null;
}
}