(一) 组合语法
每一个非基本类型的对象都有一个toString()方法,而且当编译器需要一个String而你只有一个对象时,该方法就会被调用。如下:
class WaterSourse {
private String s;
WaterSourse() {
System.out.println("WaterSource");
s = "Constructed";
}
public String toString() {
return s;
}
}
public class SprinklerSystem {
private String value1, value2, value3, value4;
private WaterSourse source = new WaterSourse();
private int i;
private float f;
public String toString() {
return "value1=" + value1 + " " + "value1=" + value2 + " " + "value1=" + value3 + " " + "value1=" + value4
+ "\n" + "i=" + i + " " + "f=" + f + " " + "source=" + source;
}
public static void main(String[] args) {
SprinklerSystem sprinkler = new SprinklerSystem();
System.out.println(sprinkler);
}
}
结果为:
WaterSource
value1=null value1=null value1=null value1=null
i=0 f=0.0 source=Constructed
编译器并不是简单地为每一个引用都创建默认对象,那样会增加不必要的负担,初始化引用可以在如下位置:
(1)定义对象的地方(使得他们总能够在构造器被调用之前)
(2)在类的构造器中
(3)在使用这些对象之前(惰性初始化),减少额外负担
(4)使用实例初始化
如下:
class Soap {
private String s;
Soap() {
System.out.println("soup()");
s = "Constructed";
}
public String toString() {
return s;
}
}
public class Bath {
private String s1 = "happy", s2 = "heappy", s3, s4;// 在定义对象时初始化。即在构造器被调用之前初始化。
private Soap castile;
private int i = 90;
private float toy;
public Bath() {
// i = 56; //可以看出实例初始化子句是在构造器执行前执行的。再次赋值。
System.out.println("Inside Bath()");
s3 = "Joy";
toy = 3.14f;
castile = new Soap();
}
{
i = 47; // 实例初始化
}
public String toString() {
if (s4 == null) { // 惰性初始化.减少不必要的负担
s4 = "JOY";
}
return "s1=" + s1 + " " + "s2=" + s2 + " " + "s3=" + s3 + " " + "s4=" + s4 + " \n" + "i=" + i + "\n" + "toy="
+ toy + "\n" + "castille=" + castile;
}
public static void main(String[] args) {
System.out.println(new Bath());
}
}
结果为:
i=47
toy=3.14
castille=Constructed
(二) 继承语法
其他包中的某个类若要从Cleanser中继承,则只能访问public成员。
所以为了继承,一般的规则是将所有的数据成员都指定为private,将所有的方法都指定为public。
class Cleanser {
private String s = "Cleanser";
void append(String a) {
s += a;
}
public void dilute() {
append("dilute() ");
}
protected void apply() {
append("apply()");
}
void scrub() {
append("scrube() ");
}
public String toString() {
return s;
}
public static void main(String[] args) {
Cleanser cleanser = new Cleanser();
cleanser.dilute();
cleanser.scrub();
cleanser.apply();
System.out.println(cleanser);
}
}
public class Detergent extends Cleanser {
public void scrub() {
append("Detergent scube ");
super.scrub();
}
public void foam() {
append("foam() ");
}
/*
* public String toString() { return "aaa"; }
*/
public static void main(String[] args) {
Detergent d = new Detergent();
Cleanser c = new Cleanser();
d.dilute();
d.foam();
d.scrub();
d.apply();
System.out.println(d);
System.out.println("Testing base class:");
Cleanser.main(args);
}
}
结果为:
Cleanserdilute() foam() Detergent scube scrube() apply()
Testing base class:
Cleanserdilute() scrube() apply()
一 初始化基类
(1)当创建了一个导出类的对象时,该对象包含了一个基类的子对象。这个子对象与基类直接创建的对象是一样的,区别在于:后者来自于外部,而基类的子对象被包装在导出类对象的内部。
(2)对基类子对象的初始化: 在构造器中调用基类构造器来执行初始化。
(3)Java会自动在到处类的构造其中插入对基类构造器的调用。
(4)基类在导出类的构造器可以访问它之前,就已经完成了初始化。
如下:
class Art {
Art() {
System.out.println("Art()");
}
}
class Drawing extends Art {
Drawing() {
System.out.println("Drawing()");
}
}
public class Cartoon extends Drawing {
Cartoon() {
System.out.println("Cartoon");
}
public static void main(String[] args) {
Cartoon cartoon = new Cartoon();
}
}
结果为:
Art()
Drawing()
Cartoon
二 带参数的构造器
(1)如果没有默认的基类构造器,或者想要调用一个带参数的基类构造器,就必须要用关键字super显示的编写调用基类构造器的语句,并且配以适当的参数列表。
(2)调用基类构造器必须是在导出类构造器中要做的第一件事。
如下:
lass Game {
Game(int i) {
System.out.println("Game()");
}
}
class BoardGame extends Game {
BoardGame(int i) {
super(i); // 调用基类构造器必须是导出类构造器的第一条语句
System.out.println("B");
// super(i);
}
}
public class Chess extends BoardGame {
Chess() {
super(11);
System.out.println("Chess");
}
public static void main(String[] args) {
Chess chess = new Chess();
}
}
结果为:
Game()
B
Chess