当前位置: 首页 > 科技观察

Java常见的30个误区和细节!

时间:2023-03-12 16:22:28 科技观察

1。在Java中,没有goto语句。因为大量使用goto语句会降低程序的可读性和可维护性,所以Java语言取消了goto的使用。同时,为了避免程序员自己使用goto造成的混乱,Java语言仍然将goto定义为关键字,但没有定义任何语法,所以称为“保留字”。2、虽然true、false、null在IDE中以不同的颜色显示,但它们不是关键字,而是“字面常量”,就像String类型的abc一样。3、定义名称时尽量避免使用$,因为编译器在编译.java文件时,会把“$”编译成顶层类型和底层类型之间的连接符。看下面的例子:编译(javacTest3.java)这段代码时,编译器会报如下错误:Test.java:12:Error:Duplicateclass:com.javastack.Test.Outer.InnerclassInner{^4UnicodeescapecharacterProcessedvery早期,在解析器之前。例如:这两行代码出现在程序中,编译时报错。这两个Unicode编码分别表示“换行”和“回车”,所以编译器编译时,代码是这样的:5.Unicode编码使用16位字符编码,在Java中用char类型表示。现在Unicode已经扩展到100万个字符,超出16位限制的就变成了增补字符。所有增补字符都不能用字符常量来表示。6、short、byte、char参与运算时,结果都是int类型,与higher类型不一样。如果变量是byte、short或byte类型,当它被赋值一个编译时常量,并且该常量不超过变量的取值范围时,编译器可以进行隐式收缩转换。这种隐式收缩转换是安全的,因为收缩转换只适用于变量的赋值,不适用于方法调用语句,即不适用于方法调用时的参数传递。(详见java中默认类型转换的小问题)7、注意char类型,它是unsigned类型。因此,char与short或char与byte之间的转换必须显式使用类型转换。byte到char的转换是扩缩转换,比较特殊,就是先把byte扩充转换成int,再收缩成char。8、整型数据之间的扩展转换,如果操作数是char类型(无符号类型),则进行无符号扩展,扩展位为0。如果操作数是byte、short或int(有符号类型),则Sign扩展为执行,扩展位为变量的符号位。9、整数数据之间的收缩转换只是截断和丢弃高位,不做任何其他处理。10.0.1+0.2不等于0.3.System.out.println((double)0.1+(double)0.2);该语句的输出是0.30000000000000004。因为计算机是用二进制来存储数据的,而很多小数是不能用二进制准确表示的(其实大部分小数都是近似值),就像1/3这样的分数是不能用十进制的小数来准确表示的。大多数浮点类型在计算机中近似地存储它们的值,不如整数准确。另一个例子,这是一个无限循环:for(floatf=10.1f;f!=11;f+=0.1f){}11。float类型可以保留7-8位有效数字,而double类型可以保留15-16位有效数字,所以当int类型或long类型的值的有效位数比double或float多时,将部分最高有效位值将丢失,从而导致精度损失。此时会使用IEEE754最近舍入模式,提取最接近整数值的浮点值。整数类型到浮点数类型的转换虽然是扩展转换,但是当值很大或很小(绝对值很大)时,都会产生一定的精度损失。12.如何计算i+++j?(这个问题在C/C++中讨论),因为C/C++依赖于实现的硬件结构,不同环境的结果会有所不同。但在Java中,这个结果是固定的,不受其运行的硬件环境和平台的影响)答:根据贪心法则,前置++优于后置++,结果为(i++)+j13.i++和++i其实都是先+1再赋值。++i,无话可说;i++,取j=i++;例如,底层实现是:temp=i;i=i+1;j=temp;所以,我=15;我=我++;这个表达式的结果是15。(因为加1后进行赋值,从16变成15)14.+0和-0在浮点变量的存储中符号位不同。当-0和+0参与浮点相关运算(如除法、取余运算)时,会产生不同的结果。15.浮点数的除法求余运算不同于整型的除法求余运算。当除数为0时,浮点运算不会产生ArithmeticException。16.String类是一个非变量类,它的对象一旦创建就不能销毁。String类的那些看似修改字符序列的方法,实际上返回的是新创建的String对象,而不是修改对象本身。17、由于String对象是不可变的,所以是线程安全的,可以自由共享。18、String类内部,使用了一个字符数组(char[])来维护字符序列。String的最大长度也是字符数组的最大长度。理论上,最大长度是int类型的最大值,即2147483647。实际中,一般能得到的最大值小于理论值。*价值。19.main()方法在性能和行为方面与其他方法基本相同。它可以被重载,被其他方法调用,继承,隐藏,也可以抛出带类型参数的异常。我们也可以在程序中通过反射调用main方法(或其他方法)。20.当两个或多个方法的名称相同但参数列表不同时,这些方法就构成重载。重载方法可以根据参数列表的类型和参数个数来区分。但是,参数名称、方法返回类型、方法异常列表和参数类型不能作为区分重载方法的条件。21.调用哪个方法,顺序如下:最后阶段不考虑自动装箱(拆箱)和可变参数,搜索对应的形参类型可以匹配实参类型和形参个数与具有相同数量实际参数的方法相同;如果第一步没有符合条件的方法,第二阶段会进行自动装箱和拆箱。如果第二步不存在符合条件的方法,则在第三阶段将考虑可变参数方法。如果三个阶段都没有找到符合条件的方法,就会产生编译错误。如果调节条件的方法不止一种,将选择最具体的方法。最清晰的方法定义为:如果方法A的形参列表的类型对应于方法B的形参列表的类型,则方法A比方法B更清晰。如果不能选择最具体的方法,则a会导致编译错误。22、重写和隐藏的本质区别是:重写是动态绑定的,根据运行时引用指向的对象的实际类型调用相关类的成员。hidden是静态绑定的,要调用的相关成员根据编译时引用的静态类型来决定。也就是说,如果子类重写了父类的方法,当父类的引用指向子类的对象时,通过父类的引用调用子类的方法。如果子类隐藏了父类的方法(成员变量),仍然通过父类的引用调用父类的方法(成员变量)。23.构造函数被递归调用。子类的构造函数会调用父类的构造函数,直到调用了Object类的构造函数。24.构造函数不创建对象。构造函数在使用new创建对象时被系统调用,用于初始化类的实例成员。从顺序上来说,先创建对象,再调用构造函数。(构造函数不生成新对象)25.默认构造函数不为空,这个构造函数会调用父类的无参构造函数,可能会进行实例成员变量的初始化。因此,默认构造函数至少调用了父类的构造函数,它可能会做更多的工作,包括实例变量声明初始化和实例初始化块,这些都是在构造函数中执行的。26.当==或!=运算符的两个操作数的类型是一个基本数据类型,另一个是包装类引用类型时,将引用类型拆箱并转换为基本数据类型,然后比较两个基本数据类型数据类型值是相等的。27、在Java中,数组也是一个类,数组声明的引用变量指向数组类型的对象。所有数组都继承了Object类并实现了java.lang.Cloneable和java.io.Serializable接口。数组的成员包括可变长度(隐式存在)和从Object类继承的成员。Cloneable和Serializable是两个标记的接口,其中没有显式声明成员。28、接口是完全抽象的设计,不能实例化。A使用new方法创建的接口类型实际上是创建了一个实现该接口类型的匿名类。29、如果两个接口都声明了同一个变量x,当一个接口同时继承这两个接口,或者某个类同时实现了这两个接口时,通过简单名称访问会导致编译错误。30、如果在两个接口中声明了一个同名的方法m,并且这两个方法不构成重载,那么当一个接口可以继承两个接口,或者一个类可以继承两个接口时,必须存在一个方法签名,使得签名同时是两个m方法签名的子签名,并且在方法的返回类型上,必须有一个类型使该类型同时成为两个m方法返回类型的替代类型时间。