Java系列0 面试题
2019-02-27 本文已影响0人
莫小归
参考:
https://blog.csdn.net/linzhiqiang0316/article/details/80473906
一.Java相关概念
1.面向对象的三个特征?
- 封装
- 继承
- 多态
2.代码中如何实现多态?
- 接口实现
- 重写父类方法
- 本类方法重载
3.虚拟机如何实现多态?
- 动态绑定
虚拟机在执行时判断所引用对象的实际类型,再根据实际类型调用对应方法
4.抽象类和接口的区别
抽象类 | 接口 | |
---|---|---|
方法实现 | 可以有方法实现 | 仅有方法定义 |
实现方式 | extends,如果子类不是抽象类,则需实现抽象类声明的所有方法 | implements,接口实现类需实现接口定义的所有方法 |
访问控制符 | public/protected/default | 默认public,不能使用其他访问控制符 |
5.Java创建对象有哪些方式?
- new
- 反射
- clone
- 序列化
6.Switch支持的参数类型
- byte
- char
- short
- int
- String (jdk1.7后)
7.object类有哪些共有方法?
- equals
- hashCode
- clone
- getClass
- toString
- notify/notifyAll/wait
8.Java中有哪几种引用,有什么区别?
- 强引用:不会被GC
- 软引用:JVM内存不够时将被GC
- 弱引用:即使JVM内存充足,该引用也将在下次GC时回收
- 虚引用:总会被回收,但在回收时GC将发送引用回收通知
9.什么叫深拷贝和浅拷贝?
略
10.equals()和==的区别
- 对基本类型而言,equals和==均是值比较
- 对对象而言,==比较地址,想要比较值需要重写equals方法
11.equals()和hashCode()的联系
- hashCode()返回对象的哈希值
- 如果两个对象equals方法结果相等,那么他们调用hashCode方法必定产生相同哈希值
- 如果两个对象equals方法结果不等,那么他们调用hashCode方法产生的哈希值一般不相等(仅在哈希碰撞的情况下相等)
12.&与&&的区别
- &是位运算符,&&是逻辑运算符
- &&具备短路特性
13.static的用法
- 静态变量
- 静态方法
- 静态代码块
- 静态内部类
- 静态导包
14.String、StringBuffer和StringBuilder的区别
- String是字符串常量,使用final修饰,效率低
- StringBuffer是字符串变量,线程安全,效率较高
- StringBuilder也是字符串变量,但线程不安全,效率最高
二.垃圾回收
1.常用垃圾回收算法有哪些?
- 标记-清除
- 标记-复制
- 标记-整理
- 分代回收
2.判断对象是否被回收的方法有?
- 引用计数法(循环引用会造成内存泄漏)
- 可达性分析法
3.调用System.gc()方法是否会立刻进行垃圾回收?
- 不会
调用该方法将通知GC开始工作,具体回收时间不定
三.多线程和锁
1.进程和线程有哪些区别?
进程 | 线程 | |
---|---|---|
基本单位 | 程序运行和资源分配的基本单位 | CPU调度和分派的基本单位 |
内存共享 | 拥有独立的内存单元 | 多个线程共享内存资源 |
关系 | 一个进程至少有一个线程 | 同一进程的多个线程可并发执行 |
2.什么叫守护线程?常见的守护进程有哪些?
- 程序运行完毕后,JVM将等待非守护线程完成后关闭,并直接关闭守护线程
- GC线程即常见的守护线程
3.创建线程的方法有哪些?
- 继承Thread类
- 实现Runnable接口的run()
- 实现Callable接口的call()
call方法有返回值,和Future、FutureTask配合可获取异步执行结果
4.Thread类的start()和run()有什么区别?
- 调用start()将启动新线程调用run()
- 调用run()将直接在当前线程执行run()
5.线程阻塞的相关方法?
- sleep():阻塞一定时间
- suspend() / resume():suspend阻塞当前线程,直到对应的resume方法被调用
- yield():使当前线程放弃已经获得的CPU时间,回到可执行状态,重新竞争CPU时间
- wait() / notify():阻塞一定时间,直到时间结束或被notify方法调用
5.1怎样唤醒一个阻塞的线程
- 如果是因为调用wait()、sleep()或join()导致的阻塞,可中断线程,并抛出InterruptedException唤醒线程
- 如果是遇到IO阻塞,IO由操作系统实现,Java无法将之唤醒
6.产生死锁的条件?
略
7.wait()和sleep()的区别
- wait()是object类的方法,sleep()是Thread类的方法
- 调用wait()方法将释放对象锁,但调用sleep()方法则不会
- sleep()需要指定一个睡眠时间,时间到后自动唤醒,wait()则需要配合notify()或notifyAll()使用
8.什么是多线程的上下文切换?
- CPU控制权的切换
- 由一个正在运行的线程切换到另外一个就绪并等待获取CPU执行权的线程
9.Synchronized和ReentrantLock的区别?
略
10.Java中有哪些锁?
- 自旋锁
因为共享数据的锁定通常只会持续很短时间,为这一小段时间而挂起和恢复线程显得有点浪费,所以让请求锁的线程稍等一会(执行自旋操作)而不放弃CPU执行时间,看持有锁的线程能否快速释放 - 偏向锁
用于消除数据在无竞争情况下的同步原语。锁会偏向第一个获得它的线程,如果在之后的执行过程中,没有其他线程获取该锁,则持有偏向锁的线程将不需要再进行同步 - 轻量级锁
- 重量级锁
11.什么是线程局部变量ThreadLocal?
- 线程局部变量是局限于线程内部的变量,属于线程自身所有,不与其他线程共享
- Java提供ThreadLocal类支持线程局部变量,在每个Thread中维护一个ThreadLocalMap完成数据隔离,以空间换时间的方式实现线程安全
12.什么是CAS?
- Compare And Swap,即比较-替换
- 假设有三个操作数 内存值V、旧的预期值A、要修改的值B
- 当且仅当预期值A和内存值V相同时,才会将内存值修改为B并返回true,否则什么都不做并返回false
13.什么是悲观锁和乐观锁?
- 乐观锁认为竞争不总会发生,所以它不需要持有锁,直接进行CAS。例子如数据库进行并发控制采用的时间戳
- 悲观锁认为竞争总是会发生,因此会先获得锁,再对资源进行操作
14.多线程开发的良好实践有哪些?
- 给线程命令
- 最小化同步范围
- 优先使用volatile
- 使用线程池
- 尽可能使用更高层次的并发工具(如BlockingQueue)而非wait和notify进行线程通信
- 优先使用并发容器而非同步容器
待续内容
- 线程池
- 锁
- 线程框架
四.一些实例
1.String s1="ab", String s2="a"+"b", String s3="a", String s4="b", String s5=s3+s4。那么s2==s5返回什么?
- false
- s2在编译时会优化为s2=”ab”,存入方法区字符串常量池
- s5将通过new创建,作为对象存入堆内存
2. 3*0.1==0.3?
- false
- 浮点数无法被精确表示
3.short s=1;s=s+1;和short s=1;s+=1;两条语句是否会报错错?
- short s=1;s=s+1;会报错,s+1的结果将转为int类型,再赋值给s时存在向下转型的问题
- short s=1;s+=1;不会报错,+=操作符会将计算结果隐式转换为赋值变量的类型,相当于s=(short)(s+1)
待续...