1.+=符号(引申扩展类赋值运算符)
+= 、-=、%=、/=、*=
byte b = 0;
b = b +128;//报错,原因:128 int 类型,b 自动转换成int 类型,(b+128)int类型,再转byte需要强转。
b += 10;//不报错,原因:等效于b = (byte)(b+10);结果:10
b += 128;//不报错,原因:等效于b = (byte)(b+128); 有强转。结果:-128,原因:精度损失。
扩展类的赋值运算符不改变运算结果类型,底层是强转。
2.类和对象
类是虚拟的
对象是实际的
类——————>实例化--------------->对象
对象——————>抽象----------------->类
类里面的成员属性会有默认值,一切向0看齐,成员方法中的成员变量不会有默认值。
3.引用数据类型
Java语言中所有的class都属于引用数据类型。eg.String.class System.class HelloWorld.class User.class Integer.class …,存放在JVM方法区内存中。
4.JVM简述
JVM主要包括3个内存空间:栈内存,堆内存,方法区内存。
- 方法在调用的时候,该方法所需要的内存空间在栈内存中分配,称为压栈,方法结束后,方法所占的内存空间释放,称为弹栈
- 栈内主要存方法体中的局部变量
- 一个线程一个栈
- new XXX() 对象,String 对象 存放在堆内存中
- 实例变量(实例变量就是前面没有static修饰的变量)放在堆内存中
- 静态变量(静态变量就是前面有static修饰的变量)会存放在方法区内存中
- 方法的代码片段以及整个类的代码片段存放在方法区内存中,在类加载时这些代码会载入
- jdk 1.6 方法区内存中有常量池 ,jdk1.8 堆内存中有常量池 ----> 常量池移动了位置
- 三个内存中变化最频繁的是栈内存,最先有数据的是方法区内存,GC主要是针对堆内存
- GC机制:回收某个Java对象的内存-----条件----->没有更多的引用指向该Java对象,这个对象无法被访问,因为堆内的数据只能通过引用的办法访问,因此该对象变成垃圾数据,等待GC回收。
5.引用数据和基本数据
int i = 10;//有个变量i,存的内容(值)是10
String s = "Hello";//有个变量s ,叫引用,存的内容(值)是“Hello”的堆内存地址,即s引用指向“Hello”堆内存
//由此可以再次理解一下Java的值传递。
6.this
-
this是一个引用,是一个变量,
保存的是自身内存地址
,this存储在JVM堆内存Java对象内部,代表当前对象。 -
实例方法中可以使用this
用法:使用this调用当前对象的方法,变量
(如果是静态的方法或变量,他会自己转化成类名.xxx(); 或 类名.xxx,所以哪怕this = null,也不会空指针异常,因为this根本就没有用到。So,
拓展:静态方法和变量可以使用引用.xxx(); 引用.xxx方式调用,它会自己转化成类名.xxx();类名.xxx;的方式。哪怕 引用 = null,也不会空指针异常,因为引用根本就没有用到。
这种方法不建议使用,容易给看代码的人造成困扰,无法区分实例和静态,所以还是建议使用类名.xxx();类名.xxx;的方式。)为什么使用this:因为实例方法和实例变量需要引用调用
-
静态方法不可以使用this
为什么不可以使用this:因为它直接类名调用,不需要当前对象;如果要用对象的方法和变量,new 一个,再使用(参考main方法)。
实例方法、变量
需要引用调用
,即:引用.xxx(); 引用.xxx;
静态方法、变量
不需要引用调用,他一般用类名调用
,不存在当前对象,即:类名.xxx();类名.xxx;
- this多数情况下可以不写。但是区分同名局部变量和成员变量时
不
可以省略。 - this使用地方:
1). 可以使用在实例方法中代表当前对象,调用当前对象的方法和变量:this.xxx(); this.xxx;
2). 可以在当前构造方法调用其他的构造方法:this(a,b…<参数>),注意,只能出现在构造方法第一行
。
拓展:super() 与 this() 不能共存
,因为他们都得是第一个要执行的语句(出现在第一行)。但super()的构造一定会执行
。
原因:
构造方法如果既没有this(),也没有super(),程序会默认第一行有个super();
如果有super(),就会代替掉默认的super();
如果第一行是this(),则也没有super(),但是this()调用其他构造方法时,其他构造方法又会做和上面同样的事情。
直到有写的super() 或者 this(),super()都没有,使用默认的super()。
7.super
- super不是一个引用,不是一个变量,不保存地址,不指向任何对象,只代表当前对象内部的那一块父类型的特征。
//this可以单独用,super不可以单独使用。
System.out.println(this);//是可以的
System.out.println(super);//不可以!
所以:super除了构造方法super()外,在使用的时候都需要加个" . "。
//比如:
System.out.println(super.xxx);//xxx是父类的成员属性或者成员方法。
super其他的性质基本和this一致。
8.静态代码块
在类加载时执行
,且只执行一次,一个类中,可以有多个静态代码块----被称为类加载时刻
一般用于初始化工作,比如:初始化连接池,解析xml文件…
static{
//Java语句;
}
拓展:
类加载:把静态的属性初始化,类加载只加载一次
。
静态变量们先赋值0,实例变量们是对象属性,不是类属性,当作看不见,视为空气。然后从头到尾按顺序走一遍(当然包括静态代码块!),忽略非静态的方法和属性。
9.实例代码块
在构造方法执行前执行
,一个类中,可以有多个实例代码块,并且遵循自上而下按顺序
执行。----被称为对象初始化时刻
{
//Java语句;
}
拓展:
对象加载:把实例的属性初始化
实例变量们先赋值0,静态变量们不变(由于类加载在对象的前边,所以静态的已经初始化过了。),视为空气。然后从头到尾按顺序
走一遍(当然包括实例代码块!),忽略静态的方法和属性。注意构造方法最后执行。
类加载,对象加载 综合eg.
public class A {
A(){
System.out.print(n+sn1+sn2);
System.out.print("D");
}
static int sn1=sf1();
static{
System.out.print("A");
}
static int sn2=sf2();
{
System.out.print("B");
}
int n=f();
{
System.out.print("C");
}
static int sf1() {
System.out.print(sn2);
return 1;
}
private int f() {
System.out.print(sn1);
System.out.print(sn2);
System.out.print(n);
return 3;
}
static int sf2() {
System.out.print(sn1);
return 2;
}
public static void main(String[] args) {
System.out.print(sn1+sn2);
new A();
new A();
}
}
0 A 1 3 B 1 2 0 C 6 D B 1 2 0 C 6 D