Java 面试题基础(四)
- 前言
- 1、获取Class对象的构造方法?
- 2、获取Class对象的成员变量?
- 3、获取Class对象的成员方法?
- 4、简述一下你了解的设计模式?
- 5、java中fail-fast和fail-safe的区别说明?
- 6、Jsp的运行原理?
- 7、finally语句总是会执行吗?
- 8、try、catch、finally中包含return的四种情况以及返回结果?
- 9、线程池的线程数量怎么确定?
- 10、Iterator 怎么使用?有什么特点??
- 11、Java 中能创建 volatile 数组吗?
- 12、volatile 能使得一个非原子操作变成原子操作吗?
- 13、String、数组和 List之间的转换?
- 14、volatile 修饰符的有过什么实践?
- 15、设计模式分类?
- 16、什么是多线程环境下的伪共享(false sharing)?
- 17、Java 中怎么获取一份线程 dump 文件?
- 18、生产环境服务器变慢,如何诊断处理?
- 19、什么是线程局部变量?
- 20、mysql用什么类型存储金额或者IP?
- 总结
前言
最新的 Java 面试题,技术栈涉及 Java 基础、集合、多线程、Mysql、分布式、Spring全家桶、MyBatis、Dubbo、缓存、消息队列、Linux…等等,持续更新中。
如果对老铁有帮助,帮忙免费点个赞,谢谢你的发财手!
1、获取Class对象的构造方法?
//获取字节码对象
Class<?> aClass = Class.forName("com.user");
//通过无参构造函数获取用户对象
Object user = aClass.getConstructor().newInstance();
//通过有参构造函数获取用户对象,参数是包装类
Constructor constructor = aClass.getConstructor(String.class, Integer.class);
Object user = constructor.newInstance("张三", 20);
2、获取Class对象的成员变量?
//获取当前类所有的字段
Field[] fields = aClass.getDeclaredFields();
//获取当前类和父类所有pulbic字段
Field[] fields = aClass. getFields();
//获取当前类指定的字段
Field field = aClass.getDeclaredField("name");
//获取当前类和父类指定的pulbic字段
Field field = aClass.getField("name");
//设置私有变量可访问
field.setAccessible(true);
field.set(user, "张三");//表示给对象user的name属性赋值。
3、获取Class对象的成员方法?
Method[] methods = aClass.getDeclaredMethods();//获取当前类所有的方法;
Method[] methods = aClass.getMethods();//获取当前类和父类所有的public方法
//获取单个方法,参数一是方法名,参数2.3...是方法参数类型
Method method = aClass.getDeclaredMethod/getMethod ("getUserByName", String.class);
method.setAccessible(true);
Object o = method.invoke(user, "张三");
4、简述一下你了解的设计模式?
面试被问到关于设计模式的知识时,可以拣最常用的作答,例如:
- 工厂模式:工厂类可以根据条件生成不同的子类实例,这些子类有一个公共的抽象父类并且实现了相同的方法,但是这些方法根据不同的业务进行了不同的操作(多态方法)。
- 动态代理模式:给一个对象生成了一个动态代理对象,并由代理对象控制原对象的引用。在实际开发中,根据使用目的的不同,代理可以分为:远程代理、虚拟代理、保护代理等。
- 适配器模式:把一个类的接口变换成客户端所期待的另一种接口,从而使因接口不匹配而无法在一起使用的类能够一起工作。
- 策略模式:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
5、java中fail-fast和fail-safe的区别说明?
- fail-fast: 当一个线程在遍历这个集合,而另一个线程对这个集合的结构进行了修改,会抛出异常
- fail-safe:任何对集合结构的修改都会在一个复制的集合上进行修改,因此不会抛出异常。
6、Jsp的运行原理?
- 1、服务器根据接收到的客户端的请求来加载相应的JSP文件。
- 2、JSP引擎会将该JSP文件转化为Servlet。
- 3、然后把Servlet代码编译成Class文件。
- 4、服务器将执行结果返回给浏览器进行显示。
如果多个客户端同时请求该Jsp文件,则Jsp引擎会创建多个线程,使得每一个请求都对应一个线程。
7、finally语句总是会执行吗?
不一定
1.当没有进入try语句就发生异常的时候,不会执行finally语句(只有与 finally 相对应的 try 语句块得到执行的情况下,finally 语句块才会执行)
2.当try语句中执行System.exit(0) 这个方法的时候,也不会执行finally语句。
8、try、catch、finally中包含return的四种情况以及返回结果?
- 第1种情况:在try和catch中有return,finally中没有return,且finally中没有对try或catch中要对return的数据进行操作,则无影响。
- 第2种情况:在try和catch中有return,finally中没有return,但finally中有对try或catch中要对return的数据进行操作:
①返回的数据为基本数据类型和String,则finally中对要返回数据操作无影响
②返回的数据为引用数据类型,finally中如果改变了返回对象的属性则影响结果,如果改变的是对象的引用,则无影响。 - 第3种情况:在try和catch中有return,finally中也有return
try或catch中return后面的代码还会执行,但最终返回的结果为finally中return的值 - 第4种情况:在try中有return,在catch中手动throw抛出异常,finally中有return
如果catch块中捕获了异常, 并且在catch块中将该异常抛给上级调用者进行处理, 但finally中有return, 那么catch块中的throw就失效了, 上级方法调用者是捕获不到异常。
9、线程池的线程数量怎么确定?
- 一般来说,如果是CPU密集型应用,则线程池大小设置为N+1。
- 一般来说,如果是IO密集型应用,则线程池大小设置为2N+1。
10、Iterator 怎么使用?有什么特点??
(1) 调用iterator()方法返回一个Iterator对象;
(2) 使用hasNext()检查序列中是否还有元素;
(3) 使用next()获得序列中的下一个元素;
(4) 使用remove()将迭代器新返回的元素删除。
Iterator是Java迭代器设计模式最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。
Iterator<Integer> iterator = numList.iterator();
while (iterator.hasNext()) {Integer num = iterator.next();if (num < 0) {//使用迭代器的删除方法删除iterator.remove();}
}
11、Java 中能创建 volatile 数组吗?
能,不过只是一个指向数组的引用,而不是整个数组。
如果多个线程同时改变数组的元素,volatile 标示符就不能起到之前的保护作用了。
12、volatile 能使得一个非原子操作变成原子操作吗?
可以,一个典型的例子是volatile 修饰的long或double类型的成员变量。
13、String、数组和 List之间的转换?
下面的代码以连接本机的 Oracle 数据库为例,演示 JDBC 操作数据库的步骤。
String 转数组:String[] array = str.split(",");
数组转String:String str = Arrays.toString(array);数组转List:List<String> list = Arrays.asList(array);
List转数组:String[] array = list.toArray(new String[list.size()]);String转List:List<String> list = Arrays.asList(str.split(","));
List转String:String str = String.join(",", list);
14、volatile 修饰符的有过什么实践?
一种实践是用 volatile 修饰 long 和 double 变量,使其能按原子类型来读写。
double 和 long 都是 64 位,因此对这两种类型的读是分为两部分的,第一次读取前 32 位,然后再读剩下的 32 位,这个过程不是原子的。
15、设计模式分类?
- 1、创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
- 2、结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
- 3、行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
16、什么是多线程环境下的伪共享(false sharing)?
伪共享是多线程系统(每个处理器有自己的局部缓存)中一个众所周知的性能问题。
伪共享发生在不同处理器上的线程对变量的修改依赖于相同的缓存行。
17、Java 中怎么获取一份线程 dump 文件?
- 在Linux下,你可以通过命令 kill -3 PID (Java 进程的进程 ID)来获取 Java 应用的 dump 文件。
- 在Windows下,你可以按下Ctrl + Break来获取。这样JVM 就会将线程的 dump 文件打印到标准输出或错误文件中,它可能打印在控制台或者日志文件中,具体位置依赖应用的配置。
18、生产环境服务器变慢,如何诊断处理?
- 1、使用 top 指令,服务器中 CPU 和 内存的使用情况,-H 可以按 CPU 使用率降序,-M 内存使用率降序。排除其他进程占用过高的硬件资源,对 Java 服务造成影响。
- 2、如果发现 CPU 使用过高,可以使用 top 指令查出 JVM 中占用 CPU 过高的线程,通过 jstack 找到对应的线程代码调用,排查出问题代码。
- 3、如果发现内存使用率比较高,可以 dump 出 JVM 堆内存,然后借助 MAT 进行分析,查出大对象或者占用最多的对象来自哪里,为什么会长时间占用这么多;如果 dump 出的堆内存文件正常,此时可以考虑堆外内存被大量使用导致出现问题,需要借助操作系统指令 pmap 查出进程的内存分配情况、gdb dump 出具体内存信息、perf 查看本地函数调用等。
- 4、如果 CPU 和 内存使用率都很正常,那就需要进一步开启 GC 日志,分析用户线程暂停的时间、各部分内存区域 GC 次数和时间等指标,可以借助 jstat 或可视化工具 GCeasy 等,如果问题出在 GC 上面的话,考虑是否是内存不够、根据垃圾对象的特点进行参数调优、使用更适合的垃圾收集器;分析 jstack 出来的各个线程状态。如果问题实在比较隐蔽,考虑是否可以开启 jmx,使用 visualmv 等可视化工具远程监控与分析。
19、什么是线程局部变量?
线程局部变量是局限于线程内部的变量,属于线程自身所有,不在多个线程间共享。Java 提供了 ThreadLocal 类来实现线程安全。但是线程局部变量在工作完成后没有释放,就存在内存泄露的风险,每次使用完ThreadLocal都调用它的remove()方法清除数据。
20、mysql用什么类型存储金额或者IP?
- 金额:如果不是特别关心内存和性能的话,使用 decimal(10,2) ,否则使用 double(10,2) 。
- IP:应该使用32位的无符号整数(UNSIGNED INT)来存储IP地址,而不是使用字符串。
mysql> select inet_aton('192.168.0.1');
+--------------------------+
| inet_aton('192.168.0.1') |
+--------------------------+
| 3232235521 |
+--------------------------+
1 row in set (0.00 sec)mysql> select inet_ntoa(3232235521);
+-----------------------+
| inet_ntoa(3232235521) |
+-----------------------+
| 192.168.0.1 |
+-----------------------+
1 row in set (0.00 sec)
总结
都已经看到这里啦,赶紧收藏起来,祝您工作顺心,生活愉快!