这是我参与更文挑战的第18天,活动详情查看: 更文挑战
对象的生命周期
对象创建
对象创建和初始化步骤
- 为对象分配内存空间,并将成员变量初始化。
- 执行显示初始化,即执行在类成员声明时带有的简单赋值表达式
- 执行构造方法,进行对象的初始化。
对象清除
Java提供了垃圾收集器,即会自动帮我们回收被认定位不再被使用的对象。并周期性的释放被回收的对象的所占的内存。
类的继承和多态
类的继承(extends)
子类
可以理解为 子类是父类的一个特例。如矩形为父类,则长方形和正方形都是其子类。
子类继承父类的属性和方法,子类只需要声明自己特有的东西,但子类也不能继承父类的所有变量和方法。如
- 带private修饰的属性和方法
- 构造方法
子类使用extends定义,含义为扩充、扩展。
单继承
- Java支持单继承,即只能丛一个类继承。
- 多次继承在现实又是普遍的,Java提供了接口机制,允许一个类实现多个接口,这样避免了多重继承的复杂,又实现了多重继承的效果,所以Java的多重继承通过接口实现
super关键字
super指向所在类的父类,用来引用父类的方法和变量。不一定是直接父类的方法,可以是间接父类的。
- 在方法中用this( )调用构造方法。
- 用super()调用父类的构造方法,且其必须出现在子类构造方法的第一行。
子类对象的创建与实例化过程
- 为对象分配内存空间,并初始化为0值
- 按继承关系,自顶向下显示初始化
- 按继承关系,自顶向下调用构造方法
方法重写
子类中父类成员的隐藏
- 当子类中与父类有同名成员变量时,父类成员变量会被隐藏
- 当子类的方法和父类的同名、同参数列表、返回值类型事,父类方法被隐藏,子类重写父类的方法。
- 隐藏的含义:通过子类对象调用与父类同名的变量和方法时,被操作的是子类的变量和方法。
方法重写规则
- 子类中重写方法的返回值类型必须和父类中被重写方法的返回值类型相同、
- 子类重写方法的访问权限不能缩小
- 子类重写的方法不能抛出新的异常
运行时多态
上溯造型
概念
通过一个父类变量的发出的方法调用,可能执行的是父类的实现,也可能是某个子类的实现,这只能在运行时时刻根据该变量指向的具体对象类型确定
用最简单的一句话就是:父类型的引用指向子类型的对象。用一句比较通俗的话:同一操作作用于不同的对象,可以产生不同的效果。这就是多态。
特征
- 具有继承或实现关系
- 父类和子类均有一个成员变量a,最后拿到的是父类的a
- 父类和子类均有一个say方法,最后执行的是子类的方法(say方法重写)
实现机理
运行时多态的实现机理是动态联编技术,也称晚联编或者运行期联编。联编:将一个方法调用和一个方法体连接到一起,在程序运行前进行联编称作“早联编”,如C语言。Java中除了final,均采用的晚联编技术,这也是被final修饰的方法不能被重写的原因之一。
class Father{
int a=5;
}
class Son extends Father{
int a=10;
}
class Test{
public static void main(String args[]){
Father f = new Son();///上溯造型,(父类指向子类)
//成员依旧是父类的,同名方法被子类重写
System.out.println(f.a);
Son s = (Son)f ///下塑造性,(父类转成子类)
}
}
对象类型的强制转换
概念
对象类型的强制转换也称向下造型或造型,是将父类类型的对象变量强制(显示)地转化为子类类型。
上溯造型,使得父类类型变量可以指向子类对象,但该变量只能访问父类定义的成员,子类特有的被隐藏,只有将其强制转换为具体的子类类型,才能访问特有成员。
instanceof运算符
在Java中使用instanceof测试对象的类型。
aObjectVariable instanceof SomeClass //当aObjectVariable的类型是SomeClass 时返回true,否则返回false
强制类型转换
//格式:(SomeClass)aobjectVariable
//在进行强制类型转换是,一般先用instanceof进行检查,符合时才转换。
规则
- 对象变量转换的目标类型一定是要当前对象类型的子类。这个由编译时编译器检查。
- 在运行时也会进行对象类型的检查,例如某个对象进行类型转换时,省略了instanceof测试。并且对象类型不是其要转换目标类型,就会抛出异常。
Object类
概述
- Object类是Java平台中类层次树的根。Java中的每个类第都是Object的直接或间接子类。
- 这个类定义所有对象都需要的状态和行为,如对象间的比较,将对象转为字符串
Object子类可以重新的方法。
- clone( )
- equals( ) / hashCode( ) // 两个方法必须同时重写
- finalize ( )
- toString( ) // 返回对象的字符串表示,内容因具体的对象而异
Object子类不能重写的方法
- notify( )
- notifyAll( )
- wait( )
clone()方法
/**
将一个已有对象复制为另外一个对象
*/
ClassName B = new ClassName();
ClassName A = B.clone();
//上述方法将创建一个和B类型一样的对象,并把B的成员变量的值初始化给A。
/**注意
1. 被调用clone()方法的对象B必须实现java.lang.Cloneable接口,否则抛CloneNotSupportException异常。因为Object类没有实现这个接口,所以提供复制能力的类必须自己实现Cloneable这个接口,只要在类声明中增加implements Cloneable
2.clone() 是shallw copy(浅复制),而不是deep copy(深复制)。浅复制:复制的成员变量只能是基本类型的,不能是引用型变量(如一个对象数组)。深复制是可以复制引用型变量。
*/
/*下面Stack类将重写Object的clone()方法,实现深复制 */
public class Stack implements Cloneable {
private Vector items;
// code for Stack's methods and constructor not shown
protected Object clone() {
try {
Stack s = (Stack)super.clone(); // clone the stack 复制堆栈对象
s.items = (Vector)items.clone(); // clone the vector 复制堆栈的数据区
return s; // return the clone 返回复制的堆栈的对象
} catch (CloneNotSupportedException e) { }
}
}
equals()方法
public boolean equals(Object obj);
比较当前对象的引用是否和参数obj指向同一个对象,返回true。
String,Date,Flie类和所有包装类都重写该方法,(如Interer,Long 等),改为比较所指对象的值
另外,“==”对于引用型变量,比较的是这两个变量所指对象的地址,所以比较两个字符串s1和s2是否相同,应该用s1.equals(s2)。但字符串存在于常量池,会去重,一样的会指向同一个地址。
toString()
toString()返回对象的字符串表示,内容因具体的对象而异。对我们调试对象内部状态很有价值,所以我们一般都会重写它;
getClass()
getClass()返回对象的类信息,返回一个Class类型的对象,
void getClassName(Object obj){
System.out.println(obj.getClass.getName());
}
Class 类型常用于在运行时刻创建在编译时不知道类型的对象,下面的方法中创建一个obj相同类型的对象
Object CreteNewInstanceOf(Object obj){
return obj.getClass().newInstance();
}
///注意:如果已经知道类的名字,我们也可以快速通过类名拿到Class对象
//如下面可以获得String类的Class对象
String.class;
Class.forName("String");