【java】复用类

1.

package test;

class Soap {
	  private String s;
	  Soap() {
		  System.out.println("Soap()");
	    s = "Constructed";
	  }
	  public String toString() { return s; }
	}	

	public class Test {
	  private String // Initializing at point of definition:
	    s1 = "Happy",
	    s2 = "Happy",
	    s3, s4;
	  
	  private Soap castille;
	  private int i;
	  private float toy;
	  
//	  构造器初始化
	  public Test() {
		  System.out.println("Inside Test()");
	    s3 = "Joy";
	    toy = 3.14f;
	    castille = new Soap();
	  }	
	  
	  
	  // Instance initialization:实例初始化
	  { 
		  i = 47; 
	  }
	  
	  
	  public String toString() {
	    if(s4 == null) // Delayed initialization:惰性初始化:就在真要使用这些对象之前初始化,称之为惰性初始化
//	    	在生成对象不值得及不必每次都生成对象的情况下,这种方式可以减少额外的负担
	      s4 = "Joy";
	    return
	      "s1 = " + s1 + "\n" +
	      "s2 = " + s2 + "\n" +
	      "s3 = " + s3 + "\n" +
	      "s4 = " + s4 + "\n" +
	      "i = " + i + "\n" +
	      "toy = " + toy + "\n" +
	      "castille = " + castille;
	  }	
	  public static void main(String[] args) {
	    Test b = new Test();
	     System.out.println(b);
	  }
	}

2.

package test;

class Cleanser {
	  private String s = "Cleanser";
	  public void append(String a) { s += a; }
	  public void dilute() { append(" dilute()"); }
	  public void apply() { append(" apply()"); }
	  public void scrub() { append(" scrub()"); }
	  
	  public String toString() { return s; }
	  
	  public static void main(String[] args) {
	    Cleanser x = new Cleanser();
	    x.dilute(); x.apply(); x.scrub();
	    System.out.println(x);
	  }
	}	

	public class Test extends Cleanser {
	  // Change a method:
	  public void scrub() {
	    append(" Test.scrub()");
	    super.scrub(); // Call base-class version
	  }
	  // Add methods to the interface:
	  public void foam() { append(" foam()"); }
	  // Test the new class:
	  public static void main(String[] args) {
	    Test x = new Test();
	    x.dilute();
	    x.apply();
	    x.scrub();
	    x.foam();
	    System.out.println(x);
	    System.out.println("Testing base class:");
	  /*  cleanser.main(args);main虽然是一个主函数,但同时它也是一个静态方法,这里就是一个静态方法的调用,
	    即调用cleaner的静态方法main*/
	    Cleanser.main(args);
	  }	
	}

2.1初始化基类

   子类在调用其构造函数之前都是先完成基类的构造函数初始化。

基类的构造器:(1)总是会被调用;(2)在子类构造器之前被调用(不管子类有没有构造函数)

无参数构造器:

class Art {
  Art() { print("Art constructor"); }
}

class Drawing extends Art {
  Drawing() { print("Drawing constructor"); }
}

public class Cartoon extends Drawing {
  public Cartoon() { print("Cartoon constructor"); }
  public static void main(String[] args) {
    Cartoon x = new Cartoon();
  }
} /* Output:
Art constructor
Drawing constructor
Cartoon constructor
*///:~

带参数的构造器:

package test;

class Game {
	  Game(int i) {
	    System.out.println("Game constructor");
	  }
	}

	class BoardGame extends Game {
	  BoardGame(int i) {
        super(i);
	    System.out.println("BoardGame constructor");
	  }
	}	

	public class Test extends BoardGame {
	  Test() {
	    super(2);
	    System.out.println("Test constructor");
	  }
	  public static void main(String[] args) {
	    Test x = new Test();
	  }
	} /* Output:
	Game constructor
	BoardGame constructor
	Test constructor
	*///:~

参考文章:

Java子类和父类间的调用关系

