地址是HashCode的16进制的写法
类: 对象的抽象化(将对象的象的部分抽取出来构成一个类)
对象: 类的实例化
1.存储的位置不同:
成员变量存储在堆内存中
局部变量存储在栈内存中
2. 声明的位置不同:
成员变量在方法外部声明
局部变量在方法内部声明
3. 默认值是否存在
成员变量有默认值
局部变量没有默认值
4. 当成员变量和局部变量重名时,优先使用局部变量
5. 尽量声明局部变量,不要因为方便而声明成员变量,否则会引起连锁反映
局部变量随着方法的结束而销毁
成员变量不会随着方法的结束而销毁,因为它在堆中声明,需要JVM的GC机制去回
收它,但是回收的时机不确定
作用是初始化属性
形参是基本数据类型时,修改形参的值,不引起对象的属性的改变,如果形参是引用类型的话,修改形参的值,会修改对象的属性。因为数据类型传递的是数,是在栈中修改。引用数据类型传递的是对象的地址,修改时直接在堆中修改。
static修饰的变量称为静态变量,也称类变量,是属于类的,可以被所用对象所共享
特点:
静态方法中不能访问this,因为对象可能还未初始化
静态变量和成员变量的区别
1.存储的地方不同:
成员变量存储在堆内存中;
静态变量存储在方法区中;
2. 分数
成员变量每个对象都有一份;
静态变量只有一份,被所有对象共享;
3.调用方法
成员变量:对象名.成员变量
静态变量:对象名.静态变量(不推荐)
类名.静态变量
静态方法: 只能访问静态变量,调用静态方法,不能访问成员变量(可能对象还未初始化),不能调用成员方法。
成员方法: 既能访问静态方法、静态变量,也能访问成员方法、成员变量;
注意:静态方法中不能出现this关键字,static不能修饰类,但是可以修饰内部类;
局部代码块: 存在于方法中,控制变量的生命周期(作用域)
构造代码块: 提取构造方法中的共性,每次创建对象都会执行一次,并且在构造方法执行之前执行;
一个类中允许定义多个构造代码块,执行的顺序根据定义的顺序进行
静态代码块: 随着类的加载而加载,只加载一次(加载类时需要做的一些初始化,比如加载驱动)
同步代码块(线程):
/*
*面试题:
* Coder静态代码块执行 --- Coder构造代码块执行 --- Coder无参空构造执行
*
*
* BlockTest静态代码块执行 --- BlockTest的主函数执行了 --- Coder静态代码块执行 --- Coder构造代码块执行 --- Coder无参空构造执行
* Coder构造代码块执行 --- Coder无参空构造执行
*
*/
public class BlockTest {
static {
System.out.println("BlockTest静态代码块执行");
}
{
System.out.println("BlockTest构造代码块执行");
}
public BlockTest(){
System.out.println("BlockTest无参构造执行了");
}
public static void main(String[] args) {
System.out.println("BlockTest的主函数执行了");
Coder c = new Coder();
Coder c2 = new Coder();
}
}
class Coder {
static {
System.out.println("Coder静态代码块执行");
}
{
System.out.println("Coder构造代码块执行");
}
public Coder() {
System.out.println("Coder无参空构造执行");
}
}
父类:又称超类、基类。
子类:又称派生类
如果子类有自己的实现方案,那么这个方法就可以重写。
注意:
多态: 同一个方法,不同对象调用会有不同的结果。
多态的三个必要条件:
1.继承是多态的前提;
2.子类改写父类的方法
3.父类引用指向子类对象
向上转型: 父类 对象名 = new 子类();(自动类型转换)
向下转型: 子类 对象名 = (子类)父类对象名(向上转型对象);
向下转型容易出现ClassCastException异常。
判断对象是否是类的实例: object instanceof class(返回一个boolea型数值)
编译时: 如果class是对象的父类、自身类、子类时编译时不会报错。
class是对象的兄弟类时会报错
运行时: 如果class是对象的父类、自身类时,运行时返回true,其他返回false。
// 子类
Cat c = new Cat();
Dog d = new Dog();
Pig p = new Pig();
Animal an = new Cat();
boolean flag = c instanceof Cat; // class 为自身类
//boolean flag2 = c instanceof Pig;// class为兄弟类时报错
boolean flag3 = c instanceof Animal; // class 为父类
// Cat的子类YellowCat
boolean flag4 = c instanceof YellowCat; // class为子类
boolean flag5 = an instaceof Cat;
System.out.println("flag = " + flag); // true
System.out.println("flag3 = " + flag3); // true
System.out.println("flag4 = " + flag4); // false
System.out.println("flag5 = " + flag5); // true
运行时看左边,使用左边的成员变量
class Animal {
int age = 10;
}
class Cat extends {
int age = 20;
int weight = 50;
}
Animal an = new Cat();
System.out.println(an.age); // 10
//System.out.println(an.weight); // 编译报错
编译看左边,参考等号左边引用对象所属的类是否有该方法。
运行看右边,在执行期间判断引用对象的实际类型,然后根据其实际的类型调用其相应的方法,又称为动态绑定。
当一个类的方法不需要自己实现,只需要子类来实现,如何在JAVA的规则中只声明方法,而不实现方法,就是把这个方法变为抽象方法,当这个方法变为抽象方法后,这个类也变为抽象类了。
当一个类很抽象,表示范围很广时,需要定义为抽象类,例如:人类,
抽象类的一些方法只需要声明不需要实现,实现过程由子类完成
不一定,可以将子类也弄成抽象类,这样就不用实现你的抽象方法了,但是你的抽象方法终归要实现,不过是你的子类的子类来实现。
–>不实现就没办法new对象,因为总有一个子类不是抽象类,而这个子类就必须实现抽象类还未实现的方法
接口是类与类的桥梁,将不同的类联系起来,在接口中定义不同类型的相同行为,谁想使用,谁就来实现这个接口, 接口只定义行为的格式,具体的实现过程,由实现这个接口的类来完成。
* is..a.. 继承关系 表明 什么是什么 例如 学生是人,老师是人
* has..a.. 聚合关系 表明 什么包含在什么里面
* like..a.. 实现关系 接口与类的关系 象什么 例如:空调有制冷功能,冰箱也有制冷功能,所以说,空调象冰箱,但是不是冰箱。