每天进步一点~
01、问:PreparedStatement与Statement的区别?
答:
-
PreparedStatement是预编译语句执行者,数据库对sql语句进行预编译;Statement是执行时对sql语句进行编译
-
Statement存在sql注入的问题,PreparedStatement解决了这个问题
-
PreparedStatement的执行效率比Statement高
-
PreparedStatement中使用?占位符,设置参数更方便
02、问:Java中的HashMap的工作原理是什么?
答:HashMap的原理是:数组+链表。
HashMap类有一个叫Entry的内部类。这个Entry类包含了key-value作为实例变量。根据key的hashcode方法计算出hash值来决定具体在哪个位置,如果这个位置有值,则调用equals方法进行判断,如果equals相等则替换,如果equals不等则追加到链表后。
- 在1.7采用头插法,元素每次插入到链表头部,当扩容时,会发生链表反转,容易产生循环链表,多线程情况下可能发生死锁。
- 在1.8采用尾插法,元素每次插入到链表尾部,扩容不会发生反转,解决了死锁问题。数组+链表+红黑树。当链表长度超过8时转为红黑树。
03、问:线程的sleep()方法和yield()方法有什么区别?
答:
-
sleep()会给比它优先级低的线程机会,yield()方法只会给跟它同等级或比它优先级高的线程机会
-
执行sleep后进入阻塞状态,执行yield后进入就绪
-
sleep方法声明抛出InterruptedException异常,yield没有声明抛出任何异常
-
sleep比yield方法具有更好的移植性
04、问:什么是序列化,如何实现序列化?
答:
序列化机制(包括序列化和反序列化)的本质是用流将对象读到内存和写入外存。序列化机制的意义就是将对象脱离程序运行独立存在
应用场景是在RMI(远程方法调用)中应用,即通过网路或跨平台传输对象,而RMI是javaEE开发基础,所以javaEE要求传递的参数与返回值都实现序列化机制
- 序列化是用流将java对象转成二进制写入硬盘或网络
- 反序列化是用流将二进制数据转为java对象写入内存
实现序列化需要实现Serializable或Externalizable接口,如果某个成员变量是引用数据类型,那么要求该引用类也是可序列化的。如果类中每个成员变量不想被序列化,可以用transient关键字修饰。
序列化通常与IO中的ObjectInputStream(readObject方法)和ObjectOutputStream(writeObject方法)搭配使用
05、问:什么是单例模式?
答:单例模式是指一个类只创建一个实例。单例模式是经常用到的一种设计模式,
它分为饿汉式、懒汉式、静态内部类、枚举;
饿汉式:在类加载时就创建本类对象为私有静态常量,构造方法写成私有的,使用共有静态方法代替构造方法获取到这个单例
懒汉式:在饿汉式的基础上给静态方法加synchronized,在方法里判断本类对象是否为空,为空时创建。
静态内部类:将单例放在静态内部类中,避免在类加载的时候就创建对象,然后用静态方法代替私有构造
06、问:对象的深拷贝与浅拷贝?
答:对象的深拷贝是在拷贝时把这个对象复制一份,如果这个对象所属的类中有引用数据类型,也会将引用该类复制一份,以达到深度克隆,这样的话,一个改变了它的值不会影响另一个
实现深拷贝的方法:
-
覆盖Object的clone方法
-
通过序列化方式实现深拷贝
对象的浅克隆是在拷贝时把这个对象复制一份,但如果这个对象所属的类中有引用数据类型,这个引用还指向原来的引用。
例如:从A拷贝一份B,如果是深克隆,A和B是俩个独立的对象,只不过一模一样。如果是浅克隆,如果A中有引用类型,那么B中此引用类型和A中此引用类型指向的是同一块地址。
07、问:java8新特性有哪些?
答:
-
lambda表达式
-
函数式接口
-
重复注解
-
接口中的默认方法和静态方法
-
stream
08、问:什么是反射?
答:反射是在运行时动态的获取类的信息,获取Class对象有三种方法:类名.class、对象名.getClass()、Class.forName(“权限定名”)
获取到类对象后可以用newInstance()创建对象,Class类中API提供了获取属性、方法、构造器的方法。
09、问:JVM内存结构?
答:JVM内存结构包括:堆、虚拟机栈、本地方法栈、程序计数器、方法区
堆:存放new的对象,是内存中最大的一块区域
虚拟机栈:就是我们平时所说的栈,用来存放基本数据类型和对象的引用
本地方法栈:与虚拟机栈相同,只不过是为native方法服务的
程序计数器:用来标记程序运行到哪一行
方法区:也叫永久代,存放类的信息。在jdk1.6及以前,常量池在方法区里,常量池用于存放静态变量和字面量;在jdk1.7,常量池从方法区中分离出来,在内存中开辟了一段空间作为常量池;在jdk1.8,取消了方法区,取而代之的是元数据区。
10、问:面向对象的特征?
答:面向对象有三大特征:封装、继承、多态
- 封装是将重复利用的代码包装起来,以便其他处引用,提高了代码的可重用性
- 继承是发生在父子类之间的,子类继承父类开放权限的所有代码,其实继承破坏了封装性
- 多态是在不改变程序的代码的情况下,在程序运行时动态的绑定代码,使程序出现多种状态。多态的体现是继承、重写、父类引用指向子类对象
11、问:String下有哪些方法?
答:
-
substring():截取字符串
-
split():分割字符串
-
valueOf():将其他类型转为字符串类型
-
trim():去掉字符串前后空格
-
indexOf():返回第一次出现该字符的索引
-
length():长度
-
concat():拼接
-
startsWith():以……开始
-
endsWith():以什么结束
......
12、问:如何避免死锁?
答:
-
避免给同一线程多次加锁
-
主副线程的加锁顺序一致
-
使用定时锁
-
死锁检测
13、问:Lock与synchronized的区别?
答:
-
synchronized是关键字;Lock是接口
-
synchronized在发生异常后会自动释放锁;Lock不会
-
Lock有trylock方法看是否获得锁;synchronized没有
-
synchronized是修饰代码块、方法获得锁的;Lock是通过ReetrantLock类加锁的
-
synchronized是悲观锁;Lock是乐观锁
14、问:乐观锁与悲观锁的区别?
答:
悲观锁是将锁给一个线程,其他线程等待这个线程释放锁
乐观锁是先进行业务处理,最后一步更新数据时再加锁
①悲观锁适合于写频繁;乐观锁适合于读取频繁
②悲观锁是先加锁后进行业务逻辑;乐观锁是先进行业务逻辑再加锁
15、问:静态方法有什么缺点?
答:静态方法是属于类的,可以直接利用类名.直接调用,但静态方法不能自动销毁,它的执行效率比实例化要高。
16、问:hashCode相等,equals一定相等吗?
答:不一定。hashCode相等是指哈希值相等,而值不一定相等。
比如1和5这俩个数都在1这个位置上,那么它们的哈希值相等,但这俩个数不相等
17、问:List与Set的区别?
答:List和Set都是Collection接口下的接口。
-
List中元素可重复,有序,有下标;Set中元素无序,不可重复
-
List的查找快,增删慢;Set的查找慢,增删快
18、问:成员变量与局部变量的区别?
答:
-
成员变量的作用域是在类中;局部变量的作用域是在方法中
-
成员变量可以不赋初值;局部变量必须赋初值
19、问:ArrayList删除指定的元素怎么删?
答:
-
用普通for循环,并且在循环中i--
-
//加入删除元素b for (int i = 0; i < al.size(); i++) { if (al.get(i) == "b") { al.remove(i); i--; //一定要记着i--,因为每次删除完一个元素,后边的元素会往前挪 } }
-
-
用一个List 记录要删除的数据,最后在原集合中removeAll(List);
-
用迭代器自带的remove方法
20、问:Iterator与ListIterator的区别?
答:
-
Iterator遍历set和list;ListIterator只能遍历list
-
Iterator只能向后遍历,ListIterator既能向前遍历,也能向后遍历
-
ListIterator比Iterator方法多,比如增加元素
21、问:Java是如何实现多线程的?
答:
-
继承Thread类,重写run方法,调用这个类的start方法
-
实现Runnable接口
-
实现Callable接口,重写call方法,搭配FutureTask类使用
22、问:synchronized的原理?
答:
- 在JDK1.6以前,sync是重量级锁。
重量级锁有一个等待队列,想要抢占锁的线程都进入等待队列中,当线程A获得到共享资源,其他线程进入阻塞状态,当线程A释放锁时,其他线程被唤醒。
这个过程很消耗操作系统,因此sync的效率很低。
- 在JDK1.6之后,sync应用了锁升级。
起初是无状态的,jvm启动4s后开启偏向锁,当某个线程来竞争,要判断当前锁是否可重新偏向,如果不能,就升级为轻量级锁,当自璇无法获取到锁,就会升级为重量级锁。
23、问:IO与NIO的区别?
答:
-
IO是单向的,NIO是双向的
-
IO是面向流的,NIO是面向缓冲区(块)的
-
IO是阻塞,NIO是非阻塞
24、问:类加载的时机?
答:
-
创建类实例
-
反射
-
访问类变量,为类变量赋值
-
调用类方法
-
初始化子类时,其父类也会被初始化
-
标注为主启动类,执行main方法
25、问:类加载的步骤?
答:加载、连接、初始化;其中连接包括验证、准备、解析,每个阶段做的事情分别如下:
- 加载:将编译后的.class文件加载到JVM,并创建一个Class对象
- 验证:验证.class文件格式是否规范、也有安全层面的验证、验证类的元信息,字节码,符号引用
- 准备:为类的静态变量分配内存,赋默认值
- 解析:将符号引用转为直接引用
- 初始化:为静态变量赋初始值
Thanks
..