Java 关键字:new, this, super, instanceof

用于定义建立实例及引用、判断实例的关键字

new

​ 实例化对象。

1、构造对象的语法:
类名称 变量名称 = new 类名称(构造方法的调用(实参列表));	// 构造对象并保存
new 类名称(实参列表);	// 匿名构造对象,不会有任何栈空间的指向,只可使用一次,随后就成为垃圾

举个 🌰:

代码说明:

  1. 一个包中只能有一个 public 的类或一个 public 的接口。

  2. Person p = new Person(‘Doris’, 2, 3);

    1. new:计算对象需要的内存大小,开辟空间,初始化为 0x0。

      相当于 C 中的:p = malloc(sizeof(Person)); memset(p, 0x0, sizeof(Person));

    2. Person(‘Doris’, 2, 3):调用构造方法,对属性初始化。

    3. Person p:构造方法调用结束,返回一个指向新对象的引用。

      Person p = 新的对象;

    4. 引用传递的本质:一块堆内存可以被多个栈内存所指向。

      Person p1 = new Person();

      Person p2 = new Person();

      p1 = p2;

  3. 对象中存储的最主要的就是属性,也可以找到方法区对象相对应的类。

  4. 内存存储情况:

  5. public Person(String n, int g, int a) {}

    其中:n 是引用类型(所有引用类型都指向对象),g 和 a 是基本数据类型。

2、访问实例变量和实例方法:

​ 对象(引用数据类型)必须在实例化后调用,否则会产生 NullPointerException(运行时错误),但编译时不会出错。

  1. 访问对象的属性
    1. 在类的内部:在同一类中访问,直接用“属性名称”访问。
    2. 在类的外部:在不同类中访问,使用“引用.属性名称”访问。
  2. 调用对象的方法
    1. 在类的内部:在同一类中调用,直接用“方法名称”调用。
    2. 在类的外部:在不同类中调用,使用“引用.方法名称(实参列表)”调用。

容易混淆的地方:

  1. 嵌套调用:
System.out.println(Arrays.toString(rotate(new int[] {1, 2, 3, 4, 5}, 3)));

​ 实际执行过程:

int[] tmp1 = new int[] {1, 2, 3, 4, 5};
int[] tmp2 = rotate(tmp1, 3);
String tmp3 = Arrays.toString(tmp2);
System.out.println(tmp3);
  1. 链式调用:
