【Java面试】-- 杂题
杂题
2019-11-03 21:09:37 by冲冲
1、类加载器的双亲委派机制
类加载器:把类通过类加载器加载到JVM中,然后转换成class对象(通过类的全路径来找到这个类)。
双亲委派机制:当有一个类进入虚拟机加载环节后,但是他自己的类加载器不去加载,而是让其父类加载器加载(让上级加载器加载),只有当父类加载器找不到这个类的时候,子类加载器才会去加载.

优点:为了安全,Object是所有类的父类,系统类的加载都是经过Object加载器加载。此时,如果有一个自定义的类,但是类名和系统类中的某个类的类名相同,此时由于双亲委派机制的存在,JVM可以判定,哪一个是真的系统类,哪一个是自定义的的类(也就是通过类加载器判断)。可以避免黑客伪造破坏类。
2、HashSet如何去重?
① 首先调用hashCode()方法判断hashCode是否存在,如果不存在则无重复。
② 如果hashCode存在,则调用equals()方法判断有无对象内容重复,如果没有则不重复。
3、volatile关键字是否能保证线程安全?
不能。volatile关键字用在多线程同步中,可保证读取的可见性。JVM只是保证从主内存加载到线程工作内存的值是最新的读取值,而非cache中。但多个线程对volatile的写操作,无法保证线程安全。
假如,线程1和线程2 在进行read,load 操作中,发现主内存中count的值都是5,那么都会加载这个最新的值,在线程1对count进行修改之后,会write到主内存中,主内存中的count变量就会变为6。线程2由于已经进行read,load操作,在进行运算之后,也会更新主内存count的变量值为6。
4、Java能不能不通过构造函数创建对象?
能。Java创建对象的4种方式:
(1) 用new语句创建对象,这是最常见的创建对象的方法。
(2) 运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。
(3) 调用对象的clone()方法。
(4) 运用反序列化手段,调用java.io.ObjectInputStream对象的 readObject()方法。
注意:(1)和(2)都会明确的显式的调用构造函数 ;(3)是在内存上对已有对象的影印,所以不会调用构造函数 ;(4)是从文件中还原类的对象,也不会调用构造函数。
原型模式应用clone()
clone()是浅拷贝,可以重写成深拷贝。
浅拷贝:如果目标对象A,拥有一个引用类型的变量B,对A进行clone()得到复制品a,a也拥有引用类型变量b,a和b指向同一个对象(内存地址相同)。
深拷贝:a和b分别指向内存地址不同的两个同类型对象。
(在有指针的情况下,浅拷贝只是增加了一个指针指向已经存在的内存,而深拷贝就是增加一个指针并且申请一个新的内存,使这个增加的指针指向这个新的内存)
5、结论
① 子类新增的方法是不能直接操作被子类隐藏的成员变量的。子类重写的方法可以直接操作被子类隐藏的成员变量的。
② 不允许使用static修饰abstract方法。
③ 内部类的类名只能在定义它的类或程序段中或在表达式内部匿名使用。
④ 内部类可以使用它所在类的静态成员变量和实例成员变量。
⑤ 内部类可以用abstract修饰符定义为抽象类。
⑥ 内部类可作为其他类的成员,而且可访问它所在类的成员。
⑦ abstract方法必须在abstract类中。
⑧ static方法中不能处理非static的数据。
6、MyBatis的一级缓存和二级缓存
(1)一级缓存:①默认开启。②作用范围是一个sqlSession。
(2)二级缓存:①默认不开启。②作用范围是一个mapper(namespace),包括多条sqlSession。
缓存的作用:Mybatis首先前往缓存中查询结果集,如果没有则查询数据库,如果有则从缓存取出返回结果集就不走数据库。
底层实现:Mybatis内部存储缓存使用一个HashMap,key为hashCode+sqlId+Sql语句,value为从查询出来映射生成的java对象。
7、线程的创建方式(7种)
①继承Thread类
②实现Runable接口
③实现Callable接口和FutureTask类(该类实现的是Runable()接口)
④匿名Thread类
⑤Timer类和TimerTask类
⑥线程池Executors
⑦Stream类
(1)继承Thread类,作为线程对象存在
public class CreatThreadDemo1 extends Thread{
/**
* 构造方法: 继承父类方法的Thread(String name);方法
* @param name
*/
public CreatThreadDemo1(String name){
super(name);
}
@Override
public void run() {
while (!interrupted()){
System.out.println(getName()+"线程执行了...");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
CreatThreadDemo1 d1 = new CreatThreadDemo1("first");
CreatThreadDemo1 d2 = new CreatThreadDemo1("second");
d1.start();
d2.start();
d1.interrupt(); //中断第一个线程
}
}
① interrupted()方法,用于判断该线程是否被中断。
② interrupt()方法,本意是中断线程,但是用于终止线程。终止线程已经不允许用stop方法,该方法不会释放占用的资源。
③ Thread.sleep(200); //线程休息2ms。静态方法,线程不释放占用的资源(对象锁),线程进入sleep类型的阻塞状态。
④ Object.wait(); //让线程进入等待,直到调用Object的notify()或者notifyAll()时,线程停止休眠。调用者是对象不是线程,该方法使线程释放锁,进入同步队列,当被notify()或notifyAll()才被唤醒进入等待地列。
⑤ Thread.yield(); //线程放弃CPU时间片,进入Runable状态(sleep和wait才会阻塞),将cpu时间片让给其他优先级相等或者更高的线程。但是OS的调度机制也有可能继续把时间片交给该线程(备受青睐没办法)。yield只是暂停执行,不会释放对象锁(同sleep)。
(2)实现Runable()接口,作为线程任务存在
public class CreatThreadDemo2 implements Runnable {
@Override
public void run() {
while (true){
System.out.println("线程执行了...");
}
}
public static void main(String[] args) {
//将线程任务传给线程对象
Thread thread = new Thread(new CreatThreadDemo2());
//启动线程
thread.start();
}
}
(3)匿名内部类创建线程对象
public class CreatThreadDemo3 extends Thread{
public static void main(String[] args) {
//创建无参线程对象
new Thread(){
@Override
public void run() {
System.out.println("线程执行了...");
}
}.start();
//创建带线程任务的线程对象
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程执行了...");
}
}).start();
//创建带线程任务并且重写run方法的线程对象
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("runnable run 线程执行了...");
}
}){
@Override
public void run() {
System.out.println("override run 线程执行了...");
}
}.start();
}
}
因为Thread类本身也实现Runable()接口,那么到底运行刚实现的Runable()接口的run方法,还是运行Thread类本身的run()方法?
应该是Thread类的run()方法,因为该段代码相当于Thread类实现两个Runable()接口,从上往下依次执行,最终Thread类的run()方法覆盖掉前面实现的Runable()的run()方法。
(4)实现Callable()接口,创建带返回值的线程
public class CreatThreadDemo4 implements Callable {
public static void main(String[] args) throws ExecutionException, InterruptedException {
CreatThreadDemo4 demo4 = new CreatThreadDemo4();
FutureTask<Integer> task = new FutureTask<Integer>(demo4); //FutureTask最终实现的是runnable接口
Thread thread = new Thread(task);
thread.start();
System.out.println("我可以在这里做点别的业务逻辑...因为FutureTask是提前完成任务");
//拿出线程执行的返回值
Integer result = task.get();
System.out.println("线程中运算的结果为:"+result);
}
//重写Callable接口的call方法
@Override
public Object call() throws Exception {
int result = 1;
System.out.println("业务逻辑计算中...");
Thread.sleep(3000);
return result;
}
}
Callable()接口源码
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
返回指定泛型的call方法。然后调用FutureTask对象的get方法可以得到call方法的返回值。
(5)定时器Timer
public class CreatThreadDemo5 {
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("定时器线程执行了...");
}
},0,1000); //延迟0,周期1s
}
}
(6)线程池创建线程
public class CreatThreadDemo6 {
public static void main(String[] args) {
//创建一个具有10个线程的线程池
ExecutorService threadPool = Executors.newFixedThreadPool(10);
long threadpoolUseTime = System.currentTimeMillis();
for (int i = 0;i<10;i++){
threadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程执行了...");
}
});
}
long threadpoolUseTime1 = System.currentTimeMillis();
System.out.println("多线程用时"+(threadpoolUseTime1-threadpoolUseTime));
//销毁线程池
threadPool.shutdown();
threadpoolUseTime = System.currentTimeMillis();
}
}
shutdown()方法,要求所有线程都运行完之后再销毁。
shutdownnow()方法,要求所有线程立即停止(即便任务还没做完也要停止)然后销毁。
(7)利用java8新特性Stream实现并发
public class CreatThreadDemo7 {
public static void main(String[] args) {
List<Integer> values = Arrays.asList(10,20,30,40);
//parallel 平行的,并行的
int result = values.parallelStream().mapToInt(p -> p*2).sum();
System.out.println(result);
//怎么证明它是并发处理呢?因为输出结果是无序的,比如200,30,10,40,20
values.parallelStream().forEach(p-> System.out.println(p));
}
}
【Java面试】-- 杂题的更多相关文章
- Java面试题精选(三) JSP/Servlet Java面试逻辑题
-- JSP/Servlet Java面试逻辑题 -- 很显然,Servlet/JSP的WEB前端动态制作的重要性比HTML/CSS/JS的价值高很多,但我们都知道他们都是建立在HT ...
- 分享13道上海尚学堂拿回来的Java面试真题,这些都是Java核心常见问题,想拿OFFER必看!
上海尚学堂Java培训学员参加面试带回来的真题,分享出来与大家,希望大家能认真地看看做一遍.后面有详细题解答案,对照下,看看自己做得怎么样,把这些面试遇到的真题全部掌握,做好面试笔试前的准备. 一.1 ...
- 【Java面试真题】剑指Offer53.2——0~n-1中缺失的数字(异或、二分两种解法)
[Java实现]剑指Offer53.2--0~n-1中缺失的数字:面试真题,两种思路分享 前面有另一道面试题[Java实现]剑指offer53.1--在排序数组中查找数字(LeetCode34:在排序 ...
- 秋招如何抱佛脚?2022最新大厂Java面试真题合集(附答案
2022秋招眼看着就要来了,但是离谱的是,很多同学最近才想起来还有秋招这回事,所以纷纷临时抱佛脚,问我有没有什么快速磨枪的方法, 我的回答是:有! 说起来,临阵磨枪没有比背八股文更靠谱的了,很多人对这 ...
- java面试基础题(三)
程序员面试之九阴真经 谈谈final, finally, finalize的区别: final:::修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承.因此 ...
- java面试95题
1.面向对象的特征有哪些方面? 答:面向对象的特征主要有以下几个方面: - 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面.抽象只关注对象有哪些属性和行为,并不关注 ...
- java面试编程题
[程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? //这是一个菲波拉契数列问 ...
- Java面试经典题:线程池专题
1.什么是线程池 线程池的基本思想是一种对象池,在程序启动时就开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理.当有线程任务时,从池中取一个,执行完成后线程对象归池, ...
- java 面试算法题
/** * 设有n个人依围成一圈,从第1个人开始报数,数到第m个人出列,然后从 * 出列的下一个人开始报数,数到第m个人又出列,…,如此反复到所有的人全部出列为 * 止.设n个人的编号分别为1,2,… ...
- java面试基础题------》Java 中的父子类静态代码块,代码块,构造方法执行顺序
4.指出下面程序的运行结果. class A { static { System.out.print("1"); } public A() { System.out.print(& ...
随机推荐
- NOI2016区间bzoj4653(线段树,尺取法,区间离散化)
题目描述 在数轴上有 \(N\) 个闭区间 \([l_1,r_1],[l_2,r_2],...,[l_n,r_n]\) .现在要从中选出 \(M\) 个区间,使得这 \(M\) 个区间共同包含至少一个 ...
- Netty 进阶
1. 粘包与半包 1.1 粘包现象 服务端代码 public class HelloWorldServer { static final Logger log = LoggerFactory.getL ...
- Java(34)IO流之字符流
作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15228453.html 博客主页:https://www.cnblogs.com/testero ...
- 【UE4 C++ 基础知识】<4> 枚举 Enum、结构体 Struct
枚举 UENUM宏搭配BlueprintType可以将枚举暴露给蓝图,不使用的话,仅能在C++使用 //定义一个原生enum class enum class EMyType { Type1, Typ ...
- Redis:学习笔记-01
Redis:学习笔记-01 该部分内容,参考了 bilibili 上讲解 Redis 中,观看数最多的课程 Redis最新超详细版教程通俗易懂,来自 UP主 遇见狂神说 1. Redis入门 2.1 ...
- 认真讲说static关键字
static 关键字主要有以下四种使用场景 修饰成员变量和成员方法 静态代码块 修饰类(只能修饰内部类) 静态导包(用来导入类中的静态资源,1.5之后的新特性) 修饰成员变量和成员方法(常用) 被 s ...
- 贪心-Saruman‘s Army POJ - 3069
万恶之源 目录 题意 思路 贪心的原则是什么呢? 错解 正解 代码实现 书上的代码 我的代码 比较一下 问题 题意 给定若干个点的坐标,与范围R.每个点可以选择是否标记,标记后这个点的左右范围R内的所 ...
- IdentityServer4 负载均衡配置
在不用到负载之前,一切都很好,但是部署多个实例之后,问题挺多的:session问题.令牌签发后的校验问题. 在此之前,先自查官方文档:Deployment - IdentityServer4 1.0. ...
- QT判断文件/目录是否存在
最近在用qt写一个ui,遇到删除sd卡中的文件失败情况,有些时候是存在删除链表里面的文件在sd卡上已经不存在了,导致失败,以为我的链表是定时刷新的,但是文件是实时更新会同步覆盖的.这样就存在可能上一秒 ...
- python进阶(22)pydantic--数据类型校验
pydantic库的作用 pydantic库是一种常用的用于数据接口schema定义与检查的库. Pydantic 在运行时强制执行类型提示,并在数据无效时提供用户友好的错误信息. pydantic安 ...