i++和++i问题
public class Question_1 {
public static void main(String[] args) {
int i = 1;
i = i++;
int j = i++;
int k = i + ++i * i++;
System.out.println("i=" +i); // 4
System.out.println("j=" +j); // 1
System.out.println("k=" +k); // 11
}
}
内存图:
public static void main(String args[]) {
int a =100,b=50,c=a-- -b,d=a-- -b;
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
}
内存图:
- 赋值=,最后计算
- =右边的从左到右加载值依次压入操作数栈
- 实际先算哪个,看运算符优先级
- 自增、自减操作都是直接修改变量的值,不经过操作数栈
- 最后的赋值之前,临时结果也是存储在操作数栈中
类和实例初始化过程
// private 方法修饰符修饰重写方法
(5)(1) (10)(6)(4)(3)(2)(9)(8)(7)
(4)(3)(2) (9)(8)(7)
// public 方法修饰符修饰重写方法
(5)(1) (10)(6)(9)(3)(2)(9)(8)(7)
(9)(3)(2) (9)(8)(7)
类初始化过程
1、一个类要创建实例需要先加载并初始化该类
- main方法所在的类需要先加载和初始化
2、一个子类要初始化需要先初始化父类
3、一个类初始化就是执行<clinit>()
方法
<clinit>()
方法由静态类变量显示赋值代码和静态代码块组成- 类变量显示赋值代码和静态代码块代码从上到下顺序执行
<clinit>()
方法只执行一次
实例初始化过程
1、实例初始化就是执行<init>()
方法
<init>()
方法可能重载有多个,有几个构造器就有几个<init>
方法<init>()
方法由非静态实例变量显示赋值代码和非静态代码块、对应构造器代码组成- 非静态实例变量显示赋值代码和非静态代码块代码从上到下顺序执行,而对应构造器的代码最后执行
- 每次创建实例对象,调用对应构造器,执行的就是对应的
<init>()
方法 <init>()
方法的首行是super()或super(实参列表),即对应父类的<init>()
方法
方法的重写
1、 哪些方法不可以被重写
- final方法
- 静态方法
- private等子类中不可见方法
2、 对象的多态性
- 子类如果重写了父类的方法,通过子类对象调用的一定是子类重写过的代码
- 非静态方法默认的调用对象是this
- this对象在构造器或者说方法中就是正在创建的对象
方法的参数传递机制
内存图:
方法的参数传递机制:
1、 形参是基本数据类型: 传递数据值
2、 实参是引用数据类型: 传递地址值;特殊的类型:String、包装类等对象不可变性
局部变量与成员变量
内存图:
局部变量与成员变量的区别
1、声明的位置
- 局部变量:方法体
{}
中,形参,代码块{}
中 - 成员变量:类中方法外
- 类变量:有static修饰
- 实例变量:没有static修饰
2、修饰符
- 局部变量:final
- 成员变量:public、protected、private、final、static、volatile、transient
3、值存储的位置
- 局部变量:栈
- 实例变量:堆
- 类变量:方法区
4、作用域
- 局部变量:从声明处开始,到所属的
}
结束 - 实例变量:在当前类中
this.
(有时this.
可以缺省),在其他类中对象名.
访问 - 类变量:在当前类中
类名.
(有时类名.
可以省略),在其他类中类名.
或对象名.
访问
5、生命周期
- 局部变量:每一个线程,每一次调用执行都是新的生命周期
- 实例变量:随着对象的创建而初始化,随着对象的被回收而消亡,每一个对象的实例变量是独立的
- 类变量:随着类的初始化而初始化,随着类的卸载而消亡,该类的所有对象的类变量是共享的
try{}catch{}finally{}的执行顺序
执行结果:
finally
exception in main
finished
try{}
中的代码出现异常会执行catch{}
中的代码,finally{}
块中的代码无论错误都会执行
带return的try{}catch{}finally{}
先执行try块中代码,如果有异常执行catch块中的代码,最后执行finally块中的代码。