JDK和JRE
- JRE:Java Runtime Environment( java 运行时环境)。即java程序的运行时环境,包含了 java 虚拟机,java基础类库。
- JDK:Java Development Kit( java 开发工具包)。即java语言编写的程序所需的开发工具包。JDK 包含了 JRE,同时还包括 java 源码的编译器 javac、监控工具 jconsole、分析工具 jvisualvm等。
== 和 equals
- 值不同,使用 == 和 equals() 比较都返回 false
- 值相同
- ==:
- 基本类型 - 基本类型、基本类型 - 包装对象返回 true
- 包装对象 - 包装对象返回 false
- 缓存中取的包装对象比较返回 true(原因是 JVM 缓存部分基本类型常用的包装类对象,如 Integer -128 ~ 127 是被缓存的)
- equals:
- 全返回 true
- ==:
- 不同类型的对象对比,返回 false
final
- 被 final 修饰的类,不能够被继承。
- 被 final 修饰的成员变量必须要初始化或在初始化函数里面赋值,赋初值后不能再重新赋值。对基本类型来说是其值不可变;对引用变量来说其引用不可变,即不能再指向其他的对象。final 修饰的对象,对象的引用地址不能变,但对象的属性值可以改变(通过setter方法)
- 被 final 修饰的方法代表不能重写,但能够重载。
final 与 static
- static 可以修饰类的代码块,final 不可以。
- static 不可以修饰方法内的局部变量,final 可以。
- static
- static 修饰的代码块表示静态代码块,当 JVM 加载类时,就会执行该代码块,只会被执行一次
- static 修饰的属性(类变量),是在类加载时被创建并进行初始化,只会被创建一次
- static 修饰的变量可以重新赋值
- static 方法中不能用 this 和 super 关键字
- static 方法必须被实现,而不能是抽象的abstract
- static 方法不能被重写
Math 类中的取整函数
JDK 中的 java.lang.Math 类(见名知意)
- ceil() :向上取整,返回小数所在两整数间的较大值,返回类型是 double,如 -1.5 返回 -1.0
- floor() :向下取整,返回小数所在两整数间的较小值,返回类型是 double,如 -1.5 返回 -2.0
- round() :朝正无穷大方向返回参数最接近的整数,可以换算为 参数 + 0.5 向下取整,返回值是 int 或 long,如 -1.5 返回 -1,1.4 返回 1
翻转字符串
/**
* 自己实现
*/
public static String reverseString(String str) {
if (str != null && str.length() > 0) {
int len = str.length();
char[] chars = new char[len];
for (int i = len - 1; i >= 0; i--) {
chars[len - 1 - i] = str.charAt(i);
}
return new String(chars);
}
return str;
}
/**
* 使用 StringBuilder
*/
public static String reverseStringByStringBuilderApi(String str) {
if (str != null && str.length() > 0) {
return new StringBuilder(str).reverse().toString();
}
return str;
}
/**
* 使用 StringBuilder自己实现
*/
public static String reverseStringByRecursion(String str) {
StringBuilder res=new StringBuilder();
for (int i = 0; i < str.length(); i++)
res.insert(0,str.charAt(i));
return res.toString();
}
/**
* 递归
*/
public static String reverseStringByRecursion(String str) {
if (str == null || str.length() <= 1) {
return str;
}
return reverseStringByRecursion(str.substring(1)) + str.charAt(0);
}
接口和抽象类
- 抽象类可以有构造方法;接口中不能有构造方法。
- 抽象类中可以有普通成员变量;接口中的变量都是默认 public static final 修饰的,且必须赋初始值。
- 抽象类中可以包含非抽象普通方法;接口中的所有方法必须都是抽象的。
- 抽象类中的抽象方法的访问权限可以是 public、protected 和 default;接口中的抽象方法只能是 public 类型的,并且默认即为 public abstract 类型。
- 抽象类中可以包含静态方法;JDK1.8 前接口中不能包含静态方法,JDK1.8 及以后接口可以包含已实现的静态方法。
- 接口不可以实现接口,但可以继承接口,并且一个接口可以继承多个接口。
<< >> >>>
- << 表示左移,不分正负数,低位补0
- 而 >> 表示右移,如果该数为正,则高位补0,若为负数,则高位补1
- 而 >>> 表示无符号右移,也叫逻辑右移,即若该数为正,则高位补0,而若该数为负数,则右移后高位同样补0
- 没有 <<<
- 计算机底层以数的补码形式存储
try-catch-finally 返回值问题
结果:333333。很明显,当try或者catch中有返回值,但是finaly中也有返回语句时,最终返回的是finally中的返回值
结果:111111。s 的值在 try 语句中缓存了,后面的更改并不能修改到缓存了的返回值
内部类
- 内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的 .class 文件,但是前面冠以外部类的类名和$符号
- 内部类是外部类的一个成员,因此内部类可以自由地访问外部类的成员变量,无论是否是 private 的
- 内部类声明成静态的,就不能随便的访问外部类的成员变量了,此时内部类只能访问外部类的静态成员变量
Serializable 接口
- 标记性接口,没有需要实现的方法。实现 Serializable 接口是为了告诉 jvm 这个类的对象可以被序列化
- 某个类可以被序列化,则其子类也可以被序列化
- 对象中的某个属性是对象类型,需要序列化也必须实现 Serializable 接口
- 声明为 static 和 transient 的成员变量,不能被序列化。static 成员变量是描述类级别的属性,transient 表示临时数据
什么场景要对象克隆
- 方法需要 return 引用类型,但又不希望自己持有引用类型的对象被修改。
- 程序之间方法的调用时参数的传递。有些场景为了保证引用类型的参数不被其他方法修改,可以使用克隆后的值作为参数传递。
- 实现 Cloneable 接口,重写 clone() 方法
- Object 的 clone() 方法是浅拷贝,即如果类中属性有自定义引用类型,只拷贝引用,不拷贝引用指向的对象。
- 可以使用下面的两种方法,完成 Person 对象的深拷贝:
- 对象的属性的Class 也实现 Cloneable 接口,在克隆对象时也手动克隆属性
@Override
public Object clone() throws CloneNotSupportedException {
DPerson p = (DPerson)super.clone();
p.setFood( (DFood) p.getFood().clone() );
return p;
}
什么是JVM?
- Java Virtual Machine(Java虚拟机)的缩写
- 实现跨平台的最核心的部分
- .class 文件会在 JVM 上执行,JVM 会解释给操作系统执行
- 有自己的指令集,解释自己的指令集到 CPU 指令集和系统资源的调用
基本数据类型?它们分别占多大字节?
- byte:1个字节,8位
- short:2个字节,16位
- int:4个字节,32位
- long:8个字节,64位
- float:4个字节,32位
- double:8个字节,64位
- boolean:官方文档未明确定义,依赖于 JVM 厂商的具体实现。逻辑上理解是占用 1位,但是实际中会考虑计算机高效存储因素
- char:2个字节,16位