class A {
	public A create() {
		return new A();	// 实际执行:A tmp = new A();	return tmp;
	}
}
class B {
	public static void main(String[] args) {
		new A().create().create().create().create();
		/**
		 * 实际执行:
		 * A tmp1 = new A();
		 * A tmp2 = tmp1.create();
		 * A tmp3 = tmp2.create();
		 * A tmp4 = tmp3.create();
		 * A tmp5 = tmp4.create();
	}
}
  1. Person p = null;

    定义了一个没有指向任何对象的 Person 类型的引用(类类型的引用)。

  2. Person p = new Person(…);

    1. 定义了一个 Person 类型的对象;
    2. 定义了一个指向 Person 类型对象的 Person 类型的引用(类类型的引用)。

引用类型和指向的对象类型是两回事。

3、对象的生命周期:

​ 生命周期是运行期间的概念。对象的四个时期分为:

  1. new 关键字:

    1. 从方法区中找相应的类,如果找不到就进行类的加载;
    2. 计算对象的大小;
    3. 在堆中合适的位置申请内存空间;
    4. memset(0x0):将整个内存空间初始化为 0 的变形。如果没有给值,取属性的默认值。
  2. 三个初始化:

    1. int a = 10;
    2. { a = 10; }
    3. 构造方法

    根据定义的顺序优先执行前两个,然后遵循先父类后子类的顺序执行第三个。

  3. 对象真正的生命:正确使用的时期。

  4. 死去但保留尸体的阶段:即没有被 GC(Garbage Collection,垃圾收集)回收的阶段。

    1. GC 回收的是什么(什么是垃圾):以对象为单位,没有使用价值、没有引用指向的对象。
    2. 怎么判断什么是垃圾:由算法判断。
    3. GC 是否足够快速回收:根据算法进行快速回收(分类)。

    有关 GC 的详细知识会在后续详述。

this

​ 作用:普通方法调用和静态方法调用的调用栈。

1、调用构造方法

​ 在构造方法中调用其他的构造方法,调用语句必须出现在第一行。

class Person() {
	String name;
	public Person(String n) {
		name = n;
	}
	public Person() {
		this("陌生人");
		// name = "陌生人";
	}
}
2、指向当前对象
  1. 通过 this 访问属性或方法,一般出现在发生了命名遮挡(name shadowing)的时候。
class Person() {
	String name;
	public Person(String name) {
		this.name = name;
		toString();	// this.toString();
	}
	public String toString() {...}
}
  1. this 代表的就是当前对象(current object)的引用。
class Person {
	String name;
	public Person(String name) { this.name = name; }
	public String toString() { return this.name; }
	public boolean equals(Person p) { return p.name = this.name; }
	public void test() {
		this.equals(this);	// 只要对象调用了本类中的方法,this 就表示当前执行的对象
	}
}
Person p = new Person();	// 则 this.equals(this); 实际表示为 p.equals(p);

普通属性和普通方法其实都绑定着一个隐含的对象,即 this。

举个 🌰:

class Solution {
	Node reverseList(Node head) { ... }
}
class Main {
	private static void testReverseList() {
		new Solution().reverseList(head);
	}
	public static void main(String[] args) {
		testReverseList();
	}
}

在这里插入图片描述

super

1、作用:
  1. 明确访问父类的属性或者方法。
  2. 显式调用父类的构造方法,必须出现在第一行。

不是代表父类对象,可以抽象的理解为:执行属性中属于父类的那部分,明确调用父类的方法。

2、🌰:
class A {
	public int a = 10;
	public void print() {
		System.out.println("父类的 print");
	}
}
class B extends A {
	public int a = 100;
	public void print() {
		System.out.println("子类的 print");
	}
	public void test() {
		super a;	// 父类的 a
		super.print();	// 父类的 print
	}
}
  1. Java 中类的继承只允许单继承。

  2. 父类和子类之间的关系,涉及到 super 关键字:

    1. 类加载的关系:

      1. 子类的加载必须触发父类的加载,即父类的加载一定是发生在子类的加载之前的。
      2. 执行 main 方法就要进行类的加载,执行静态代码块。
    2. 对象实例化、构造的关系:

      1. 子类对象的构造过程会触发父类中属性的初始化过程,即父类属性的初始化一定发生在子类属性的初始化之前。

      2. 先执行构造到吗快,在执行构造方法,与书写位置无关。

        属性初始化:定义时初始化 + 构造代码块(前两个按照书写顺序执行)+ 构造方法

      和 super 调用父类构造方法的位置无关。

instanceof

1、语法:

​ 引用 instanceof 类型(类类型、接口类型)

list instanceof List

​ 作用:list 引用指向的对象是否能被 List 类型的引用指向。

​ 主要用于向下转型时判断对象是否为类型引用的指向。

2、向下转型:
  1. 解决调用方法由引用决定,所以为了使用只有子类型独有的方法,需要向下转型。

  2. 向下转型是不自然的,需要强制转换。

A ab = new B();
ab.methodOfB();	// Compile Error
B bb = (B)ab;
// 如果 ab 实际上不是指向 B 类型的对象,不会有编译错误
// 但会触发运行时错误,会抛出异常 ClassCastException

举个 🌰:

List a = new ArrayList();
// 如果需要调用的只有 ArrayList 支持的方法
ArrayList b = (ArrayList) a;	// 需要强制转换
// 需要保证 a 指向的对象可以被 ArrayList 引用指向(是 ArrayList 的子类类型的对象)

​ 转换的正确性需要开发者自行保证。

为了安全,由 instanceof 运算符做运行时检查。

ab instanceof B;	// ab 引用指向的对象能否被 B 类型的引用指向 
3、向上转型:
  1. 把引用类型转换为另一种引用类型(类型层级属于其上层的)。
  2. 向上转型是自然的,不需要强制转换。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值