ZB-035-01Java的类与Class

Java的类与Class

先看一个例子

Animal.java

1
public class Animal {}

Cat.java

1
2
3
public class Cat extends Animal {
public void catchMouse(){}
}

WhiteCat.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class WhiteCat extends Cat {
public static void main(String[] args) {

Object obj = new WhiteCat();
// 为什么可以直接赋值给 Object?

/*
这就是 继承啊
因为在java世界里 任何的类都继承了 Object 类,它是整个java世界的基础(根)
所以 java中 任何的类都是 Object的子类
*/

// obj.catchMouse();
// 为什么报错
/*
因为 java 是一个强类型语言,因此
在 Object obj = new WhiteCat(); 时 obj 是 Object类型的
因此编译时 Object 没有 catchMouse() 所以会报错
*/
}
}

RTTI(Run-Time Type Identification) 运行时类型识别

在任何时刻,任何一个对象都清楚的知道自己是什么类型的。

Object.getClass()

在整个 java 运行期间 任何一个对象都可以在任何时候知道自己是什么类型的

1
2
3
4
5
6
7
8
9
10
11
// 这个方法就是 
// obj.getClass();

public class WhiteCat extends Cat {
public static void main(String[] args) {

Object obj = new WhiteCat();
System.out.println(obj.getClass());
// class com.io.demo.WhiteCat
}
}

一个Class 对象就是一个类的说明书

Class 和 类的关系

什么是 JVM ? 就是一个虚拟的计算机,所有的java代码都可以在里面跑。

我们平常写的 java代码是什么

(源代码)xxx.java 写完后经过 编译变成 xxx.class (也就是通常所说的字节码) 它是java跨平台的基石

jvm 可以跑 xxx.class 这样就实现了 一处编写,处处运行

JVM里有什么

  • 栈 (方法栈)
  • 堆 java中 所有的对象都是在 堆里 分配的
    • new Cat() 的过程就是在 堆里创建

Cat 是如何创建的呢?

我想创建一个 Cat,它长什么样子有什么属性,这些东西存在那里?

这个信息就在堆里一个很奇怪的地方存着,叫做 class文件

一个Class对象就是一个类的说明书

1
2
3
4
5
6
7
8
9
10
11
public class Cat extends Animal {
public String[] leg;
public String head;
public String tail;

// 不和任何实例变量相绑定,它是归属于 Cat.class这个说明书的
// 因为所有的 Cat 类实例都共享同一份说明书
public static int count;

public void catchMouse(){}
}

此时当你 new Cat() 时候,JVM就会根据 Cat的说明书 把它创建出来。

1
2
3
4
5
// 于是你疯狂造猫
new Cat()
new Cat()
new Cat()
。。。

这些猫 有什么共同点呢?

  • 都是同一份说明书上生产出来的
  • 每只猫都有独立的属性 leg / head / tail
  • public static int count 本质是什么 归属于 这份说明书的,每个 cat对象共享这份说明书。

这个Cat的说明书是什么?

  • Class对象
  • 静态变量归属于这个 Class对象

instanceof 瞬间豁然开朗

1
2
3
4
5
6
obj instanceof Cat

通过 obj.getClass()
知道每个对象到底是什么类型的

因此它当然清楚知道 它到底是什么类型的

刚刚的Cat说明书在jvm内部开辟的一小块空间

它是非常特殊的,因为所有的类型基本上都只存在一份说明书

这个东西在 java7之前 叫做 永久代

java8之后叫做 元空间

将来你在工作的某一天迟早会碰到这样一个异常

  • Java7之前叫做 OutOfMemory:PermGen
  • Java8之后 叫做 MetaSpace

当你看到它们的时候,基本上是你的类出问题了

总结

每个对象创建出来的时候都需要一份说明书。

一个Class对象就是一份说明书,

因此你总是可以问一个对象obj.getClass() 你是从哪里装配出来的

然后对象说,我是从这个类 装配出来的,这就是 Class 文件的本质。

因此 你很容易实现 instanceof 判断

强制类型转换

1
2
3
4
5
6
Object obj = new WhiteCat();
Integer i = (Integer) obj;

// 此时你会得到一个异常
Exception in thread "main" java.lang.ClassCastException: com.io.demo.WhiteCat cannot be cast to java.lang.Integer
at com.io.demo.WhiteCat.main(WhiteCat.java:7)

为什么报错?

首先强制类型转换本来就是不安全的,编译器允许你这样做

但是它在运行时会出问题,因为每个对象都清楚的知道自己是从什么对象创建出来的。

所以会报错