在讲之前,一些基本知识是应该具备的:

  1、如果一个类中没有定义构造器,编译器在编译时会自动加上默认无参构造器:

  public ClassName {}

  2、this 和 super 的区别。

  3、每个类直接或间接是Object的子类,Object只有一个无参构造方法。

  4、编译器会在每个构造方法的第一行隐式添加父类的默认无参构造器,即添加super()。

  新手容易犯的错误:

  class Employee extends Object {

  public Employee(int id) {

  }

  }

  class Teacher extends Employee {

  public Teacher() {

  }

  }

  以上代码会产生编译错误:

  Implicit super constructor Employee() is undefined. Must explicitly invoke another constructor

  因为父类定义了一个带参数的构造器,因此编译器不会添加默认无参构造方法,但是因为在子类的构造器中没有显式调用父类的某个构造方法,因此编译器会自动添加super()方法, 但是父类中不存在默认无参构造方法,因此会提示默认无参构造方法未定义错误。

  修改后的代码:

  class Employee {

  public Employee(int id) {

  }

  }

  class Teacher extends Employee {

  public Teacher() {

  super(10);

  }

  }

  这样,在子类的构造器中显式调用了父类的某个构造器,所以编译器不会自动添加super()方法。

  构造器的访问修饰符:

  一般可以用public,protected,default和private修饰,但是对于private,子类是无法调用该类构造器的。

  多层次调用父类构造方法:

  假设我们有这样一个层次结构:

  Object->Employee->Teacher->Professor

  class Employee {

  public Employee() {

  System.out.println("Employee constructor called");

  }

  }

  class Teacher extends Employee {

  public Teacher() {

  System.out.println("Teacher constructor called");

  }

  }

  class Professor extends Teacher {

  public Professor() {

  System.out.println("Professor constructor called");

  }

  }

  public class Test {

  public static void main(String args[]) {

  Employee p = new Professor();

  }

  }

  打印结果:

  Employee constructor called

  Teacher constructor called

  Professor constructor called

  在创建Professor对象时(new Professor()),首先会找到该类的无参构造方法,然后首先调用super()方法,调用Teacher类的无参构造方法,接着再调用Employee的无参构造方法,最后再调用Object的无参构造方法。最后再打印出信息。

3.代理

4.结合使用组合和继承

package test;

class Plate {
	  Plate(int i) {
	    System.out.println("Plate constructor");
	  }
	}

	class DinnerPlate extends Plate {
	  DinnerPlate(int i) {
	    super(i);
	    System.out.println("DinnerPlate constructor");
	  }
	}	

	class Utensil {
	  Utensil(int i) {
	    System.out.println("Utensil constructor");
	  }
	}

	class Spoon extends Utensil {
	  Spoon(int i) {
	    super(i);
	    System.out.println("Spoon constructor");
	  }
	}

	class Fork extends Utensil {
	  Fork(int i) {
	    super(i);
	    System.out.println("Fork constructor");
	  }
	}	

	class Knife extends Utensil {
	  Knife(int i) {
	    super(i);
	    System.out.println("Knife constructor");
	  }
	}

	// A cultural way of doing something:
	class Custom {
	  Custom(int i) {
	    System.out.println("Custom constructor");
	  }
	}	

	public class Test extends Custom {
	  private Spoon sp;
	  private Fork frk;
	  private Knife kn;
	  private DinnerPlate pl;
	  public Test(int i) {
	    super(i + 1);
	    sp = new Spoon(i + 2);
	    frk = new Fork(i + 3);
	    kn = new Knife(i + 4);
	    pl = new DinnerPlate(i + 5);
	    System.out.println("Test constructor");
	  }
	  public static void main(String[] args) {
	    Test x = new Test(9);
	  }
	} /* Output:
	Custom constructor
	Utensil constructor
	Spoon constructor
	Utensil constructor
	Fork constructor
	Utensil constructor
	Knife constructor
	Plate constructor
	DinnerPlate constructor
	Test constructor
	*///:~

4.1确保正确清理


      要点:The order of cleanup is the reverse  of the order of initialization



package test;

