JavaSE面试题(倒背如流版)
1、Float在JVM的表达方式及使用陷阱
//请写出本题的执行结果,并说明原因 float d1 = 423432423f; float d2 = d1+1; if(d1==d2){ System.out.println("d1 == d2"); }else{ Syetem.out.println("d1 != d2"); }
答案:为相等的,因为单精度的float浮点型在JVM内存中是以科学计数法进行表示的,
4.2343242E7,只保留到了小数点后的七位,那么d1与d2同样都是4.2343242E7
因此高精度的用double类型保存,尤其是在银行业务中,最好使用BigDecimal类进行加减乘除的运算。
2、随机生成30~100之间的整数
两种方法:
1)利用Math类的random()方法
2)java.util包下Random类的nextInt()方法
/** * 利用java.util包下的Random类的nextInt()方法,参数设置上限,下限默认为0 * @return 30~70随机整数 */ public Integer randomInt1() { int min = 30; int max = 100; int result = new Random().nextInt(max - min) + min; return result; } /** * Math工具类的random()方法,生成0~1的小数,手动扩大范围 * @return 30~70随机整数 */ public Integer randomInt2() { int min = 30; int max = 100; //先生成0~1的随机小数,×70 : 0~70 随机小数; +30 : 30~70随机小数; int result = (int) (Math.random() * (max - min)) + min; return result; }
3、 列出1-1000的质数
public static void main(String[] args) { for (int i = 2; i <= 1000; i++) { boolean flag = true; for (int j = 2; j < i; j++) { if(i%j == 0){ flag = false; break; } } if (flag) { System.out.println(i); } } }
4、 静态和实例变量(方法)的区别
- 实例变量属于某个对象的属性,只有使用new关键字实例化对象后才能使用;
静态变量属于类本身。 - 静态变量在JVM加载类字节码时创建,实例变量在实例化对象时创建。
- 静态变量无法被垃圾回收释放,实例变量不再使用后会被回收
- 静态变量存储在方法区中、实例变量存储在对象堆的内存中
- 开发时推荐优先使用实例变量而减少静态变量的使用
5、类的加载顺序
原则:
1. 静态优先
2. 父类优先
3. 非静态块优先于构造函数
//请写出程序输出结果 //1. 静态优先 //2. 父类优先 //3. 非静态块优先于构造函数 public class ExecutionSequence { public static void main(String[] args) { new GeneralClass(); } } class ParentClass{ static { System.out.println("①我是父类静态块"); } { System.out.println("②我是父类非静态块"); } public ParentClass(){ System.out.println("③我是父类构造函数"); } } class GeneralClass extends ParentClass{ static{ System.out.println("④我是子类静态块"); } { System.out.println("⑤我是子类非静态块"); } public GeneralClass(){ System.out.println("⑥我是子类构造函数"); }
结果:
①我是父类静态块 ④我是子类静态块 ②我是父类非静态块 ③我是父类构造函数 ⑤我是子类非静态块 ⑥我是子类构造函数
5、Java异常体系
- Exception必须进行强制处理,try..catch..或者抛出
- RuntimeException代表应用程序运行过程中产生的异常,它及它的子类并不需要显示处理,在编码阶段不要求强制进行处理。
6、String与字符串常量池
- true
- true
- false (s2是引用类型的,编译器在编译期间无法确定它的数值,这就意味着无法使用编译器对其进行优化,只有在运行时才能确定s2具体的值,因此即便s2+"def"等于"abcdef",也会产生一个新的内存地址,同时分配给s5,那么s4与s5的内存地址不再相等,于是返回false)
- true (String类的equals方法比较的是字符串的内容)
- false (s1的"adc"会存储在常量池中,而s6的new String("abc")不会在常量池中保存)
7、 String、StringBuffer、StringBuilder的区别
- String : 数据存放在常量池中,且由final修饰,每一个String创建后便不再发生变化。
- StringBuffer: 使用sychronize关键字修饰,实现了线程同步。
8、面向对象的三大特征
- 继承
1) 面向对象最显著的特征
2)从已有的类中派生出新的类,新的类可以吸收已有类的属性和行为,并扩展新的功能
3)Java中并不支持多继承,单继承使得Java的继承关系很简单,一个类只能有一个父类,易于管理
4)父类也是子类的抽象化,子类是父类的具体化
5)在使用的过程中,继承主要的作用主要应用在对代码的抽象上,比如一个类的功能是向表A插入数据,另一个类是向表B插入数据,而向数据表插入数据前都需要获得数据库的连接,那么此时可以对这两个类抽象出一个父类,对获取数据库连接的方法进行抽象,这样子类只需要关注对具体的数据插入的操作就可以了,而获取连接的工作就交给它的父类自动完成。
继承的好处:
减少程序开发的重复度,同时增加了程序的健壮性
- 封装
1)将同一类事务的特征和功能包装到一起,只暴露对外调用的接口
2)封装也称为信息的隐藏,封装最典型的体现就是定义接口,接口中没有功能的实现,只有抽象的方法声明,作用就是每一个接口的实现类对接口进行实现,但是调用的时候通常是面对接口进行调用,对于使用者来说,只需要知道接口定义了哪些方法,这些方法是做什么的就可以了。对于接口内部的执行的操作不需要了解。
封装的好处:
1> 实现专业的分工,使用者与开发者分工明确
2> 减少代码的耦合,面向接口
3> 类内部的结构可以自由修改,只要接口的定义没有变化,使用者是无法感知到的
接口与抽象类的异同
抽象类就是父类
注意:JDK8以上版本,接口可以有default方法,包含方法的实现
- 多态
1)最重要的操作
2)多态是同一个行为具有多个不同表现形式或形态的能力
3)多态是同一个接口,使用不同的实例而执行不同操作(例如有一个导出的接口,在这个接口下有两个实现类,一个是导出Excel一个是导出txt文本)
=============集合框架===============
1、请说明List与Set的区别
List按照插入时的顺序依次保存,而Set无序或者需要自定义排序规则
ArrayList与LinkedList的区别
Arraylist数据之间紧密相连
HashSet与TreeSet的区别
- Hash值的生成具有不确定性,故不能保证前后顺序
- TreeSet在创建时可以设置一个排序规则
2、熟练使用Collection.sort()方法对List进行排序(实现Comparetor接口,实现其compare()方法,可基于Lambda表达式与泛型简化代码)
3、熟练使用两种方法对TreeSet进行排序
1)Java Bean 实现 compareble接口,这种又被称为自然排序
public class Employee implements Comparable<Employee>{ //TreeSet采用红黑树进行实现,compareTo方法如果返回-1,则代表把传入至参数中的Employee对象放在红黑树的左子树,降序排列;返回1则代表升序排列,放在红黑树的右侧。 @Override public int compareTo (Employee o){ // 当前对象比传参对象的age属性大,返回1; // 小则返回-1; // 相等返回0,取前面的元素 return this.getAge().compareTo(o.getAge()); } }
2) 在实例化TreeSet时实现Comparator接口,自定义排序规则
TreeSet<Employee> emps = new TreeSet<Employee>(new Comparator<Employee>( @Override public int compare(Employee o1 , Employee o2){ return (int)(o1.getSalary() - o2.getSalary()); } ));
Object类hashCode()和equals()的区别
1)equals()方法用来判断两个对象是否 “相同”
2)hashCode()返回一个int,代表“将该对象内存中的地址”,不同的对象也可能产生相同的哈希值