一、访问修饰符public、private、protected以及不写(默认)的区别?
- public对于当前类、同包中的类、子类、其他包中的类是公开的
- private只能对于当前类是公开的
- protected对于当前类、子类是公开的,对于同一包中但不具有附子关系的类相当于私有的
- 不写访问修饰符是默认为default,对于同一包中的其他类相当于公开,对于不是同一个包中的其他类是私有的
二、String是最基本的数据类型吗?
不是,Java中基本的数据类型只有8个:byte、short、int、long、float、double、char、boolean;除了基本类型,剩下的都是引用类型,Java5以后引入的枚举类型也算是一种比较特殊的引用类型
三、float f = 3.4;是否正确?
不正确,3.4是双精度数,需要进行强制类型转换:float f = (float)3.4; 或者float f = 3.4F;
四、Integer和int的区别?
- Integer是int的封装类,而int是基本数据类型;
- Integer的默认值是null,而int默认值为0;
- 声明为Integer的变量需要实例化,而声明int的变量不需要实例化;
- Integer是对象,用一个引用指向这个对象,而int是基本数据类型,直接存储数值。
看下面这段代码:
public class Test03 {
public static void main(String[] args) {
Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;
System.out.println(f1 == f2);
System.out.println(f3 == f4);
}
}
结果是:
true
false
首先要注意的是,四个变量都是Integer对象引用,所以==比较的时候比较的是引用而不是值
当整型字面量在-128到127之间,那么不会new新的Integer对象,而是直接引用常量池中的Integer对象,所以f1 ==f2是true, f3 ==f4是false。
五、&和&&的区别?
- &是逻辑与、按位与,&&是短路与
- 虽然两条运算都是需要运算符左右条件同时为true时才为true,但是&&只要第一个条件为false则后面的条件直接短路掉,不会进行运算
- 我们平时使用较多的都会是&&而不是&,例如登录时需要验证用户名不为null和不为空字符串,会写成:
username != null && !username.equals("")
二者顺序是不可以改变的,更不能使用&运算符,因为第一个条件不成立,根本无法进行字符串的equals的比较,否则会抛出NullPointerException异常。
六、Java中如何跳出多重嵌套循环?
在最外层循环前加一个标记如ok,然后用 break ok; 可以跳出多重循环。
outerloop:
for (int i = 1; i < 5; i++) {
for (int j = 1; j < 5; j++) {
if (i * j > 6) {
System.out.println("Breaking");
break outerloop;
}
System.out.println(i + " " + j);
}
七、构造器能否被重写(override)?
构造器不能被重写,但是可以被重载
八、数组有没有length()方法?String有没有length()方法?
数组没有length()方法,有length属性,String有length()方法
九、两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?
不对,如果两个对象x和y满足x.equals(y)==ture,它们的hash code应当相同。Java相对于equals方法和hashcode方法有规定:
(1)如果两个对象相同,那么它们的哈希码一定相同;
(2)如果两个对象的哈希码相同,它们不一定相同。
补充:equals方法必须满足自反性(x.equals(x)必须返回 true)、对称性(x.equals(y)返回 true 时,y.equals(x)也必须返回 true)、传递性(x.equals(y)和 y.equals(z)都返回 true 时,x.equals(z)也必须返回 true)和一致性(当 x 和 y 引用的对象信息没有被修改时,多次调用 x.equals(y)应该得到同样的返回值),而且对于任何非 null 值的引用 x,x.equals(null)必须返回 false。
十、是否可以继承String类?
String类是final修饰的类,不可以被继承。
补充:为什么String被修饰为final?
迫使String类设计成不可变的原因是安全,当你调用一些系统级操作指令之前,可能会进行一系列校验,如果是可变类的话,可能在你校验完成之后,它的内部的值就变了,这样可能会引起严重的系统崩溃问题。另一个就是高效,只有字符串是不可变时,我们才能实现字符串常量池,字符串常量池可以为我们缓存字符串,提高程序的运行效率。
十一、Java会存在内存泄漏吗?简单描述一下。
理论上Java因为有垃圾回收机制(GC)不会存在内存泄漏问题;
然而在实际开发中,可能会存在无用但可达的对象,这些对象不会被GC回收,因此会导致内存泄漏的发生。例如,Hibernate 的 Session(一级缓存)中的对象属于持久态,垃圾回收器是不会回收这些对象的,然而这些对象中可能存在无用的垃圾对象,如果不及时关闭(close)或清空(flush)一级缓存就可能导致内存泄露。
十二、GC是什么?为什么要有GC?
GC是垃圾收集的意思,内存处理是编程人员容易出问题的,Java提供的GC功能可以自动监测对象是否超过作用域而达到自动回收内存的目的。不用担心内存管理,因为垃圾收集器会自动进行管理。
十三、String s = new String(“xyz”); 创建了几个字符串对象?
两个;一个是静态区的"xyz",一个是用new创建在堆上的对象。
十四、接口是否可继承(extends)接口?抽象类是否可实现(implements)接口?抽象类是否可继承具体类(concrete class)?
接口可以继承接口,而且支持多重继承。抽象类可以实现接口,抽象类可以继承具体类也可以继承抽象类。
十五、抽象类和接口有什么异同?
相同:
- 不能实例化
- 可以将抽象类和接口作为引用类型
- 一个类如果继承了某个实现类或者实现了某个接口,都需要对其抽象方法进行全部实现
不同:
- 抽象类中可以定义构造器,接口中不能定义构造器
- 抽象类中可以有抽象方法和具体方法,接口中的方法全是抽象方法
- 一个类只能继承一个抽象类,一个类可以实现多个接口
- 抽象类中可以有静态方法,接口中不能有静态方法
- 抽象类中的成员可以是public、private、默认和protected,接口中的成员只能是public
- 抽象类中可以定义成员变量,接口中定义的成员变量实际上是常量
十六、抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被 synchronized 修饰?
都不能。
- 抽象方法需要子类重写,而静态方法不能被继承,所以二者是矛盾的
- 本地方法是由本地代码实现的方法,而抽象方法是没有实现的,也是矛盾的
- synchronized 和方法的实现细节有关,抽象方法不涉及实现细节,所以也会矛盾的
十七、阐述静态变量和实例变量的区别?
静态变量是被static修饰符修饰的变量,也称为类变量,它属于类,不属于任何一个对象,一个类不管有几个对象,静态变量在内存中有且仅有一个拷贝;实例变量必须依存于某一实例,需要先创建对象然后通过对象才能访问到它,静态变量可以实现让多个对象共享内存。
十八、一个”.java”源文件中是否可以包含多个类(不是内部类)?有什么限制?
可以,但是一个源文件中最多只能有一个公共类(public class) 而且文件名必须和公开类的类名保持一致。
十九、Java中final关键字有哪些用法?
- 修饰类:表示该类不能被继承
- 修饰方法:表示该方法不能被重写
- 修饰变量:表示变量只能一次赋值,以后值不可被修改(相当于常量)
二十、final、finally、finalize的区别?
- final:修饰符有三种用法:修饰类,表示该类不能派生子类;修饰变量,表示该变量只能一次赋值,且不能被修改;修饰方法,表示该方法不能被重写
- finally:通常放在try…catch…后面,程序无论正常执行还是发生异常,这里的代码只要JVM不关闭都能执行,可以将释放资源的代码写在finally中
- finalize:Object类中定义的方法,Java中允许使用finalize()方法在垃圾收集器将对象从内存中清除之前做一些必要操作。这个方法是垃圾收集器在销毁对象是调用的,通过重写finalize()方法可以整理系统资源或者执行其他清理工作
二十一、try{}里面有一个return语句,那么紧跟在try后的finally{}里的代码会不会被执行?什么时候被执行?在return前还是后?
会执行,在方法返回调用者前执行,准确说只在return中间执行。
public class Test06 {
@SuppressWarnings("static-access")
public static void main(String[] args) {
System.out.println("结果: " + new Test06().test());
}
static int test(){
int i = 1;
try {
System.out.println("try里面的i : " + i);
return i;
}finally{
System.out.println("进入finally...");
++i;
System.out.println("fianlly里面的i : " + i);
}
}
}
这说明了,finally中的代码是执行了的,但是为什么结果是1?
因为在try中,要执行return,此时,要返回的结果已经准备好了,也就是1,但是同时程序转到finally执行。但是在执行完finally后,对变量的修改并不会影响返回结果。
二十二、Java中如何实现异常处理?
Java中的异常处理是通过五个关键词来实现的:try、catch、finally、throw、throws
我们可以把可能产生异常的代码块放入try…catch中处理,把资源回收方法finally中,无论发生什么异常,finally都会执行。
throw和throws的区别:
- 位置不同,throw在方法内部,throws在方法声明处;
- 内容不同:1.throw + 异常对象(检查异常,运行时异常) 2.throws + 异常的类型(可以是多个类型,使用逗号拼接)
- 作用不同:1.throw:异常出现的源头,制造异常 2.在方法的声明处,告诉调用者可能会发生这个异常,调用者对这些异常进行处理(要么进行处理,要么继续向上抛出)
二十三、运行时异常和受检异常有何异同?
运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误,只要程序设计得没有问题,通常就不会发生。
受检异常跟程序运行的上下文环境有关,即使程序设计无误,仍然可能因使用的问题而引发。
对可以恢复的情况使用受检异常,对编程错误使用运行时异常
Java 编译器要求方法必须声明抛出可能发生的受检异常,但是并不要求必须声明抛出未被捕获的运行时异常。
二十四、列出常见的运行时异常
- ArithmeticException(算术异常)
- ClassCastException (类转换异常)
- IllegalArgumentException (非法参数异常)
- IndexOutOfBoundsException (下标越界异常)
- NullPointerException (空指针异常)
- SecurityException (安全异常)
二十五、Error和Exception有什么区别?
Error表示系统级的错误和程序不必处理的异常,是恢复不是不可能,但是很困难的情况下的一种严重问题,例如:内存溢出,程序是不能处理这样的情况
Exception表示需要捕获或者需要程序进行处理的异常,是一种设计或者实现问题,也就是说它表示如果程序运行正常,从不会发生的情况
二十六、List、Set、Map 是否继承自 Collection 接口?
List、Set是,Map不是,Map是键值对映射容器,与List和Set有明显的区别,而Set存储的零散的元素且不允许有重复元素,List是线性结构的容器,适用于按数值索引访问元素的情形。
二十七、Collection 和 Collections 的区别?
Collection是一个接口,它是Set、List等容器的父接口;
Collections是一个工具类,提供了一系列的静态方法来辅助容器操作,这些方法包括对容器的搜索、排序、线程安全化等。
二十八、List、Set、Map三个接口存取元素时,各有什么特点?
List以特定的索引来存取元素,可以有重复的元素;
Set不能存放重复元素(用equals()方法来区分元素是否重复);
Map保存键值对(key-value pair)映射,映射关系是一对一或一对多。
Set和Map容器都有基于哈希存储和排序树两种实现版本:
基于哈希存储的版本理论存取时间复杂度为O(1);
而基于排序树版本的实现在插入或删除元素时会按照元素的键构成排序树从而达到排序和去重的效果。
二十九、线程的sleep()和yield()方法有什么区别?
- sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给优先级低的线程以机会;yield()方法只会给相同级别的或者更高优先级的线程以运行的机会;
- 线程执行sleep()方法后转入阻塞状态,而执行yield()方法没有声明任何异常;
- sleep()方法比yield()方法具有跟好的可移植性。
三十、当一个线程进入一个对象的 synchronized 方法 A 之后,其它线程是否可进入此对象的 synchronized 方法 B?
不能。其他线程只能访问该对象的非同步方法,同步方法则不能进入。因为非静态方法上的synchronized修饰符要求执行方法时要获得对象的锁,如果已经进入A方法说明对象锁已经被取走,那么食欲进入B方法的线程就只能在等锁池中等待对象的锁。
三十一、synchronized关键字的用法?
synchronized关键字可以将对象或者方法标记为同步,以实现对象和方法的互斥访问,可以用synchronized(对象){ … }定义同步代码块,或者在声明方法时将synchronized作为方法的修饰符。
三十二、举例说明同步和异步
事实上,所谓的同步就是指阻塞式操作,而异步就是非阻塞式操作
同步:
- 如果系统中存在临街资源(资源数量少于竞争资源的线程数量的资源),例如正在写的数据以后可能被另一个线程读到,或者正在读的数据已经被另一个线程写过了,那么这些数据必须进行同步存取
异步:
- 当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待的返回时,就应该用异步编程,在很多情况下采用异步编程更有效率
三十三、阐述JDBC操作数据库的步骤
- 加载驱动
Class.forName("com.mysql.jdbc.Driver");
- 创建连接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "userroot", "pwdroot");
- 创建语句
PreparedStatement ps = con.prepareStatement("select * from emp where sal between ? and ?");
ps.setInt(1, 1000);
ps.setInt(2, 3000);
- 执行语句
ResultSet rs = ps.executeQuery();
- 处理结果
while(rs.next()) {
System.out.println(rs.getInt("empno") + " - " +
rs.getString("ename"));
}
- 关闭资源
finally {
if(con != null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
注意:关闭资源的顺序应该是和打开的顺序相反。
三十四、Statement 和 PreparedStatement 有什么区别?哪个性能更好?
- PreparedStatement 接口代表预编译的语句,主要的优点是在于可以减少SQL的编译错误并增加SQL的安全性(减少SQL注入攻击的坑可能性);
- PreparedStatement 中的SQL语句是可以带参数的,避免了用字符串连接拼接SQL语句的麻烦和不安全;
- 当批量处理SQL或频繁执行相同的查询时,PreparedStatement 有明显的性能优势,由于数据库可以将编译优化后的SQL语句缓存起来,下次执行相同结构的语句会很快
三十五、简述一下你了解的设计模式
所谓设计模式就是一套被反复使用的代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被理解、保证代码可靠性。
- 工厂模式:工厂类可以根据条件生成不同的子类实例,这些子类有一个公共的抽象父类并且实现了相同的方法,但是这些方法针对不同的数据进行了不同的操作。当得到子类实例后,开发人员不可以调用基类中的方法而不必考虑到底返回哪一个子类的实例;
- 代理模式:给一个对象提供了一个代理对象,并由代理对象控制原对象的引用。在实际开发中,按照使用目的的不同,代理可以分为:远程代理、虚拟代理、保护代理等
- 适配器模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起使用的类能够工作