杂题


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面试】-- 杂题的更多相关文章

  1. Java面试题精选(三) JSP/Servlet Java面试逻辑题

    --   JSP/Servlet  Java面试逻辑题   --     很显然,Servlet/JSP的WEB前端动态制作的重要性比HTML/CSS/JS的价值高很多,但我们都知道他们都是建立在HT ...

  2. 分享13道上海尚学堂拿回来的Java面试真题,这些都是Java核心常见问题,想拿OFFER必看!

    上海尚学堂Java培训学员参加面试带回来的真题,分享出来与大家,希望大家能认真地看看做一遍.后面有详细题解答案,对照下,看看自己做得怎么样,把这些面试遇到的真题全部掌握,做好面试笔试前的准备. 一.1 ...

  3. 【Java面试真题】剑指Offer53.2——0~n-1中缺失的数字(异或、二分两种解法)

    [Java实现]剑指Offer53.2--0~n-1中缺失的数字:面试真题,两种思路分享 前面有另一道面试题[Java实现]剑指offer53.1--在排序数组中查找数字(LeetCode34:在排序 ...

  4. 秋招如何抱佛脚?2022最新大厂Java面试真题合集(附答案

    2022秋招眼看着就要来了,但是离谱的是,很多同学最近才想起来还有秋招这回事,所以纷纷临时抱佛脚,问我有没有什么快速磨枪的方法, 我的回答是:有! 说起来,临阵磨枪没有比背八股文更靠谱的了,很多人对这 ...

  5. java面试基础题(三)

    程序员面试之九阴真经 谈谈final, finally, finalize的区别: final:::修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承.因此 ...

  6. java面试95题

    1.面向对象的特征有哪些方面? 答:面向对象的特征主要有以下几个方面: - 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面.抽象只关注对象有哪些属性和行为,并不关注 ...

  7. java面试编程题

      [程序1]   题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?   //这是一个菲波拉契数列问 ...

  8. Java面试经典题:线程池专题

    1.什么是线程池 线程池的基本思想是一种对象池,在程序启动时就开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理.当有线程任务时,从池中取一个,执行完成后线程对象归池, ...

  9. java 面试算法题

    /** * 设有n个人依围成一圈,从第1个人开始报数,数到第m个人出列,然后从 * 出列的下一个人开始报数,数到第m个人又出列,…,如此反复到所有的人全部出列为 * 止.设n个人的编号分别为1,2,… ...

  10. java面试基础题------》Java 中的父子类静态代码块,代码块,构造方法执行顺序

    4.指出下面程序的运行结果. class A { static { System.out.print("1"); } public A() { System.out.print(& ...

随机推荐

  1. xml文件报Element 'beans' cannot have character [children],because the type's content type is element

    写springMvc.xml文件时,偶然遇到 Element 'beans' cannot have character [children],because the type's content t ...

  2. 2020.12.3--vj个人赛补题

    A Vasya studies music.He has learned lots of interesting stuff. For example, he knows that there are ...

  3. Spring的JDK动态代理如何实现的(源码解析)

    前言 上一篇文章中提到了SpringAOP是如何决断使用哪种动态代理方式的,本文接上文讲解SpringAOP的JDK动态代理是如何实现的.SpringAOP的实现其实也是使用了Proxy和Invoca ...

  4. Scrum Meeting 14

    第14次例会报告 日期:2021年06月07日 会议主要内容概述: 汇报了已完成的工作,明确了下一步目标,正在努力赶进度. 一.进度情况 我们采用日报的形式记录每个人的具体进度,链接Home · Wi ...

  5. Beta-技术规格说明书

    项目 内容 这个作业属于哪个课程 2021春季软件工程(罗杰 任健) 这个作业的要求在哪里 团队项目-计划-功能规格说明书 一.架构与技术栈 1.整体架构 本项目的整体架构如上图所示.下面我们将对涉及 ...

  6. kafka错误之 Topic xxx not present in metadata after 60000 ms

    Topic xxx not present in metadata after 60000 ms 一.背景 二.场景还原 1.jar包引入 2.jar代码 3.运行结果 三.问题解决 四.参考文档 一 ...

  7. 洛谷 P3209 [HNOI2010] 平面图判定

    链接: P3209 题意: 给出 \(T\) 张无向图 \((T\leq100)\),并给出它对应的哈密顿回路,判断每张图是否是平面图. 分析: 平面图判定问题貌似是有线性做法的,这里给出链接,不是本 ...

  8. Flink计算pv和uv的通用方法

    PV(访问量):即Page View, 即页面浏览量或点击量,用户每次刷新即被计算一次. UV(独立访客):即Unique Visitor,访问您网站的一台电脑客户端为一个访客.00:00-24:00 ...

  9. 编译安装与gcc编译器

    先说一下gcc编译器,只知道这是一个老款的编译器.编译的目的也比较重要,就是将c语言的代码编译成可以执行的binary文件. gcc 简单使用(后期补充) eg: gcc example.c    # ...

  10. 更优于 Shellinabox 的 web shell 工具 -- ttyd

    ttyd 是一个运行在服务端,客户端通过web浏览器访问从而连接后台 tty (pts伪终端)接口的程序,把 shell 终端搬到 web 浏览器中. WebSocket WebSocket 是 HT ...