Java易错总结
new
String s = new String(“XYZ”) 产生了几个对象
该语句会产生2个字符串对象:
- 一个是通过 ” ” 方式在
编译期
产生,存放在常量池
中 - 一个是通过new方式在
运行期
产生,存放在堆内存
中
但在运行时只会通过new方式产生一个对象
传递参数
java中的参数只能“按値”传递,且传递的是値的 copy
如是基本类型,则传递的是基本类型的副本
如是引用类型,则传递的是引用本身的副本
覆盖
符合覆盖的条件(在继承中):
- 子类中的方法名和父类相同
- 子类中的方法参数和父类相同
- 子类中的方法返回类型和父类一样
- 子类的方法不能比父类抛出更多的异常
- 子类的方法访问范围大于或等于父类
java中的构造函数
- 构造函数不能被继承
- 每一个类都至少有一个构造函数,自己不定义,编译器也会给分配一个默认的不带参数的构造函数
- 子类的构造函数一定会调用父类的构造函数,通过super()调用,或显式或隐式,显式调用的父类构造函数必须存在; 如果没有显式调用则编译器会自动在子类的构造函数第一行处加上super()这个隐式调用,这时要求父类一定要有不带参数的构造函数存在(如果父类自己定义了构造函数,但带有参数,编译时会报错)
例子:
class super1{
public int I = 0;
public super1 (String text){
I = 1;
}
}
public class sub1 extends super1{
public sub1(String text){
// super(text);
I= 2;
//隐式超级构造super1()是未定义的。必须明确援引另一个构造
}
public static void main (String args[]){
sub1 sub2 = new sub1("Hello");
System.out.println(sub2.I);
}
}
java中的异常处理
- 异常机制中try{}后一定要跟catch吗?
- 不一定,,但必须跟finally.也就是catch和finally必须跟其中一个
- 异常的抛出可以先子类再父类,如果子类捕获了,则父类就不再捕获;
但是不能先父类再子类,那样会导致编译出错
基本类型的转化
规则: 小的可以自动转化为大的, 大的要强制性才能转为小的,比如以下
Double d = 1.0f; //正确, 小转大,自动
Float f = 1.0d(或1.0); //错误,大转小,需强制 float f = (float)1.0d;
当我们给出一个小数,且该小数后不带f标示,则编译器自动把它视为double类型
Float类和Double类
Float类和Double类都重写对于的equals方法,在比较之前都会判断是否同属于Float对象或Double对象,如果不是直接返回false,如果是再继续比较对应的数值大小。
- Float类
public boolean equals(Object obj) {
return (obj instanceof Float)
&& (floatToIntBits(((Float)obj).value) == floatToIntBits(value));
}
- Double类
public boolean equals(Object obj) {
return (obj instanceof Double)
&& (doubleToLongBits(((Double)obj).value) == doubleToLongBits(value));
}
变量修饰的问题
A:变量不能被defalut修饰
B:native修饰方法,native修饰的方法简单来说就是:一个Java方法调用了一个非Java代码的接口。
定义navtive方法时,并不提供实现体,因为其实现体是用非Java语言在外面实现的。native可以和任何修饰符连用,abstract除外。因为native暗示这个方法时有实现体的,而abstract却显式指明了这个方法没有实现体。
C:abstract修饰方法和类
D:final修饰的方法不能被重写。而abstract定义的方法没有实现,必须被子类重写,明显不能一起使用。
Array
Array.asList方法返回java.util.ArrayList对象 [❌]
Arrays.asList() 返回 java.util.Arrays.ArrayList 对象,这里的 ArrayList 是 Arrays 私有的内部类
Java集合
A: HashSet 它不是线程安全的,属于Set接口下的实现类,Set下的实现类特征就是无序,不允许存储相同的对象
B: ConcurrentHashMap 它是线程安全的HashMap实现,特征也相似,其中存储的值对象可以重复,键对象不能重复
C: Collection接口是List接口和Set接口的父接口,通常情况下不被直接使用
D: ArrayList线程不安全的,底层是数组实现,允许存放重复对象
Java关键字
Java的关键字对Java的编译器有特殊的意义,他们用来表示一种数据类型,或者表示程序的结构等,关键字不能用作变量名、方法名、类名、包名和参数。
true false 是boolean的变量值,是编译器赋予特定含义的,但并不是关键字
this调用格式
线程
如果一个类继承了某个类,只能使用Runnable实现线程 [❌]
实现多线程的三种方式,一种是继承Thread类使用此方式就不能继承其他的类了。还有两种是实现Runnable接口或者实现Callable接口
内部类
- 静态内部类:
- 静态内部类本身可以访问外部的静态资源,包括静态私有资源。但是不能访问非静态资源,可以不依赖外部类实例而实例化。
- 成员内部类:
- 成员内部类本身可以访问外部的所有资源,但是自身不能定义静态资源,因为其实例化本身就还依赖着外部类。
- 局部内部类:
- 局部内部类就像一个局部方法,不能被访问修饰符修饰,也不能被static修饰。
- 局部内部类只能访问所在代码块或者方法中被定义为final的局部变量。
- 匿名内部类:
- 没有类名的内部类,不能使用class,extends和implements,没有构造方法。
- 多用于GUI中的事件处理。
- 不能定义静态资源
- 只能创建一个匿名内部类实例。
- 一个匿名内部类一定是在new后面的,这个匿名类必须继承一个父类或者实现一个接口。
- 匿名内部类是局部内部类的特殊形式,所以局部内部类的所有限制对匿名内部类也有效。
ceil和float
Javac
javav.exe是java语言编译器
java标识符
标识符由数字(09)和字母(AZ 和 a~z)、美元符号($)、下划线(_)以及 Unicode 字符集中符号大于 0xC0 的所有符号组合构成(各符号之间没有空格)。
标识符的第一个符号为字母、下划线和美元符号,后面可以是任何字母、数字、美元符号或下划线。
提示:标识符命名时,切记不能以数字开头,也不能使用任何 Java 关键字作为标识符,而且不能赋予标识符任何标准的方法名。
运算顺序
位运算与逻辑运算的区别:
(|)和(||)成立的条件是只要一侧表达式为真,结果就为真,在(|)运算时,无论左侧的表达式的值为真还是为假,都要判断右侧的表达式的值的真假,而(||)在运算时,只要左侧表达式的值为真,就不再判断右侧表达式的值了
同理&和&&也一样
>>表示右移,如果该数为正,则高位补0,若为负数,则高位补1;
>>>表示无符号右移,也叫逻辑右移,即若该数为正,则高位补0,而若该数为负数,则右移后高位同样补0。
类的初始化
构造函数正确的是 : ( BCD )
A. 子类的构造函数必须和父类的构造函数的传递参数保持一致
B. 子类可以通过super调用父类公有的构造函数
C. 类可以使用this调用当前类的其他构造函数
D. 编译器可以检测同一个类构造函数的交叉调用
E. 构造函数至少一个是公有的,才可以通过编译
父类和子类的构造函数也可以交叉调用
接口的继承
-
java中接口可不可以继承一般类,为什么?
答:不可以因为接口中只能出现3种成员- 公共的静态常量(public final static )
- 公共的抽象方法(public abstract )
- 静态内部类(static class)
而一个类中,就算什么都不写,也必须带一个构造方法,在extends时就会被子类继承,如果是接口也会继承这个构造方法,很明显构造方法不在上面三项之列
而如果类中有一般的方法和成员变量,也会被子类全部继承,这些更不能出现在接口中了,所以接口是绝对不可能继承一个类的
-
java中实体类不能继承接口
-
java中接口不能实现接口,只能继承接口
-
抽象类可以实现接口
抽象类实现接口时,可以完全重写或覆盖接口中的方法,也可只重写接口中的部分方法。
-
抽象类可以继承实体类
抽象类可以继承实体类,但前提是实体类必须有明确的构造函数。
声明的类的范围
private 私有的;因此只能在当前类下使用
类修饰符 :public、default、abstract、final、strictfp,没有private
接口修饰符 :public、default、abstract、strictfp
构造器修饰符 :public、protected、default、private
全局变量修饰符:public、protected、default、private、static、transient、volatile、final
方法修饰符 : public、protected、default、private、abstract、static、final、native、synchronized、strictfp
内部类 :public、protected、default、private、static、abstract、final
局部变量修饰符:final
private可以修饰变量、构造器,方法、内部类;不可以修饰外部类
继承中的方法与变量
泛型
class LRU<T1,T2,T extends TreeMap<T1, T2>, Date,Comparable> {
}
- 子类不能同时实现和父类相同的泛型接口
- 如果父类实现为泛型接口,那么子类只能重写,不能再声明其他类型的该接口
- 实现泛型的桥代码会自动生成(子类不能再写Object类的类型了)
- 不能直接实例化泛型数组
- 不能抛出或者捕获泛型类对象
- Throwable不能被泛型继承
继承与异常抛出
子类抛出的异常类型不能比父类抛出的异常类型更宽泛。假设父类抛出异常ParentException,另外有两个子类继承自ParentException分别为ChildException1, ChildException2, 那么 子类可以同时抛出异常ChildException1,ChildException2. 满足“子类抛出的异常类型不能比父类抛出的异常类型更宽泛”,这一条件。
同理,接口也是一样,如果实现接口的类不能比接口抛出的异常类型更广泛
重写的Thread的run方法,无法抛出checked异常
线程被interrupt不意味着线程结束了
volatile关键字
- 是java关键字
- 修饰的变量不允许重排
- 只可以修饰成员变量或者类变量
- 被修饰的变量要求CPU必须从主存中存取
- 不能保证原子性
异常的坑点
上面说到,实现接口的类不能比接口抛出的异常类型更广泛,但是这里实现类抛出了空指针异常,但是接口中却没有抛出,这是为什么呢?
因为这些都是运行时异常,会由虚拟机抛出也会有虚拟机处理
这里也是一样,其实代码中并没有抛出任何异常,但是编译器没有报错,所有所有运行时的异常可能都会由虚拟机抛出
代理和反射
以下说法正确的是:(ACD)
A. 动态代理类借助实现的InvocationHandler进行函数调用
B. 动态代理类对象必须与代理类具有完全相同的接口列表
C. 动态代理类只可以代理接口
D. java.lang.reflect包中的Proxy类提供了创建动态代理类的方法
子类继承
-
若存在继承关系,而且父类和子类中都存在静态代码块、静态变量、构造代码块、构造方法
-
先是父类静态代码块和静态变量,静态代码块和静态变量的初始化顺序 是谁在前谁先加载
-
再是子类静态代码块和静态变量,静态代码块和静态变量的初始化顺序 是谁在前谁先加载
-
再是父类构造代码块,父类构造方法
-
再是子类构造代码块,父类构造方法
-
子类只能重写父类的普通而且是public方法,私有方法不能重写
-
子类,父类含有相同的成员变量,数值看引用型变量所属的类,即左边
-
父类独有方法改变成员变量值,则改变的是父类中的数据
-
子类重载父类方法,调用的是子类的方法,改变的是子类数据
-
如果在多态,即Parent c = new Child(),子类重载父类方法,则c.方法( ) 调用
是子类的方法,改变的子类变量数据,c.变量 显示的是父类数据,还是未改变的。
UI
java中,一个源组件可以注册多个监听器,也可以将其本身注册为监听器
AWT和Swing之间的区别:
1)AWT 是基于本地方法的C/C++程序,其运行速度比较快;Swing是基于AWT的Java程序,其运行速度比较慢。
2)AWT的控件在不同的平台可能表现不同(native),而Swing在所有平台表现一致。
equal
运算
a++ 先把10赋值给a 再+1 所以左边是10 但此时a=11。右边a-- 也是先赋值 a=11,再-1。10+11=21 此时a=10。