“复用代码是Java众多,引人注目的功能之一。但要想成为极具革命性的语言,仅仅能够复制代码并对之加以改变是不够的,它必须还能够做更多的事情。” Java解决问题都围绕类展开的,对于复用代码,可以创建新的类来复用,也可以使用别人已经开发并调试好的类。方法的关键在于使用类而不破坏现有程序代码。有两种方式达成此方法的目的:组合和继承。下面将介绍这两种代码重用机制。
组合和继承的实现在新的类中产生现有类的对象,即做组合。该方法只是复用了现有程序代码的功能,而不是它的形式。按照现有类的类型创建新类,无需改变现有类的形式,采用现有类的形式并在其中添加新的代码,此方式就是继承。
只需要将对象的引用置于新类中即可。
class A{ ... } class B{ private A; ... }在Java中,类中域为基本类型时能够被自动初始化为零,对象引用会被初始化为null。编译器并不是简单地为每一个引用都创建默认对象。若是想初始化对象引用,可以在代码中的下列位置进行:
在定义对象的地方。这也意味着它们会在构造器被调用之前被初始化。
在类的构造器中。
在临近使用这些对象之前,再初始化,这种方式就叫做惰性初始化。
使用实例初始化。
使用《Java编程思想》上面的实例说明:
class Soap{ private String s; public Soap() { System.out.println("Soap()无参构造器"); s = "Constructed"; //在类构造器中初始化 } @Override public String toString() { return s;} } public class Bath { private String s1 = "Happy";//在定义对象的地方初始化 private Soap castille = new Soap(); private String s2; private int i; public Bath() { System.out.println("Bath() 无参构造器");} //实例初始化 { i = 31; System.out.println("初始化i为31"); } @Override public String toString() { if(s2 == null) { //惰性初始化 s2 ="Java"; } return s1 + "\t"+ s2 + "\t" + i + "\t" + castille; } public static void main(String[] args) { System.out.println(new Bath()); } } /* output: Soap()无参构造器 初始化i为31 Bath() 无参构造器 Happy Java 31 Constructed */ 继承的实现Java中的继承是使用关键字extends实现的,使用继承子类将会得到父类中所有的域和方法。父类中的私有域和方法将被隐式继承,非私有方法和域将被显式继承。隐式继承也就说可以被间接访问到。
下面将以一个例子说明继承中出现的一些问题。
class Person { private String name; //私有域 public Person() { System.out.println("Person() 无参构造器"); name = "noName"; } public Person(String name) { System.out.println("Person(String name) 带参构造器"); this.name = name; } public String getName() { return name;} //让子类可以间接访问到私有域name public String toString() { return "Person: "+name; } } class Student extends Person{ public Student() { //默认调用 super(); 表示调用父类的无参构造器 System.out.println("Student() 无参构造器"); } public Student(String name) { super(name); //调用父类的带参构造器 System.out.println("Student(String name) 带参构造器"); } public String toString() { return "Student: " + getName();} } public class ExtendsExample { public static void main(String[] args) { System.out.println(new Student()); System.out.println(new Student("sakura")); } } /* output: Person() 无参构造器 Student() 无参构造器 Student: noName Person(String name) 带参构造器 Student(String name) 带参构造器 Student: sakura */子类和父类的构造器调用问题
关于构造器的调用顺序在前面构造方法和匿名对象提过,这里再着重介绍下子类和父类的构造器调用问题。
有一个常识问题就是肯定是先有父再有子,那么在程序中也是,应该是现有父类然后才有子类。Java中使用super关键字表示超类也就是父类。若是子类中没有显式调用父类的构造器,那么编译器就会默认调用super(),即父类的默认构造器;若是父类没有默认构造器,则子类中就必须显式调用父类的带参构造器,并且调用必须放在构造器中的第一行!
super()和this()可以同时存在吗?
通过代码可以得知,super()和this()是不能同时出现在构造器中。需要知道,不管怎么样,在子类构造器调用之前一定会先执行父类的构造器。
组合和继承之间的区别组合和继承都允许在新的类中防止子对象,组合是显式这样做,而继承则是隐式这样做。组合技术通常是用于想在新类中使用现有类的功能而非其接口的情况。即,在新类中嵌入某个对象,让其实现所需要的功能;新类的用户看到的只是为新类所定义的接口,而非所嵌入类的接口。继承是使用某个现有类并开发其特殊版本,会拥有现有类的接口并且可以为新类开发新的接口。所以,继承关系为“is-a”(是一个),组合关系为“has-a”(有一个)。
protected关键字