class Shape {
	  Shape(int i) 
	  { System.out.println("Shape constructor"); }
	  void dispose() 
	  { System.out.println("Shape dispose"); }
	}

	class Circle extends Shape {
	  Circle(int i) {
	    super(i);
	    System.out.println("Drawing Circle");
	  }
	  void dispose() {
	    System.out.println("Erasing Circle");
	    super.dispose();
	  }
	}

	class Triangle extends Shape {
	  Triangle(int i) {
	    super(i);
	    System.out.println("Drawing Triangle");
	  }
	  void dispose() {
	    System.out.println("Erasing Triangle");
	    super.dispose();
	  }
	}

	class Line extends Shape {
	  private int start, end;
	  Line(int start, int end) {
	    super(start);
	    this.start = start;
	    this.end = end;
	    System.out.println("Drawing Line: " + start + ", " + end);
	  }
	  void dispose() {
		  super.dispose();
	    System.out.println("Erasing Line: " + start + ", " + end);
	    
	  }
	}

	public class Test extends Shape {
	  private Circle c;
	  private Triangle t;
	  private Line[] lines = new Line[3];
	  public Test(int i) {
	    super(i + 1);
	    for(int j = 0; j < lines.length; j++)
	      lines[j] = new Line(j, j*j);
	    c = new Circle(1);
	    t = new Triangle(1);
	    System.out.println("Combined constructor");
	  }
	  public void dispose() {
	    System.out.println("Test.dispose()");
	     /*The order of cleanup is the reverse
	     of the order of initialization:*/
	    t.dispose();
	    c.dispose();
	    for(int i = lines.length - 1; i >= 0; i--)
	      lines[i].dispose();
	    super.dispose();
	  }
	  public static void main(String[] args) {
	    Test x = new Test(47);
	    try {
	      // Code and exception handling...
	    } finally {
	      x.dispose();
	    }
	  }
	} 

参考资料:Java finalize方法使用

4.2名称屏蔽

package test;

class Homer {
	  char doh(char c) {
	   System.out.println("doh(char)");
	    return 'd';
	  }
	  float doh(float f) {
	   System.out.println("doh(float)");
	    return 1.0f;
	  }
	}

	class Milhouse {}

	class Bart extends Homer {
	  void doh(Milhouse m) {
	   System.out.println("doh(Milhouse)");
	  }
	}

	public class Test {
	  public static void main(String[] args) {
	    Bart b = new Bart();
	    b.doh(1);
	    b.doh('x');
	    b.doh(1.0f);
	    b.doh(new Milhouse());
	  }
	}


参考资料:java中重写、覆盖,重载三者的区别?
首先要明确Java中重写,覆盖,重载都是针对方法的几个不同概念。其中重写与覆盖等同,只是两种不同的称法而已。 
现在主要来理解下重写与重载的区别? 
以前的理解是: 
重写就是保证跟父类原有方法的返回值,方法名,参数列表一致的前提下,在子类中将函数重新实现一遍。 
而重载就是指返回值和方法名相同,参数列表不同的函数的实现。 
现在细化下理解: 
方法重写(Overriding),是继承与实现中的一个概念,主要指抽象方法的重写。 
方法重载(Overloading) 
两者都是Java中多态性一个的一个体现,方法重写是父类与子类之间多态性的体现,而方法重载主要是类内部多态性的一个体现。 
看如下例子: 
例1: 

?
1
2
3
4
5
6
7
8
9
10
class FatherCat
{
     void eat(){}; //method_1
}
 
class Cat extends FatherCat
{
     void eat(){}; //method_2
     void eat(String fish){}; //method_3
}
例2: 
?
1
2
3
4
5
6
7
8
9
10
abstract class Animal
{
     abstract void eat(); //method_1
}
 
class Cat extends Animal
{
     void eat(){}; //method_2
     void eat(String fish){}; //method_3
}
例3: 
?
1
2
3
4
5
6
7
8
9
10
interface  Animal
{
     abstract void eat(); //method_1
}
 
class Cat implements Animal
{
     public void eat(){}; //method_2
     void eat(String fish){}; //method_3
}
例3注:eat()方法前必须加public权限,因为接口中抽象方法访声明时默认的访问权限都为public,因此子类中实现时,必须重写抽象方法,且访问权限也必须为public. 

三个方法之间的关系如下: 
method_1与method_2: 
重写关系,子类Cat重写父类FatherCat的eat()方法。 
method_2与method_3: 
重载关系,再加一个参数列表不同方法名相同的方法。 
method_1与method_3: 
本来没什么关系,若硬是要扯上关系可看成重载关系(个人理解)。 

具体区别有人罗列为: 

