Java中有8种基本数据类型:
| 基本类型 | 字节数 | 默认值 | 取值范围 |
|---|---|---|---|
| byte | 1 | 0 | -128~127 |
| short | 2 | 0 | -32768~32767 |
| int | 4 | 0 | -231~231-1 |
| long | 8 | 0L | -263~263-1 |
| char | 2 | ‘u0000’ | 0~65535 |
| float | 4 | 0f | -231~231-1 |
| double | 8 | 0d | -263~263-1 |
| boolean | false | true/false |
8种基本的数据类型都有对应的包装类,分别为:Byte、Short、Integer、Long、Float、Double、Character、Boolean。包装类型不赋值就是null,而基本数据类型有默认值且不是null。
Java中所有的数值型变量可以相互转换,当把一个表示范围小的数值或变量直接赋给另一个表示范围大的变量时,可以进行自动类型转换;反之,需要强制类型转换。
这就好像小杯中的水倒进大杯没问题,但大杯的水倒进小杯子就不行了,可能会溢出。
public class A {
static {
System.out.println("父类静态代码块");
}
{
System.out.println("父类非静态代码块");
}
public A(){
System.out.println("父类无参构造");
}
}
class B extends A{
static {
System.out.println("子类静态代码块");
}
{
System.out.println("子类非静态代码块");
}
public B() {
System.out.println("子类无参构造");
}
public static void main(String[] args) {
B b = new B();
}
}
输出结果:
父类静态代码块
子类静态代码块
父类非静态代码块
父类无参构造
子类非静态代码块
子类无参构造
静态代码块、静态变量、静态方法等都是和类相关的,会随着类的加载而执行,且在类的生命周期内只执行一次;
非静态代码块、实例变量、实例方法等都是和对象相关的,每构造一个对象就会执行一次;
类初始化阶段,先执行最顶层父类的静态代码块,然后依次向下,直到执行当前类的静态代码块;
对象初始化阶段,先执行最顶层父类的非静态代码块、然后是父类的构造器,接着依次向下,直到执行当前类的非静态代码块和构造器。
Math.round(a)为什么要先执行非静态代码块,再去执行构造器呢?
对于构造器来说,比如有参构造,会给非静态代码块中一些成员变量赋值,所以必须要先执行非静态代码块,再执行构造函数,要不然构造函数会出现相关的成员属性无定义的问题。
Math.round(-2.4); // -2 Math.round(-2.5); // -2 Math.round(-2.8); // -3 Math.round(3.6); // 4 Math.round(3.5) // 4 Math.round(3.4) // 3
round方法中接收的入参有两种,static long Math.round(double a)和static int Math.round(float a),两个方法的返回值也不同。将入参加0.5后再向下取整就是所得结果。
还有两个比较相似的方法是static double ceil(double a)和static double floor(double a),ceil方法是向上取整,而floor方法是向下取整。
Math.ceil(-2.4) // -2.0 Math.ceil(-2.8) // -2.0 Math.ceil(3.5) // 4.0 Math.ceil(3.0) // 3.0 Math.floor(-2.4) // -3.0 Math.floor(-2.8) // -3.0 Math.floor(3.5) // 3.0 Math.floor(3.0) // 3.0类中的static关键字
- 可以直接使用类名来访问类中的静态变量和静态方法,但静态变量和静态方法必须是非private权限的,一般都是public修饰;
- 静态代码块在类加载时执行,并且在整个类的生命周期中只执行一次;
- 静态方法内不能使用this关键字;
- 其实可以通过对象名来访问类中的静态方法,编译可以通过,也能运行,只不过没有什么意义。
public class StaticTest {
public static int num = 5;
// private 修饰的静态成员,其他类通过本类名访问不到
private static String str = "tom";
public static void func(){
System.out.println("我是静态方法");
}
public void method(){
System.out.println("我是实例方法");
}
}
class Test{
public static void main(String[] args) {
// 可以通过类名调用类中的public修饰的静态成员(包含属性和方法)
StaticTest.func();
// 也可以通过对象调用类中的public修饰的静态成员,不过没有什么实际意义
StaticTest staticTest = new StaticTest();
staticTest.func();
int num = staticTest.num;
}
}
异常
在Java中,异常的顶级父类是Throwable,它有两个子类Error和Exception。
- Error:是程序无法处理的错误,一般表示系统错误,例如虚拟机相关的错误OutOfMemoryError;
- Exception:程序本身可以处理的异常。它可以分为RuntimeException(运行时异常)和CheckedException(可检查的异常)。
运行时异常是不用检查的异常,程序中可以选择捕获处理,也可以不用捕获处理。这类异常一般都是由程序逻辑错误而引起的,程序应该从逻辑角度尽可能避免这类异常的发生。
常见的RuntimeException有:
- NullPointerException:空指针异常
- IndexOutOfBoundsException:数组索引越界异常
- ClassNotFoundException:找不到类异常
- IllegalArgumentException(非法参数异常)
- ArithmeticException:出现异常的运算条件时,抛出此异常
什么是CheckedException(可检查的异常)?
从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等。
常见的 CheckedException 异常:
- IOException:(操作输入流和输出流时可能出现的异常)
- SQLException
Java中只有值传递
值传递call by value,将变量的一个副本传递到方法中,方法中不管如何操作该变量的副本,都不会改变原变量的值;
引用传递call by reference,将变量的内存地址传递给方法,方法操作变量时会找到保存在该地址的变量,对其进行操作,会对原变量造成影响。
try-catch-finally盲点当Java程序执行try-catch代码块时,如果遇到 return 或 throw 语句,这两个语句都会导致该方法结束,但是系统执行这两个语句并不会立即结束该方法,而是去寻找该异常处理流程中是否包含finally块:
- 如果没有finally块,程序立即执行return或throw语句,方法终止;
- 如果有finally块,系统立即开始执行finally块中的代码,当finally块中的代码执行完后,系统才会再次跳回来执行try块、catch块中的return或throw语句;
- 如果finally块中也使用了return或throw等语句,那finally块会直接终止方法,系统将不会再跳回去执行try块和catch块中的代码。
try块后面至少需要跟有catch或finally中任何一个,即可以是try…catch…或者try…finally…或者完整的try…catch…finally…结构。此外,try后面可以有多个catch块,但是只能有一个finally块。
运算数据类型判断以下表达式运算后结果的类型?
(short)10 / 10.2 * 2
Java中默认的浮点类型是double,float数据类型有一个后缀为f或F(long类型也有一个后缀,为l或L)。
Java中自动类型提升的规则与基本数据类型的容量大小有关,当容量小的数据类型与容量大的数据类型的变量做运算时,运算结果就自动提升为容量大的数据类型。byte–>short–>int–>long–>float–>double ,小精度可转大精度,大转小会失去精度。
此题是把10转成了short类型,然后short / double,计算结果会自动转化为double,后面乘法同理,最后结果即为double类型。
protected修饰的成员变量protected修饰的成员变量对于子女、朋友来说,就是public的,可以自由使用,没有任何
限制,而对于其他的外部class,protected来说就变成private。



