链接:https://www.zhihu.com/question/53312117/answer/134711192
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
一、java面向对象中的常见误区
1、String是属于非可变类的,它的对象一旦创建出来了就无法销毁。String里面那些看着像是修改了字符序列的方法事实上是返回新创建的string对象的,却不是用来修改自身对象。
2、string内部是通过一个字符数组( char[])进行维护字符序列的。字符数组的最大长度就是string的最大数组。通常来讲最大长度就是int类型的最大数值了。实际的实践当中,一般理论最大值大于可获取的最大值。
3、string对象是具有线程安全性,能自由实现共享,是无法改变。
4、main()的表现行为是可以重载和其他方法基本上相同,通过其他方法进行继承、隐藏、调用,也能够带着类型参数,抛出异常。程序员们也能在一个程序里面经过反射来调用main方法;;在有两个或两个以上的方法的名称相同但参数列表却不同时候,这些就形成了重载。重载是能够按照参数别表对应的个数和类型进行区别的,但参数的方法、名称的返回类型、类型参数和方法的异常不能看做是区分重载方法的条件。
5、正确的方法调用顺序:
第一步,自动拆箱(装箱)和可变参数不予考虑搜索对应参类型能够匹配实参类型并且形参个数和实参个数一样的方法;
假如第一步的方法不符合条件,在第二步里面自动拆箱和装箱将会执行。
假如第二步的方法不符合条件,在第三步里可变参数的方法将会作为一个考虑。
要是三个步骤的方法都不符合条件,就会产生编译错误。如果条件的方法多过一个,也会选择最明确的方法,这个最明确的方法定义为:假如A方法的形参列表类型对应的都能够赋值给B方法的形参列表类型,则A方法比B方法更加明确。如果不能选出最明确的方法也会产生编译错误。
6、隐藏与重写本质上面的区别在于:隐藏是静态绑定,按照编译时引用的静态类型和决定调用的,重写是动态绑定的,是按照运行时引用所指向对象的实际类型决定调用相关类型。从另一个方面来讲假如子类隐藏了父类,则通过父类引用调用的仍旧是父类的方法;另一方面子类要是重写了父类的方法,则父类引用指向子类对象时候,通过父类的引用调用的是子类方法。
7、当==或!=运算符的这两个操作数的类型其实是一个基本数据类型,则另外一个是包装类的引用类型时候,把引用类型拆箱转换为基本的数据类型时,再比较两个基本数据类型值是不是相等的。
8、构造器是递归调用的,父类的构造器是经过子类构造器调用的,一直到调用到Object类构造器为止。
9、在构造器没有创建对象时,构造器是在new创建对象的时候经过系统调用在初始化类的实例中使用的,在顺序上是先创建对象再调用构造器。
10、java里面的数组也是类、数组声明的引用变量指向对象是数组类型的。所有的数组都继承Object类型,并要实现java.io.Serializable和java.lang.Cloneable接口。数组包括了变量的隐士存在length和object类型继承的成员。Serializable和Cloneable是两个标记的接口,这两个接口没有显示任何组成成员。
11、默认的构造器不能空,这个构造器会调用父类的无参构造器,就可能执行实例成员变量初始化。因此默认的构造器基本上是调用了父类的构造器,包含了实例初始化块和实例变量声明初始化,这些都是在构造器里执行实现的,因此它工作可能是会更多点。
一、java语言常见的基础误区
12、java里面是没有goto语句。Goto语句使用多了会降低程序的可维护性以及可读性,因此在java里面早取消了goto语句。并且,为了避免程序员独自使用goto带来的混乱,java语言仍旧将goto定义成了一个没有任何语法的关键字,成为了“保留字”
13、false、true和null在ide里面虽然用不同的颜色显示,但就是一个字面常量就像是string类型的abc是一样,并不是什么关键字。
14、名称的定义尽量避免$的使用,因为编译器对.java文件进行编译的时候,会把$自动翻译成底层类型和顶层类型的连接符号。比如:
使用$定义变量名
package com.laixintao.Test;
public class Outer$Inner {
public static void main(String[] args)
{
Outer o = new Outer();
Outer.Inner i = o.new Inner();
i.innerPrint();
}
}
class Outer {
class Inner {
void innerPrint() {
System.out.println("Inner Print!");
}
}
}
packagecom.laixintao.Test;
publicclassOuter$Inner{
publicstaticvoidmain(String[]args){
Outero=newOuter();
Outer.Inneri=o.newInner();
i.innerPrint();
}
}
classOuter{
classInner{
voidinnerPrint(){
System.out.println("Inner Print!");
}
}
}
在编译( javac Test3.java )这段代码的时候,编译器会报以下错误: Test.java:12: 错误: 类重复: com.laixintao.Test.Outer.Inner class Inner{ ^
15、Unicode转义字符处理的非常早,在解析程序之前。
比如:
Unicode编译错误
// char c1 = '\u00a';
// char c2 = '\u00d';
// char c1 = '\u00a';
// char c2 = '\u00d';
在程序里面出现这两行代码编译错误的时候,这两个Unicode分别表示的是回车和换行,在编译器编译的时候,代码就是这样的:
Unicode编译
// char c1 = '
';
// char c2 = '
';
// char c1 = '
';
// char c2 = '
'
16、Unicode是用16个字符编码,在java里面用插入类型表示的。现在的Unicode已经发展成了一百万个字符了,超出16位限制的就成增补字符。全部的增补字符都是不可以用字符常量表示。
17、如果byte、short、char参加运算结果是int类型,却不是和较高的类型相同时。如果变量是byte、short、byte类型会对它赋予编译时期的常量,但这个常量有没有超过变量的取值范围的话,编译器就会对其进行隐式收索转换。这种转换方式是安全的,但它是能适用在变量的赋值,不适合用在方法的调用语句里面,就是不适用在方法调用的参数传递。
18、char类型是一个没有符号的类型。因此,short和char或者char和byte之间的转换一定是显示地适用类型转换。从byte到char的转换为扩展收缩转换,这个是比较特殊的转换方式,是先把byte换成int最后到char。
19、整型数据之间的扩展转换里面如果操作数是char类型,就会进行无符号扩展,扩展位是0.如果操作数是byte,int或者short就会进行有符号扩展,扩展的位是这个变量的符号位。
20、数据间的收缩转换是截断并丢弃高位,不会做任何的其他方面处理,计算机是通过二进制进行存储数据的,像很多小数据是不能够准确的通过二进制进行表示的,就好比十进制小数不能准确地表示1/3的分数一样。在计算机里的浮点型只是近似的存储其值而不是和整型一样的准确存储。
21、i+++j是怎么算的?这个问题事实上在C/C++上讨论是没有什么意义。C/C++是更依赖在现实的硬件结构,不同的环境结果也不相同。但是在java里面,这个结果是不变的,不会因为运行的硬件环境和平台的影响
22、 i++和++i事实上都是+1,再赋值。++i,没什么好说的;i++,以j=i++打比方在底层的实现是: temp = i;i = i + 1; j = temp; 因此,i=15;i=i++;这个表达式的结果是15.
23、点的求余运算和相处的不同和整型的求余运算和相除。在除数是0的时候,浮点运算是不会产生ArithmeticException异样现象。
三、Java接口中的误区
24、假如两个接口里面都声明了相同方法m,并且两个方法没有构成重载,那么在某个接口能够同事继承这个接口的时候,或某一类型能够同时继承这两个接口的时候,一定是会存在一种方法签名并让这个签名可以同一时间为两个m方法签名的子签名,在方法的返回类型上面一定会存在一种类型,让这两个m方法返回类型能够随时退换。
25、要是这两个接口说明了相同变量的x时候,当某个接口同时间继承这两个接口的时候,或另一类同时候实现这两个接口时候,就会经过简单名称访问会出现编译错误问题。
26、接口是按照抽象设计的,无法实例化。让A用new方式创建的借口类型,事实上是创建了一个匿名类型,这个匿名可以实现接口类型。
以上是基础的java语言中容易出现的一些问题,对于初学的小白来说还是非常的具有实用性的,其实java没有想象中的那么难,要有别的不懂问题欢迎在 有码互联 进行询问。相信你会越努力越幸运的。