Java 中的复用类
}
}
public class Thinking_test {
private String value1,value2,value3,value4;
private Test t=new Test();
private int i;
private float f;
@Override
public String toString() {
return "Thinking_test{" +
"value1='" + value1 + ''' +
", value2='" + value2 + ''' +
", value3='" + value3 + ''' +
", value4='" + value4 + ''' +
", t=" + t +
", i=" + i +
", f=" + f +
'}';
}
public static void main(String []args){
Thinking_test test=new Thinking_test();
System.out.println(test);
}
}
Output:
Test()
Thinking_test{value1='null', value2='null', value3='null',
value4='null', t=Constructed, i=0, f=0.0}
这里有一个特殊的函数:toString()。每一个非基本类型的对象都有一个 toString( 《一线大厂 Java 面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 )方法,而且当编译器需要一个 String 而你却只有一个对象时,该方法便会被调用。
1.2 引用的初始化
编译器并不是简单地为每一个引用创建默认对象,同时在初始化引用时可以在代码中的以下位置进行:
1.在定义对象的地方
,这意味着它们总是能够在构造器被调用之前被初始化。
2.在类的构造器中
3.就在正要使用这些对象之前
,这种方式称为:惰性初始化。在生成对象不值得及不必每次都生成对象的情况下,这种方式可以减少额外的负担。
4.使用实例初始化
如果没有在定义处初始化,那么除非发生了不可避免的运行期异常,否则将不能保证信息在发送给对象引用之前已经被初始化。
[](()继承语法:extends
2.1 继承语法
当创建一个类时总是在继承,因此,除非已明确指出要从其他类中继承,否则就是隐式地从 Java 的标准根类 Object 进行继承。组合的语法比较平实,但是继承使用的是一种特殊的语法。在继承过程中,需要先声明“新类与旧类相似”。这种声明通过在类的左边花括号之前,书写后面紧跟基类名称的关键字 extends 而实现。这样做,会自动得到基类种所有的域和方法
。
2.2 初始化基类:
继承类从外部看,就像是一个与基类具有相同接口的新类,或许还会有一些额外的方法和域。但继承并不只是复制基类的接口。当创建了一个导出类的对象时,该对象包含了一个基类的子对象。这个子对象与你用基类直接创建的对象是一样的。二者的区别在于,后者来自于外部,而基类的子对象被包装在导出类对象内部。
仅有一种方法来保证基类子对象的正确初始化:在导出类构造器中调用基类构造器来执行初始化,而基类构造器具有执行基类初始化所需要的所有知识和能力。
Java 会自动在导出类的构造器中插入对基类构造器的调用:
class Art{
Art(){
System.out.println("Art");
}
}
class Drawing extends Art{
Drawing(){
System.out.println("Drawing");
}
}
public class Cartoon extends Drawing{
public Cartoon(){
System.out.println("Cartoon");
}
public static void main(String[] args) {
Cartoon cartoon=new Cartoon();
}
}
Output:
Art
Drawing
Cartoon
构建过程是从基类“向外”扩散的,所以基类在导出类构造器中可以访问它之前,就已经完成了初始化。即使没有给 Cartoon()创建构造器,编译器也会自动合成一个默认的构造器,该构造器将调用基类的构造器。
[](()使用组合和继承
使用组合和继承是很常见的事,通过使用组合和继承可以创建比较复杂的类。
3.1 名称屏蔽
若 Java 的基类拥有某个已被多次重载的方法名称,那么在导出类中重新定义该方法名称并不会屏蔽其在基类的任何版本。因此,无论是在该层或者它的基类中对方法进行定义,重载机制都可以正常工作
。
class Homer{
char doh(char c){
System.out.println("doh(char)");
return 'c';
}
float doh(float f){
System.out.println("doh(float)");
return 1f;
}
}
class MilHouse{};
class Bart extends Homer{
void doh(MilHouse m){
System.out.println("doh(MilHouse)");
}
}
public class Hide {
public static void main(String[] args) {
Bart b=new Bart();
b.doh('x');
b.doh(1f);
b.doh(new MilHouse());
}
}
Output:
doh(char)
doh(float)
doh(MilHouse)
从上方代码可以看出,我们进行了重载,而不是覆写,覆写的话应该是函数名和参数都相同。
3.2 组合和继承之间的选择
组合和继承都允许在新的类中放置子对象,组合是显式地这样做,而继承是隐式地做。
组合技术通常用于想在新类中使用现有类的功能而非它的接口这种情形。即,在新类中嵌入某个对象,让其实现所需要的功能,但新类的用户看到的只是为新类所定义的接口,而非所有嵌入对象的接口。为取此效果,需要在新类中嵌入一个现有类的 private 对象。而在继承的时候,使用某个现有类,并开发一个它的特殊版本。通常这意味着你在使用一个通用类,并为了某种特殊需要而将其特殊化。
用一个“交通工具”对象来构成一部“车子”是毫无意义的,因为“车子”并不包含“交通工具”,它仅是一种交通工具(is-a 关系)。“is-a”(是一个)的关系是用继承来表达的,而“has-a”(有一个)的关系则是用组合来表达的。
(还有一个关系是 is-like-a 关系,指的是继承之后又添加了一些方法)
3.3 向上转型
向上转型:子类引用转换为父类引用,参数接受的是父类,但给的引用是子类。
评论