Java对象、类、多态回顾
2017-04-14 本文已影响38人
stefanJi
内存中的对象
数据类型 | 储存位置 |
---|---|
基本类型(char byte short int long float double boolean) | 栈 |
Java对象 | 堆 |
⚠️
- 声明基本类型时,栈中就会分配一些字节
- 声明引用变量时,栈中也会分配一些字节,但是内存中不包含对象的数据,只包含对象在堆中的地址
例如:Book book;
就把一些字节分配给引用变量book。book的初始值为null,因为还没有对象赋给它
执行book = new Book();
就创建了Book的一个实例,它储存在堆中,并将这个实例的地址赋给引用变量book。
一个对象可以被多个引用变量引用:
Book myBook = new Book();
Book yourBook = myBook;
第二行代码把myBook的值复制给yourBook,结果是yourBook现在和myBook引用同一个Book对象。
类访问控制修饰符
类具有两种访问修饰
- public
- 默认缺省
package base;
public class Book {
String name;
int number;
}
Book 类是base包的一个成员,由于Book类是公用的,可从任何其他类实例化。
package base;
class Stu{
String name;
int age;
}
Stu 类的访问限制就是缺省的,只能被同一个包中的其他类使用。
一个Java源文件只能包含一个公共类,但可以包含多个非公共类
类成员访问修饰符
访问级别 | 从其他包中 | 从同一个包中的类 | 从子类 | 从同一个类 |
---|---|---|---|---|
Public | 是 | 是 | 是 | 是 |
Protected | 否 | 是 | 否 | 是 |
缺省(包私有) | 否 | 是 | 是 | 是 |
Private | 否 | 否 | 否 | 是 |
final变量
final 声明的变量,一旦赋值,就不能改变
⚠️ 注意
- final声明的基本变量,赋值之后,就不可改变其值
- final 声明的引用变量(Java对象),赋值之后,其内部属性可以修改,但引用变量不能再引用其他对象
本质是因为:final 限定了变量的栈区不可改变
package base;
public class Book{
String name;
int age;
public static void main(String args[]){
final Book book = new Book();
final int a = 10;
a = 20; //报错
book.name = "name";
book.age = 20;
book.age = 21;
book.name = "name2";
book = new Book(); //报错
}
}
static静态变量
⚠️ 静态引用变量 static Book book = new Book();
book变量将包含Book对象的地址,对象还是储存在堆中
参数传递
数据类型 | 传递方式 | 说明 |
---|---|---|
基本类型 | 值传递 | JVM将会把传递进来的变量复制给一个新的局部变量 |
引用变量 | 引用传递 | 局部变量就指向和引用变量一样的对象 |
JVM执行类的流程
加载->链接->初始化
- 加载 JVM将Java类的二进制形式加载到内存中,并将它缓存在内存中,以便再次使用 * 如果没有找的制定的类就会抛出错误*
- 链接 验证->准备->解析
- 验证 JVM根据Java编程语言和JVM的语义要求检查这个二进制形式
- 准备 准备要执行的类:给这个类的静态变量和其他数据分配内存控件
- 解析 检查该类是否引用类其他类/接口,是否能找到和加载其他类/接口,这些检查是针对被引用的类/接口递归进行
- 初始化 JVM用赋值或者缺省值将静态变量初始化,并执行静态初始化程序(static块中的代码),初始化发生在执行main方法之前。在初始化之前,类的父类必须先被初始化。这个过程递归进行,直到要初始化的类处于层次结构的最上端为止。
类型 | 默认值 |
---|---|
boolean | false |
byte | 0 |
short | 0 |
int | 0 |
long | 0L |
float | 0.0f |
char | \u0000 |
double | 0.0d |
对象引用 | null |
对象比较
⚠️ 引用变量并不包含对象,而是包含对象在内存(栈)中的地址
因此:
Object a = new Object();
Object b = new Object();
a == b
将返回 false
这样的比较实际没有多大用处,因为大多数时候我们更关心对象,而不是对象的地址。
所以,比较对象可以通过两种方式:
- 提供比较对象的工具类
- 为类实现继承自
java.lang.Object
的equals
和hashCode
方法
Java多态
多态是Java面向对象三大特性之一
要实现Java多态有3个必要条件和2种实现方式
必要条件
- 继承
- 重写
- 向上转型
实现方式
- 继承
- 接口
对于继承实现的多态:
对于引用子类类型的父类,在处理该引用时,它适用于继承该父类的所有子类,子类的
对象不同,对方法的实现也就不同,执行相同动作产生的行为也就不同。
对于接口实现的多态:
指向接口的引用必须是指定实现了该接口的一个类的实例,在运行时,根据对象引用的实际类型来执行对应的方法
在继承链中,对象方法的调用存在一个优先级
该优先级为:
this.fun()
super.fun()
this.fun((super)O)
super.fun((super)O)
下面是经典的多态例子:
class A {
public String show(D obj) {
return ("A and D");
}
public String show(A obj) {
return ("A and A");
}
}
class B extends A{
public String show(B obj){
return ("B and B");
}
public String show(A obj){
return ("B and A");
}
}
class C extends B{
}
class D extends B{
}
public class Main {
public static void main(String[] args){
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
System.out.println("1--" + a1.show(b));//输出A-A
//执行A的show(A object)
//this.show() no
//super.show() no
//(super)b = A
//this.show((super)b) yes
System.out.println("2--" + a1.show(c));//输出A-A
//因为A中没有show(C object)方法,
//所有到A的父类中寻找,但是A没有父类,
//所以执行show((super)c),c的父类为B和A
//因为A中只有show(A object)方法,所以最终执行show(A object)
/**
* 实质执行:a1.show((super)c);
*/
//this.show() no
//super.show() no
//(super)c = B/A
//this.show((super)c=B) no
//this.show((super)c=A) yes
System.out.println("3--" + a1.show(d));//输出A-D
//执行A的show(D Object)
System.out.println("4--" + a2.show(b));//输出B-A
//a2.show()实质优先调用a2引用的对象的show方法
//a2的this是指向B的对象
//this.show no
//super.show no
//(super)b = A
//this.show((super)b) yes
System.out.println("5--" + a2.show(c));//输出B-A
//a2.show()实质优先调用a2引用的对象的show方法
//但是B中没有show(C object)方法,于是到B的父类A中寻找,也没有show(C object)方法,
//于是回到B中尝试执行show((super)c),c的super是B和A,
//B的父类A中只有针对A的show方法,所以执行B中重写的父类的show(A object)方法,而不会执行B的show(B object)
//this.show no
//super.show no
//(super)c = B/A
//this.show((super)c = B) yes
System.out.println("6--" + a2.show(d));//输出A-D
//a2指向B的对象中没有show(D object)方法,于是到父类A中查找,发现有符合,
//所以执行B的父类A的show(D object)
//this.show no
//super.show yes
System.out.println("7--" + b.show(b));//输出B-B
//this.show yes
System.out.println("8--" + b.show(c));//输出B-B
//this.show no
//super.show no
//(super)c = B/A
//this.show((super)c=B) yes
System.out.println("9--" + b.show(d));//输出A-D
//this.show no
//super.show yes
}
}
运行结果如下:
1--A and A
2--A and A
3--A and D
4--B and A
5--B and A
6--A and D
7--B and B
8--B and B
9--A and D