131、看程序说出执行结果
public class MyTest2 {
public static void main(String[] args) {
System.out.println(MyParent2.str);
}
}
class MyParent2{
public static final String str = "hello world";
static {
System.out.println("MyParent2 static block");
}
}
输出:
hello world
解析:常量在编译阶段会存入到调用这个常量的方法所在类的常量池中。在本题中就是MyTest2类中的主函数里面调用了这个常量,所以在这里就是将常量存放到了MyTest2的常量池中。之后,MyTest2与MyParent就没有任何关系了,甚至我们可以将MyParent2的class文件删除了。本质上,调用类并没有直接引用到定义常量的这个类(MyParent2),因此并不会触发定义常量的这个类(MyParent2)的初始化,没有初始化,就不会执行静态代码块,所以只会输出一行。
132、知道JVM反编译指令和常见的助记符吗?
反编译指令:javap -c xxx.class
助记符(特别特别多):
ldc : 表示将int,float或是String类型的常量值从常量池中推送至栈顶
bipush:表示将单字节(-128-127)的常量值推送至栈顶
sipush:表示将一个短整型常量值(-32768 - 32767)推送至栈顶
iconst_1:表示将int类型1推送至栈顶(只有iconst_m1、iconst_0 - iconst_5这7个)
anewarray:表示创建一个引用类型的数组(如类、接口、数组),并将其引用值压入栈顶
newarray:表示创建一个指定的原始类型的数组(如int、float、char等),并将其引用值压入栈顶
......................
133、看下面这题和131题的区别
import java.util.UUID;
public class MyTest3 {
public static void main(String[] args) {
System.out.println(MyParent3.str);
}
}
class MyParent3{
public static final String str = UUID.randomUUID().toString();
static {
System.out.println("MyParent3 static code");
}
}
打印结果:
MyParent3 static code
c8fed399-b99c-4639-96a9-777bfe5e017a
为什么静态代码块里面的代码会执行呢?str都是常量,131题中静态代码块里的程序就没有执行啊!问题的关键是,这个常量的值在编译器是否可以确定下来,131题中,常量的值在编译期已经确定下来了,但是在本题中,常量的值在编译期无法确定下来,由于使用了UUID和随机函数。
知识点:当一个常量的值并非在编译期间就可以确定的,那么其值就不会被放到调用类的常量池中,这时候在程序运行时会导致主动使用这个常量所在的那个类,显然就会导致那个类的初始化。
134、开发中有没有遇到过内存溢出?内存溢出原因有哪些?怎么解决?
引起内存溢出的原因有很多,常见的有以下几种:
- 内存中加载的数据量过于庞大,比如一次从数据库中取出过多的数据
- 集合类中有对象的引用,使用完后未清空,使得JVM不能回收
- 代码中存在死循环或循环产生过多重复的对象实体
- 使用第三方软件中有bug
- 启动参数内存设置的值太小
解决方案:
- 修改JVM启动参数,直接增加内存(-Xms,-Xmx参数一定不要忘记加)
- 检查错误日志,查看“OutOfMemory”错误前是否有其他异常或错误
- 对代码进行走查和分析,找出可能发生内存溢出的位置
重点排查以下几点:
- 检查对数据库查询中,是否有一次获得全部数据的查询操作,一般来说,如果一次获取10万条记录到内存时,就有可能引起内存溢出,这个问题比较隐蔽,再上线前,数据库中数据比较少,不容易出问题,上线后,数据库中记录多了,一次查询就有可能引起内存溢出,因此对于数据库查询尽量采用分页的方式查询。
- 检查代码中是否有死循环或者递归调用
- 检查是否有大量循环重复产生新对象实体
- 检查List、Map等集合对象是否有使用完未清除的问题。List、Map等集合对象会始终存有对对象的引用,使得这些对象不能被GC回收。可以使用内存查看工具动态查看内存使用情况。
135、JDBC操作数据库流程?
- Class.forName()加载数据库连接驱动
- DriverManager.getConnection()获取数据连接对象
- 根据SQL获取sql会话对象,有两种方式:Statement、PreparedStatement;
- 执行SQL处理结果集,执行SQL前如果有参数值就设置参数值setXXX()
- 关闭结果集,关闭会话,关闭连接
136、为什么要使用PreparedStatement?
- PreparedStatement接口继承自Statement,PreparedStatement实例包含已编译的SQL语句,所以其执行速度要快于Statement对象。
- 作为Statement的子类,PreparedStatement继承了Statement的所有功能,三种方法execute、executeQuery、executeUpdate已被更改以使之不再需要参数。
- 在JDBC应用中,在任何时候都不要使用Statement,原因如下:
- 代码的可读性和可维护性Statement需要不断地拼接,而PreparedStatement不会。
- PreparedStatement尽可能提高性能,DB有缓存机制,相同的预编译语句再次调用不会再次编译
- 最重要的一点就是极大地提高了安全性,Statement容易被SQL注入,而PreparedStatement传入的内容不会和SQL语句发生任何匹配关系。
137、关系数据库中连接池的机制是什么?
前提:为数据库连接建立一个缓冲池。
- 从连接池获取或创建可用连接
- 使用完毕之后,把连接返回给连接池
- 在系统关闭前,断开所有连接并释放连接占用的系统资源
- 能够处理无效链接,限制连接池中的连接总数不低于或者不超过某个限定值。
最小连接数是连接池一直保持的数据连接。如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费掉。
最大连接数是连接池能申请的最大连接数,如果数据连接请求超过此数,后面的连接请求将被加入到等待队列中。
如果最小连接数与最大连接数相差太大,那么,最先的连接请求会获利,之后超过最小连接数量的连接请求等价于建立一个新的数据库连接,不过,这些大于最小连接数的数据库连接在使用完不会马上释放,他将被放到连接池中等待重复使用,或是空闲超时后被释放。
总结:数据库连接池连接数量一直保持一个不少于最小连接数的数量,当数据不够时,数据库会创建一些连接,直到一个最大连接数,之后连接数据库就会等待。
138、TRUNCATE和DELETE的区别是什么?
DELETE命令从一个表中删除某一行,或多行,TRUNCATE命令永久地从表中删除每一行。
139、什么是触发器,MySQL中都有哪些触发器?
触发器是指一段代码,当触发某个事件时,自动执行这些代码。在MySQL数据库中有如下六种触发器:
- 1、Before Insert
- 2、After Insert
- 3、Before Update
- 4、After Update
- 5、Before Delete
- 6、After Delete
140、请说明InnoDB和MyISAM的区别
- InnoDB支持事务,MyISAM不支持;
- InnoDB数据存储在共享表空间,MyISAM数据存储在文件中;
- InnoDB支持行级锁,MyISAM只支持表锁;
- InnoDB支持崩溃后的恢复,MyISAM不支持;
- InnoDB支持外键,MyISAM不支持;
- InnoDB不支持全文索引,MyISAM支持全文索引;