1、hashCode 和identityHashCode有什么区别?
hashCode是根据内容来计算值的,identityHashCode是根据地址来计算值的。
String a=new String("a");
String b=new String("b");
String c="c";
String d="c";
System.out.println(a.hashCode());
System.out.println(b.hashCode());
System.out.println(System.identityHashCode(a));
System.out.println(System.identityHashCode(b));
System.out.println(c.hashCode());
System.out.println(d.hashCode());
System.out.println(System.identityHashCode(c));
System.out.println(System.identityHashCode(d));
输出结果为:
97
98
381259350
2129789493
99
99
668386784
668386784
2、什么是hash冲突
数据结构中学过,散列表是通过一个hash函数来计算地址的,但是如果不同的值计算得到相同的值那么就是hash冲突。解决办法主要有两个,1、开放地址法,2、拉链法。其中开放地址法又可以根据计算下一个地址方式的不同分为 线性探测法,平方探测法,再散列法,伪随机数法。
3、Java中的关于钱的计算怎么避免精度丢失?
需要精确的表示两位小数时,将其转换为BigDecimal 对象,构造BigDecimal 对象时最好使用BigDecimal(String val)构造方法。
4、Java中的语法糖是什么意思?
语法糖(Syntactic Sugar),也称糖衣语法,是由英国计算机学家 Peter.J.Landin(彼得·兰丁) 发明的一个术语,指在计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。语法糖就是对现有语法的一个封装。简而言之,语法糖让程序更加简洁,有更高的可读性。
Java中的语法糖主要有:switch语句支持String与枚举、泛型和类型擦除、自动装箱与拆箱、方法边长参数、枚举、内部类、条件编译、断言、数值字面量、增强for循环、try-with-resources语句、Lambda表达式等。这篇文章里对Java的语法糖及其原理有比较深入的讲解。
5、Class.forName()和ClassLoader()有什么区别?
在 java 中 Class.forName() 和 ClassLoader 都可以对类进行加载。ClassLoader 就是遵循双亲委派模型最终调用启动类加载器的类加载器,实现的功能是“通过一个类的全限定名来获取描述此类的二进制字节流”,获取到二进制流后放到 JVM 中。Class.forName() 方法实际上也是调用的 ClassLoader 来实现的。
Class.forName()除了会将类的.class文件加载到JVM中外,还会对类进行解析,执行其中的static初始代码块。
6、什么是宏变量和宏替换?
Java中,一个用final定义的变量,不管它是类型的变量,只要用final定义了并同时指定了初始值,并且这个初始值是在编译时就被确定下来的,那么这个final变量就是一个宏变量。编译器会把程序所有用到该变量的地方直接替换成该变量的值,也就是说编译器能对宏变量进行宏替换。
7、Optional类有什么用?
optional类主要是为了解决空指针引用的问题,本质上,这是一个包含有可选值的包装类,这意味着 Optional 类既可以含有对象也可以为空。
public static void main(String[] args){
Integer value1=null;
Integer value2=2;
//如果可能为空就选择ofNullable方法
Optional<Integer> num1=Optional.ofNullable(value1);
//如果必须保证其不能为null就选择of方法
Optional<Integer> num2=Optional.of(value2);
System.out.println(Offer.add(num2,num1));
}
public static Integer add(Optional<Integer>a,Optional<Integer> b){
Integer num1=a.get(); //get方法如果返回空还是会抛出异常
Integer num2=b.orElse(10); //如果获得的是null,那么用10替代
b.ifPresent(n->{System.out.println("参数2存在");});
//可以根据是否存在做不同的动作
b.ifPresentOrElse(n->{System.out.println("参数存在");},
()->{System.out.println("参数不存在");});
return num1+num2;
}
8、Java中方法引用是指什么?
9、Java中函数式编程怎么用?
Lambda 表达式,有时候也称为匿名函数或箭头函数,Java8 中引入 Lambda 表达式,使原本需要用匿名类实现接口来传递行为,现在通过 Lambda 可以更直观的表达。
- Lambda 表达式,也可称为闭包。闭包就是一个定义在函数内部的函数,闭包使得变量即使脱离了该函数的作用域范围也依然能被访问到。
- Lambda 表达式的本质只是一个”语法糖”,由编译器推断并帮你转换包装为常规的代码,因此你可以使用更少的代码来实现同样的功能。
- Lambda 表达式是一个匿名函数,即没有函数名的函数。有些函数如果只是临时一用,而且它的业务逻辑也很简单时,就没必要非给它取个名字不可。
- Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中).
- Lambda 表达式语法如下:形参列表=>函数体(函数体多于一条语句的可用大括号括起)。在Java里就是() -> {}:
函数式接口
Java 8 中采用函数式接口作为Lambda 表达式的目标类型。函数式接口(Functional Interface)是一个有且仅有一个抽象方法声明的接口。任意只包含一个抽象方法的接口,我们都可以用来做成Lambda表达式。每个与之对应的lambda表达式必须要与抽象方法的声明相匹配。函数式接口与其他普通接口的区别:
- 函数式接口中只能有一个抽象方法(这里不包括与Object的方法重名的方法)
- 接口中唯一抽象方法的命名并不重要,因为函数式接口就是对某一行为进行抽象,主要目的就是支持 Lambda 表达式
- 自定义函数式接口时,应当在接口前加上@FunctionalInterface标注(虽然不加也不会有错误)。编译器会注意到这个标注,如果你的接口中定义了第二个抽象方法的话,编译器会抛出异常。
Java中比较常用的函数式接口有Runable, Callable, Comparator.
//Runnable
new Thread(()->{
System.out.println("threan1");
},"thread1").start();
//callable接口
ExecutorService pool= Executors.newCachedThreadPool();
pool.submit(()->{
System.out.println("callable");
},"call1");
pool.shutdown();
10、Java事件机制包含哪三部分?
包含事件,事件监听器,事件源三部分。
11、Comparable和Comparator的区别
如果一个类要和自己进行比较,那么需要实现Comparator接口,因此可以把Comparable认为是一个内比较器,其核心方法是compareTo(),一个简单的例子如下:
class Car implements Comparable{
public String name;
public double price;
@Override
public int compareTo(Object o) {
Car car=(Car)o;
if(this.price>=car.price){
return 1;
}
else if(this.price==car.price){
return 0;
}
else {
return -1;
}
}
}
Comparator可以认为是是一个外比较器,用来给外部的类提供比较,核心方法是compare(),当一个序列需要进行比较的时候,就可以借助到它了,例子如下:
class DescriCar implements Comparator<Car>{
@Override
public int compare(Car o1, Car o2) {
if(o1.price>o2.price){
return 1;
}
else if(o1.price==o2.price){
return 0;
}
else {
return -1;
}
}
}
比如对一个cars序列进行排序,就需要传入一个实现了comparator的比较器。
ArrayList<Car> cars=new ArrayList<>();
cars.add(new Car("奔驰",1000000.0));
cars.add(new Car("丰田",500000.0));
cars.add(new Car("五菱",80000.0));
//借助实现了comparator的比较器进行排序
cars.sort(new DescriCar());
持续更新中…