一、组合语法
class Construct{
public String cont = "Hello World";
}
2.在类的构造器中,如第五章的构造方法初始化:
package com.chenxyt.java.practice;
class Construct{
public String cont;
Construct(String cont){
this.cont = cont;
}
}
public class ConstructTest {
Construct construct = new Construct("Hello");
}
3.延迟加载,我们需要用到这个对象引用了,判断一下是否为null,然后再决定是否初始化
public class ConstructTest {
public static String s;
public static void main(String[] args) {
if(s==null){
s=new String("Hello");
}
}
}
4.使用实例进行初始化,如下边这种,我们没有使用构造方法而是直接赋值了个实例进行初始化
public class ConstructTest {
public static String s;
public static void main(String[] args) {
s="Hello";
}
}
二、继承语法
package com.chenxyt.java.practice;
class Father{
public String Name;
public int age;
private double money;
public void doPrint(){
System.out.println("Hello World");
}
}
public class Son extends Father {
public static void main(String[] args) {
Son son = new Son();
son.Name = "Zhang San";
son.doPrint();
//money是父类私有的域,所以子类不能进行访问
//son.money = 2014;
}
}
子类继承了父类所有的域跟方法,我理解的是对于private修饰的域跟方法也同样继承了下来,只不过private修饰的是类自己私有,对象本身无法访问,比如Father类的对象也无法访问Father类的私有域。同时我做了一个测试来证明这一点。示例中,由于父类显示的写有带参数的构造函数,所以我们必须显示的引用父类的构造函数。
package com.chenxyt.java.practice;
class Father{
public String Name;
public int age;
private double money;
Father(double money){
this.money = money;
}
public double getMoney() {
return money;
}
}
public class Son extends Father {
Son(double money) {
super(money);
// TODO Auto-generated constructor stub
}
public static void main(String[] args) {
Son son = new Son(2014);
son.Name = "Zhang San";
System.out.println(son.getMoney());
}
}
运行结果:

三、代理
package com.chenxyt.java.practice;
class Construct{
public void print(){
System.out.println("print");
}
public void say(){
System.out.println("say");
}
public void clean(){
System.out.println("clean");
}
}
public class Son{
public Construct construct = new Construct();
public void delegation(){
construct.clean();
}
public static void main(String[] args) {
Son son = new Son();
son.delegation();
}
}
四、结合使用组合和继承
package com.chenxyt.java.practice;
class Father{
//---
}
class Mother{
//---
}
public class Son extends Father{
public Mother mother = new Mother();
public static void main(String[] args) {
//---
}
}
关于继承还有一点说明,前文说到子类可以继承父类的全部,所以对于父类重载了的方法,子类也是可以继承并可以重载使用的。而且可以灵活的使用,避免了像C++中需要屏蔽父类该方法的方式。
package com.chenxyt.java.practice;
class Father{
public void doFunc(){
//---
}
public void doFunc(String s){
//--
}
}
public class Son extends Father{
public void doFunc(int i){
//--
}
public static void main(String[] args) {
Son son = new Son();
son.doFunc();
son.doFunc("H");
son.doFunc(1);
}
}
五、在组合和继承之间选择
六、protected关键字
package com.chenxyt.java.practice;
class Father{
protected String s = "Hello";
}
public class Son extends Father{
public static void main(String[] args) {
Son son = new Son();
System.out.println(son.s);
}
}

七、向上转型
在继承的关系中,由于子类继承了父类所有的方法,所以发给父类方法的所有消息,子类都可以接收,注意这里是发给父类方法的所有消息,而不是子类调用了继承的方法。编译器会知道传递的参数引用属于哪一种类型,并将其子类对象引用的类型转换成父类,这个过程称作向上引用。
package com.chenxyt.java.practice;
class Father{
private static String s;
Father(String s){
this.s = s;
}
public static void doFunc(Father father){
System.out.println(s);
}
}
public class Son extends Father{
Son(String s) {
super(s);
// TODO Auto-generated constructor stub
}
public static void main(String[] args) {
Son son = new Son("Hello");
Father.doFunc(son);
}
}
如上所示,父类中有一个static的方法,并且方法的参数是父类的对象,在子类中直接通过类名.方法的形式调用了该方法,并传递了子类的对象引用作为参数。编译器没有报错,运行结果如下:

八、Final关键字
package com.chenxyt.java.practice;
public class FinalTest{
private static final String ARG_NAME = "Hello World";
public static void main(String[] args) {
System.out.println(ARG_NAME);
}
}
如果一个常量被修饰为static final 那么表明这个常量是不可被修改且只有一份的,并且它的命名规则要使用大写且用下划线分割所有单词。对于基本数据类型,final表示这个值不可以修改,对于对象的引用,表示这个引用不可以修改,也就是不可以指向别的对象。
package com.chenxyt.java.practice;
class Gzino{
public void doFunc(){
//--
}
}
public class FinalTest{
public void with(final Gzino g){
//error! 此处不可以修改该对象的引用
//g = new Gzino();
//可以使用该参数
g.doFunc();
}
public void without(Gzino g){
//没有被final修饰,可以使用
g = new Gzino();
g.doFunc();
}
public static void main(String[] args) {
FinalTest ft = new FinalTest();
ft.with(new Gzino());
ft.without(new Gzino());
}
}
3.final方法:使用final方法的原因有两个,第一个是把它锁定,以防任何继承它的类修改这个方法。第二个原因是提高效率,如果一个方法被声明为final方法,那么编译器会跳过这个方法的常规调用方式(参数入栈,跳到方法的执行部分,然后返回清理栈中参数,最后返回结果),并且以方法体中的实际代码副本代替方法调用,这样减小了方法调用的开销,但在方法过大的时候却不实用,因此在JDK1.5之后,取消了该种形式的作用,final方法只用来锁定防止其它类修改。
九、初始化及类加载
在许多语言中,程序在启动的过程中发生了加载,然后是初始化,最后是程序运行。Java不同,Java采用不同的加载机制, 每个类的编译文件都在它自己的代码文件中,该文件只有在用到该程序的时候才被加载。所以一般可以说“类的代码在初次使用时才发生加载“,这通常是指加载发生在创建第一个类对象时,但是当static域被访问时,也会发生加载。
package com.chenxyt.java.practice;
class Insect{
private int i = 9;
protected int j;
public Insect() {
System.out.println("i=" + i + "--j=" + j);
j=39;
}
private static int x1 = printInit("static Insect.x1 initialized");
static int printInit(String s){
System.out.println(s);
return 53;
}
}
public class LoadTest extends Insect{
private int k = printInit("LoadTest.k initialized");
public LoadTest(){
System.out.println("k= " + k);
System.out.println("j= " + j);
}
private static int x2 = printInit("static LoadTest.x2 initialized");
public static void main(String[] args) {
System.out.println("LoadTest constructor");
LoadTest lt = new LoadTest();
}
}
运行结果:

十、总结
继承和组合都能从现有类中得到新的类型,区别在于组合一般是将现有类型作为底层实现的一部分使用,而继承复用的是接口。本章的重点内容是熟悉final关键字的用法以及类加载和初始化的过程,最后一点尤为重要。