重写(override)又名覆盖: 
1.不能存在同一个类中,在继承或实现关系的类中; 
2. 名相同,参数列表相同,方法返回值相同, 
3.子类方法的访问修饰符要大于父类的。 
4.子类的检查异常类型要小于父类的检查异常。 
重载(overload) 
1.可以在一个类中也可以在继承关系的类中; 
2.名相同; 
3.参数列表不同(个数,顺序,类型) 和方法的返回值类型无关。 


简化为: 
重写就是再写一遍,重载就是再加一个。

final关键字

final数据

package test;

import java.util.*;

class Value {
  int i; // Package access
  public Value(int i) { this.i = i; }
}

public class Test {
  private static Random rand = new Random();
  private String id;
  public Test(String id) { this.id = id; }
  // Can be compile-time constants:
  private final int valueOne = 9;
  private static final int VALUE_TWO = 99;
  // Typical public constant:
  public static final int VALUE_THREE = 39;
  
  
  // Cannot be compile-time constants:
//  INT_5的值不会因为通过创建第二个FinalData对象而加以改变,这是因为
//  它是static的,在加载的时候就已经初始化了,而不是每次创建新对象时初始化
//  但是i4刚好与其相反
 /* output:
  * fd1: i4 = 14, INT_5 = 9
		  fd2: i4 = 9, INT_5 = 9
		  */
  private final int i4 = rand.nextInt(20);
  static final int INT_5 = rand.nextInt(20);
  
  
//  以下两个都是带有编译时数值的final基本类型,没有重大区别
  private Value v1 = new Value(11);
  private final Value v2 = new Value(22);
  
  
  /*典型的对常量进行定义的方式:
   * 定义为:public,则可以被用于包之外
   * 定义为:static,则强调只有一份
   * 定义为:final,则说明是一个常量
   * 注意定义为static final的要注意其命名规则:大写+下划线
   * */
  private static final Value VAL_3 = new Value(33);
  
  
  // Arrays:
  private final int[] a = { 1, 2, 3, 4, 5, 6 };
  public String toString() {
    return id + ": " + "i4 = " + i4 + ", INT_5 = " + INT_5;
  }
  public static void main(String[] args) {
    Test fd1 = new Test("fd1");
    //! fd1.valueOne++; // Error: can't change value
    fd1.v2.i++; // Object isn't constant!
    fd1.v1 = new Value(9); // OK -- not final
    for(int i = 0; i < fd1.a.length; i++)
      fd1.a[i]++; // Object isn't constant!
    //! fd1.v2 = new Value(0); // Error: Can't
    //! fd1.VAL_3 = new Value(1); // change reference
    //! fd1.a = new int[3];
    System.out.println(fd1);
    System.out.println("Creating new Test");
    Test fd2 = new Test("fd2");
    System.out.println(fd1);
    System.out.println(fd2);
  }
}

空白final

package test;

class Poppet {
	  private int i;
	  Poppet(int ii) { i = ii; }
	}

	public class Test {
	  private final int i = 0; // Initialized final
	  private final int j; // Blank final
	  private final Poppet p; // Blank final reference
	  // Blank finals MUST be initialized in the constructor:
	  public Test() {
	    j = 1; // Initialize blank final
	    p = new Poppet(1); // Initialize blank final reference
	  }
	  public Test(int x) {
	    j = x; // Initialize blank final
	    p = new Poppet(x); // Initialize blank final reference
	  }
	  public static void main(String[] args) {
	    new Test();
	    new Test(47);
	  }
	}

final参数

package test;

class Gizmo {
	  public void spin() {}
	}

	public class Test {
//		这一特性主要用来想匿名内部类传递数据
	  void with(final Gizmo g) {
//	     g = new Gizmo(); // Illegal -- g is final
//		  The final local variable g cannot be assigned. 
//		  It must be blank and not using a compound assignment
	  }
	  void without(Gizmo g) {
	    g = new Gizmo(); // OK -- g not final
	    g.spin();
	  }
	  // void f(final int i) { i++; } // Can't change
	  // You can only read from a final primitive:
	  int g(final int i) { return i + 1; }
	  public static void main(String[] args) {
	    Test bf = new Test();
	    bf.without(null);
	    bf.with(null);
	  }
	}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值