javase疑惑记录
1、为什么重写 equals 还要重写 hashcode?
重写equals,还要重写hashcode,是因为如果不重写hashcode,两个对象的hashcode值可能还是不同的,此时不满足hashmap中判断为同一个对象的条件,而会被认为是两个对象。重写hashcode,要对我们比较的属性都进行hash,从而保证了他们的hashcode也是一样的。
2、== 和 equals 比较的区别
比较的对象不同. 1、equals ():用来检测两个对象是否相等,即两个对象的内容是否相等。. 2、==:用于比较引用和比较基本数据类型时具有不同的功能,具体如下:. (1)、基础数据类型:比较的是他们的值是否相等,比如两个int类型的变量,比较的是变量的值是否一样。. (2)、引用数据类型:比较的是引用的地址是否相同,比如说新建了两个User对象,比较的是两个User的地址是否一样。
3.为啥有时会出现 4.0 - 3.6 = 0.40000001 这种现象?
这种舍入误差的主要原因是:浮点数值采用二进制系统表示, 而在二进制系统中无法精确地表示分数 1/10。这就好像十进制无法精确地表示分数 1/3—样。
如果在数值计算中不允许有任何舍入误差, 就应该使用 BigDecimal类(Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。 双精度浮点型变量double可以处理16位有效数,但在实际应用中,可能需要对更大或者更小的数进行运算和处理。)
由于在运算的时候,float类型和double很容易丢失精度,所以浮点数值不适用于无法接受舍入误差的金融计算中。例如,命令 System.out.println ( 2.0-1.1 ) 将打印出 0.8999999999999999, 而不是人们想象的 0.9。
4.为什么二进制无法精确表示1/10
其实跟数位表示法有关,比如十进制的情况下:123,相当于1102+2*101+3100(值*进制位置,个位0,十位1,百位2)0.75也能够表示,因为它可以表示成为1/2+1/(22).0.875也能够表示,因为它可以表示成为1/2+1/(22)+1/(2^3) 但是0.1不能够精确表示,因为它不能表示成为1/(2^n)的和的形式
5.final 关键字的作用
1、用来修饰一个引用
如果引用为基本数据类型,则该引用为常量,常与static关键字一起使用,该值无法修改;
如果引用为引用数据类型,比如对象、数组,则该对象、数组本身可以修改,但指向该对象或数组的地址的引用不能修改。
如果引用时类的成员变量,则必须当场赋值,否则编译会报错。
2.用来修饰一个方法
当使用final修饰方法时,这个方法将成为最终方法,无法被子类重写。但是,该方法仍然可以被继承。
3.用来修饰类
当用final修改类时,该类成为最终类,无法被继承。简称为“断子绝孙类”。例如String
优点:
final关键字提高了性能。JVM和Java应用都会缓存final变量。
final变量可以安全的在多线程环境下进行共享,而不需要额外的同步开销。
使用final关键字,JVM会对方法、变量及类进行优化。
不可变类
不可变类有很多好处,譬如它们的对象是只读的,可以在多线程环境下安全的共享,不用额外的同步开销等等。
关于final的重要知识点:
在匿名类中所有变量都必须是final变量。
final关键字容易与finalize()方法搞混,后者是在Object类中定义的方法,是在垃圾回收之前被JVM调用的方法。
接口中声明的所有变量本身是final的。
接口的含义.接口就是提供一种统一的’协议’,而接口中的属性也属于’协议’中的成员.它们是公共的,静态的,最终的常量.相当于全局常量.
抽象类是不’完全’的类,相当于是接口和具体类的一个中间层.即满足接口的抽象,也满足具体的实现.
如果接口可以定义变量,但是接口中的方法又都是抽象的,在接口中无法通过行为来修改属性。有的人会说了,没有关系,可以通过实现接口的对象的行为来修改接口中的属性。这当然没有问题,但是考虑这样的情况,因为接口中的数据对所有实现类只有一份,所以是static。如果接口A中有一个public访问权限的静态变量a。按照java的语义,我们可以不通过实现接口的对象来访问变量a,通过A.a = xxx;就可以改变接口中的变量a的值了。正如抽象类中是可以这样做的,那么实现接口A的所有对象也都会自动拥有这一改变后的a的值了,也就是说一个地方改变了a,所有这些对象中a的值也都跟着变了。这和抽象类有什么区别呢,怎么体现接口更高的抽象级别呢,怎么体现接口提供的统一的协议呢,那还要接口这种抽象来做什么呢?所以接口中不能出现变量,如果有变量,就和接口提供的统一的抽象这种思想是抵触的。所以接口中的属性必然是常量,只能读不能改,这样才能为实现接口的对象提供一个统一的属性。
通俗的讲,你认为是要变化的东西,就放在你自己的实现中,不能放在接口中去,接口只是对一类事物的属性和行为更高层次的抽象。对修改关闭,对扩展(不同的实现implements)开放,接口是对开闭原则的一种体现。
final和abstract这两个关键字是反相关的,final类就不可能是abstract的。
final方法在编译阶段绑定,称为静态绑定(static binding)。
final成员变量必须在声明的时候初始化或者在构造器中初始化,否则就会报编译错误。本地变量必须在声明时赋值。没有在声明时初始化final变量的称为空白final变量(blank final variable),它们必须在构造器中初始化,或者调用this()初始化。不这么做的话,编译器会报错“final变量(变量名)需要进行初始化”。
将类、方法、变量声明为final能够提高性能,这样JVM就有机会进行估计,然后优化。
按照Java代码惯例,final变量就是常量,而且通常常量名要大写:
private final int COUNT = 10;
对于集合对象声明为final指的是引用不能被更改,但是你可以向其中增加,删除或者改变内容
6.多态有几种表现形式
1、方法的重载:通常是指在同一个类中,相同的方法名对应着不同的方法实现,这些方法名相同的方法其区别在于他们的参数不同;
2、方法的重写:方法的重写主要用于父类和子类之间,子类重写父类的方法,只是对应的方法实现不同,方法名和方法参数都相同;
3、抽象类:在面向对象语言中,一个类中的方法只给出了标准,而没有给出具体的方法实现,这样的类就是抽象类。例如父类就可以是抽象类,抽象类是不能被实例化的类;
4、接口:在多态机制中,接口比抽象类使用起来更加方便。而抽象类组成的集合就是接口。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律