面试题
1.多态的了解
多态存在有三个前提
继承,重写,父类引用指向子类对象。
多态成员访问的特点:
a.成员变量
编译看左边(父类),运行看左边(父类)
b.成员方法
编译看左边(父类),运行看右边(子类)。动态绑定
c.静态方法
编译看左边(父类),运行看左边(父类)。
(静态和类相关,算不上重写,所以,访问还是左边的)
只有非静态的成员方法,编译看左边,运行看右边
2.什么是内部类,内部类的作用
内部类( Inner Class )就是定义在另外一个类里面的类。与之对应,包含内部类的类被称为外部类。
内部类的主要作用如下:
a. 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类
b. 内部类的方法可以直接访问外部类的所有数据,包括私有的数据
c. 内部类所实现的功能使用外部类同样可以实现,只是有时使用内部类更方便
3.抽象类的意义
抽象类体现的是一种模板模式的设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展,改造,但子类总体上会大致保留抽象类的行为方式
4.接口的意义
接口体现的是一种规范
5.内部类的设计意图
一个类可以访问另一个类的私有成员(封装性)
让Java可以实现多继承
6.静态内部类
如果内部类不会引用到外部类的东西的话,强烈建议使用静态内部类,因为这样更节省资源,减少内部类指向外部类的引用
7.String转化为integer的原理
8.匿名内部类
方便编写程序而设计的一个机制,有时候内部类只需要创建一个它的对象,以后不会在使用它,这个时候就使用匿名内部类。而且省去了起名字的麻烦
9.常见编码方式
utf-8,gbk,gb2312,ascii
10.静态代理和动态代理区别
静态代理类:由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
动态代理类:在程序运行时,运用反射机制动态创建而成。
静态代理通常只代理一个类,动态代理是代理一个接口下的多个实现类。
静态代理事先知道要代理的是什么,而动态代理不知道要代理什么东西,只有在运行时才知道。
动态代理是实现JDK里的InvocationHandler接口的invoke方法,但注意的是代理的是接口,也就是你的业务类必须要实现接口,通过Proxy里的newProxyInstance得到代理对象。
还有一种动态代理CGLIB,代理的是类,不需要业务类继承接口,通过派生的子类来实现代理。通过在运行时,动态修改字节码达到修改类的目的。
11.依赖注入
12.泛型
作用:类型限定,类型检查,提高程序运行效率
a泛型是伪泛型,在编译期间会被擦除,只留下原始类型,如果没有限定类型。原始类型就是Object,如果有限定类型,就用第一个边界的类型.
b.泛型变量的使用,是在编译之前检查的,因为编译的时候就擦除了,无法进行检查.
c.没有指定泛型类型的时候,泛型方法中如果有多个参数,最终的结果是两个参数最小的共同父类型
d.类型检查是针对引用的,用引用调用方法,就会检查。而无关真实的对象
e.泛型中参数化类型为什么不考虑继承关系
如果考虑了继承关系,在取值的时候,会发生ClassCastException或者
13.String为什么设计成不可变的
14.equals和hashcode方法
15.Object中的方法
wait,notify,hashcode,clone,equals,finalize,tostring,getclass
16.clone方法
浅拷贝:只拷贝对象。而不拷贝对象的引用,也就是说拷贝出来的对象和原对象引用同一个对象
深拷贝:不仅拷贝对象。也拷贝对象的引用
如何实现深拷贝?
a.实现Cloneable接口,重写clone方法,手动克隆引用
b.采用序列化方式
17.iterator和listiterator区别
18.java集合
19.concurrenthashmap
20Collections.synchronizedMap()
21如何控制某个方法允许并发访问线程的个数,
信号量
22.什么导致线程阻塞
23.java如何终止线程
25.synchronized和lock区别
26.进程和线程区别
进程:进程是资源(CPU、内存等)分配的基本单位,它是程序执行时的一个实例。程序运行时系统就会创建一个进程,并为它分配资源
线程:线程是程序执行时的最小单位,它是进程的一个执行流,是CPU调度和分派的基本单位,一个进程可以由很多个线程组成,线程间共享进程的所有资源,每个线程有自己的堆栈和局部变量。线程由CPU独立调度执行,在多CPU环境下就允许多个线程同时运行。
27.类锁。方法锁。重入锁
28.CountDownlatch
在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待
CountDownLatch内部通过共享锁实现。在创建CountDownLatch实例时,需要传递一个int型的参数:count,该参数为计数器的初始值,也可以理解为该共享锁可以获取的总次数。当某个线程调用await()方法,程序首先判断count的值是否为0,如果不会0的话则会一直等待直到为0为止。当其他线程调用countDown()方法时,则执行释放共享锁状态,使count值 – 1。当在创建CountDownLatch时初始化的count参数,必须要有count线程调用countDown方法才会使计数器count等于0,锁才会释放,前面等待的线程才会继续运行。注意CountDownLatch不能回滚重置。
29.CyclicBarrier
让一组线程到达一个屏障时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活
30.上面两个的区别?
CountDownLatch的作用是允许1或N个线程等待其他线程完成执行;而CyclicBarrier则是允许N个线程相互等待
CountDownLatch的计数器无法被重置;CyclicBarrier的计数器可以被重置后使用,因此它被称为是循环的barrier
31.多线程编程的好处和缺点
优点:提高CPU利用率,提高程序运行效率
缺点:安全性问题,性能问题(线程的创建销毁,以及线程之间的互相切换都是会消耗时间
32.线程优先级
优先级1-10,默认是5,普通优先级,一般来说,高优先级的线程在运行时会具有优先权,但这
依赖于线程调度的实现,这个实现和操作系统相关的,我们可以设置线程的优先级,但是不能保证优先级高的线程一定先执行。
33.什么是线程调度器(Thread Scheduler)和时间分片(Time Slicing)?
线程调度器是一个操作系统服务,它负责为Runnable状态的线程分配CPU时间。一旦我们创建一个线程并启动它,它的执行便依赖于线程调度器的实现。时间分片是指将可用的CPU时间分配给可用的Runnable线程的过程。分配CPU时间可以基于线程优先级或者线程等待的时间。线程调度并不受到Java虚拟机控制,所以由应用程序来控制它是更好的选择(也就是说不要让你的程序依赖于线程的优先级)。
34.在多线程中,什么是上下文切换(context-switching)?
上下文切换是存储和恢复CPU状态的过程,它使得线程执行能够从中断点恢复执行。上下文切换是多任务操作系统和多线程环境的基本特征。
35.为什么线程通信的方法wait(), notify()和notifyAll()被定义在Object类里?
Java的每个对象中都有一个锁(monitor,也可以成为监视器) 并且wait(),notify()等方法用于等待对象的锁或者通知其他线程对象的监视器可用。在Java的线程中并没有可供任何对象使用的锁和同步器。这就是为什么这些方法是Object类的一部分,这样Java的每一个类都有用于线程间通信的基本方法
36.为什么wait(), notify()和notifyAll()必须在同步方法或者同步块中被调用?
当一个线程需要调用对象的wait()方法的时候,这个线程必须拥有该对象的锁,接着它就会释放这个对象锁并进入等待状态直到其他线程调用这个对象上的notify()方法。同样的,当一个线程需要调用对象的notify()方法时,它会释放这个对象的锁,以便其他在等待的线程就可以得到这个对象锁。由于所有的这些方法都需要线程持有对象的锁,这样就只能通过同步来实现,所以他们只能在同步方法或者同步块中被调用。
37.为什么Thread类的sleep()和yield()方法是静态的?
Thread类的sleep()和yield()方法将在当前正在执行的线程上运行。所以在其他处于等待状态的线程上调用这些方法是没有意义的。这就是为什么这些方法是静态的。它们可以在当前正在执行的线程中工作,并避免程序员错误的认为可以在其他非运行线程调用这些方法。
38.ArrayMap和hashmap对比
存储方式不同
39.TreeMap