Java_03 快速入门 Java面向对象高级知识

目录

第一章:面向对象高级知识

2.1  继承性

范例2-1:要求定义两个描述人与学生的类。

范例2-2:继承的基本实现。

范例2-3:在子类中扩充方法。

范例2-2:错误的继承。

范例2-5:多层继承。

范例2-6:观察属性。

范例2-7:观察实例化对象操作。

范例2-8:子类隐含语句。

范例2-9:父类不提供无参构造方法。

范例2-10:疑问的程序。

2.2  覆写

范例2-11:没有实现方法覆写。

范例2-12:实现方法覆写。

范例2-13:定义更多的子类。

范例2-12:正确的覆写。

范例2-15:正确的方法覆写。

范例2-16:错误的覆写。

范例2-17:正常的覆写。

范例2-18:使用private声明父类中的print()方法。

范例2-19:利用super方法()访问父类中方法。

范例2-20:观察属性覆盖。

2.3  继承案例

范例2-21:基础实现

范例2-22:定义并测试排序子类。

范例2-23:开发反转类并测试。

2.2  final关键字

范例2-22:观察final定义的类。

范例2-25:观察final定义的类。

范例2-26:定义常量。

2.5  多态性

范例2-27:观察如下一个程序。

范例2-28:对象向上转型(自动完成)。

范例2-29:对象向下转型。

范例2-30:错误的向下转型操作。

范例2-31:对象向上转型作用分析。

范例2-32:子类扩充父类方法。

范例2-33:向下转型,调用子类中的特殊功能。

范例2-32:使用instanceof判断。

范例2-35:使用instanceof判断。

2.6  抽象类

范例2-36:定义抽象类。

范例2-37:错误的实例化抽象类对象的操作。

范例2-38:正确使用抽象类。

范例2-39:没有抽象方法的抽象类。

范例2-20:定义抽象类的内部类。

范例2-21:利用static定义的内部抽象类为外部抽象类。

范例2-22:在抽象类中定义static方法

范例2-23:通过内部类的方式定义抽象类子类。

范例2-22:观察属性与构造问题。

范例2-25:在抽象类的普通方法中调用抽象方法。

范例2-26:定义一个行为类。

范例2-27:定义描述机器人的行为子类

范例2-28:定义人的类。

范例2-29:定义猪的类。

范例2-50:测试行为。

2.7  接口

范例2-51:定义接口。

范例2-52:两种接口功能完全等价。

范例2-53:接口方法定义时强烈建议加上public。

范例2-52:实现接口。

范例2-55:接口的转换。

范例2-56:子类继承抽象类并实现接口。

范例2-57:观察接口的多继承。

范例2-58:在接口里定义抽象类。

范例2-59:在一个接口内部如果使用static去定义一个内部接口,该接口就表示是一个外部接口。

范例2-60:定义USB标准。

范例2-61:定义计算机类。

范例2-62:定义U盘子类。

范例2-63:测试代码。

范例2-62:观察程序代码问题。

范例2-65:定义新的子类。

范例2-66:修改客户端代码。

范例2-67:增加一个工厂类进行过渡。

范例2-68:代理设计模式实现。

2.8  Object类

范例2-69:利用Object类来接收对象。

范例2-70:观察自定义类对象与String类对象直接输出。

范例2-71:覆写toString()方法。

范例2-72:实现对象比较。

范例2-73:接收数组数据。

范例2-72:Object类接收接口对象。

范例2-75:修改可用链表。

范例2-76:测试新链表——利用String类型完成。

2.9  综合练习:宠物商店

范例2-77:定义出宠物的标准。

范例2-78:定义宠物商店。

范例2-79:定义宠物猫子类。

范例2-80:定义宠物狗子类。

范例2-81:编写测试类。

2.10  匿名内部类

范例2-82:分析匿名内部类的产生动机。

范例2-83:采用匿名内部类简化类的定义。

2.11  基本数据类型的包装类

范例2-82:包装类雏形。

范例2-85:使用int和Integer。

范例2-86:使用double和Double。

范例2-87:使用boolean和Boolean(不是Number子类)。

范例2-88:观察自动装箱与自动拆箱。

范例2-89:观察Integer的实例化操作问题。

范例2-90:利用Object接收基本数据类型。

范例2-91:观察double类型的自动装箱与拆箱操作。

范例2-92:观察Boolean类型的自动装箱与拆箱操作。

范例2-93:将字符串变为int型数据。

范例2-92:错误的转换操作。

范例2-95:观察double转换。

范例2-96:观察boolean转换。


第一章:面向对象高级知识

2.1  继承性

范例2-1:要求定义两个描述人与学生的类。

Person.java:

Student.java:

class Person {

    private String name ;

    private int age ;

    public void setName(String name) {

        this.name = name ;

    }

    public void setAge(int age) {

        this.age = age ;

    }

    public String getName() {

        return this.name ;

    }

    public int getAge() {

        return this.age ;

    }

}

class Student {

    private String name;

    private int age;

    private String school;

    public void setName(String name) {

        this.name = name;

    }

    public void setAge(int age) {

        this.age = age;

    }

    public void setSchool(String school) {

        this.school = school;

    }

    public String getSchool() {

        return this.school;

    }

    public String getName() {

        return this.name;

    }

    public int getAge() {

        return this.age;

    }

}

范例2-2:继承的基本实现。

class Person {

    private String name;

    private int age;

    public void setName(String name) {

        this.name = name;

    }

    public void setAge(int age) {

        this.age = age;

    }

    public String getName() {

        return this.name;

    }

    public int getAge() {

        return this.age;

    }

}

class Student extends Person { // Student类继承了Person类

    // 此类没有定义任何的操作方法

}

public class TestDemo {

    public static void main(String args[]) {

        Student stu = new Student(); // 实例化的是子类

        stu.setName("张三"); // Person类定义

        stu.setAge(20); // Person类定义

        System.out.println("姓名:" + stu.getName() + ",年龄:" + stu.getAge());

    }

}

范例2-3:在子类中扩充方法。

class Person {

    private String name;

    private int age;

    public void setName(String name) {

        this.name = name;

    }

    public void setAge(int age) {

        this.age = age;

    }

    public String getName() {

        return this.name;

    }

    public int getAge() {

        return this.age;

    }

}

class Student extends Person { // Student类继承了Person类

    private String school ; // 子类扩充的属性

    public void setSchool(String school) { // 扩充的方法

        this.school = school ;

    }

    public String getSchool() { // 扩充的方法

        return this.school ;

    }

}

public class TestDemo {

    public static void main(String args[]) {

        Student stu = new Student(); // 实例化的是子类

        stu.setName("张三"); // Person类定义

        stu.setAge(20); // Person类定义

        stu.setSchool("清华大学") ;   // Student类扩充方法

        System.out.println("姓名:" + stu.getName() + ",年龄:" + stu.getAge()

                + ",学校:" + stu.getSchool());

    }

}

范例2-2:错误的继承。

class A {}

class B {}

class C extends A,B {}   // 一个子类继承了两个父类

范例2-5:多层继承。

class A {}

class B extends A {} // B类继承A类

class C extends B {} // C类继承B类

范例2-6:观察属性。

class A {

private String msg;

public void setMsg(String msg) {

    this.msg = msg;

}

public String getMsg() {

    return this.msg;

}

}

class B extends A { // 继承自A类

}

public class Demo {

public static void main(String args[]) {

    B b = new B();

    b.setMsg("Hello"); // 设置msg属性,属性通过A类继承

    System.out.println(b.getMsg()); // 通过子类对象取得msg属性

}

}

范例2-7:观察实例化对象操作。

class A {

public A() { // 父类提供的无参构造方法

System.out.println("A、A类的构造方法!");

}

}

class B extends A { // B是子类继承父类A

public B() { // 定义子类的构造方法

System.out.println("B、B类的构造方法!");

}

}

public class Demo {

public static void main(String args[]) {

new B(); // 实例化子类对象

}

}

范例2-8:子类隐含语句。

class B extends A { // B是子类继承父类A

public B() { // 定义子类的构造方法

super() ; // 父类中有无参构造时加与不加无区别,如果编写则必须出现在首行

System.out.println("B、B类的构造方法!");

}

}

范例2-9:父类不提供无参构造方法。

class A {

    public A(String title) { // 父类提供的有参构造方法

System.out.println("A、A类的构造方法,title = " + title);   

   }

}

class B extends A { // 定义子类B

    public B(String title) { // 子类提供有参构造

        super(title); // 明确调用父类构造,否则将出现编译错误

        System.out.println("B、B类的构造方法!");

   }

}

public class Demo {

    public static void main(String args[]) {

        new B("Hello"); // 实例化子类对象

    }

}

范例2-10:疑问的程序。

class A {

public A(String msg) { // 父类无参构造

System.out.println("msg = " + msg);

}

}

class B extends A {

public B(String msg) { // 子类构造

this("MLDN", 30); // 调用本类构造,无法使用“super()”

}

public B(String msg,int age) {// 子类构造

this(msg) ; // 调用本类构造,无法使用“super()”

}

}

public class TestDemo {

public static void main(String args[]) {

B b = new B("HELLO",20); // 实例化子类对象

}

}

2.2  覆写

范例2-11:没有实现方法覆写。

class A {

public void fun() { // 在父类中定义的方法

System.out.println("A类中的fun()方法。") ;

}

}

class B extends A { // 定义子类,此时没有覆写任何方法

}

public class TestDemo {

public static void main(String args[]) {

B b = new B() ; // 实例化子类对象

b.fun() ; // 调用fun()方法

}

}

范例2-12:实现方法覆写。

class A {

 public void fun() { // 在父类中定义的方法

  System.out.println("A类中的fun()方法。") ;

 }

}

class B extends A { // 定义子类,此时没有覆写任何方法

 public void fun() { // 此处为覆写

 System.out.println("B类中的fun()方法。") ;

}

}

public class TestDemo {

 public static void main(String args[]) {

  B b = new B() ; // 实例化子类对象

  b.fun() ; // 调用fun()方法,此时方法被覆写,所以调用被覆写过的方法

}

}

范例2-13:定义更多的子类。

class A {

public void fun() { // 在父类中定义的方法

System.out.println("A类中的fun()方法。") ;

}

}

class B extends A { // 定义子类,此时没有覆写任何方法

public void fun() { // 此处为覆写

System.out.println("B类中的fun()方法。") ;

}

}

class C extends A {

public void fun() { // 此处为覆写

System.out.println("C类中的fun()方法。") ;

}

}

public class TestDemo {

public static void main(String args[]) {

B b = new B() ; // 实例化子类对象

b.fun() ; // 调用fun()方法,此时方法被覆写,所以调用被覆写过的方法

C c = new C() ; // 实例化子类对象

c.fun() ; // 调用fun()方法,此时方法被覆写所以调用被覆写过的方法

}

}

范例2-12:正确的覆写。

class A {

public void fun() { // 在父类中定义的方法

System.out.println("A类中的fun()方法。") ;

}

}

class B extends A { // 定义子类,此时没有覆写任何方法

// 父类中的fun()方法权限为public,此时子类中的方法权限并没有变得严格,而是与父类一致

public void fun() { // 此处为覆写

System.out.println("B类中的fun()方法。") ;

}

}

public class TestDemo {

public static void main(String args[]) {

B b = new B() ; // 实例化子类对象

b.fun() ; // 调用fun()方法,此时方法被覆写,所以调用被覆写过的方法

}

}

范例2-15:正确的方法覆写。

class A {

void fun() { // 在父类中定义的方法

System.out.println("A类中的fun()方法。") ;

}

}

class B extends A { // 定义子类,此时没有覆写任何方法

// 父类中的fun()方法权限为public,此时子类中的方法权限与父类相比更加宽松

public void fun() { // 此处为覆写

System.out.println("B类中的fun()方法。") ;

}

}

范例2-16:错误的覆写。

class A {

public void fun() {

System.out.println("A类中的fun()方法。") ;

}

}

class B extends A {

void fun() { // 此处不能覆写,因为权限更加严格

System.out.println("B类中的fun()方法。") ;

}

}

范例2-17:正常的覆写。

class A {

public void fun() {

this.print() ; // 调用print()方法

}

public void print() {

System.out.println("更多课程请访问:www.mldn.cn") ;

}

}

class B extends A {

public void print() { // 覆写的是print()方法

System.out.println("更多课程请访问:www.yootk.com") ;

}

}

public class TestDemo {

public static void main(String args[]) {

B b = new B() ; // 实例化子类对象

b.fun() ; // 调用父类继承来的fun()方法

}

}

范例2-18:使用private声明父类中的print()方法。

class A {

public void fun() {

this.print() ; // 调用print()方法

}

private void print() { // 此为private权限,无法覆写

System.out.println("更多课程请访问:www.mldn.cn") ;

}

}

class B extends A {

public void print() { // 不能覆写print()方法

System.out.println("更多课程请访问:www.yootk.com") ;

}

}

public class TestDemo {

public static void main(String args[]) {

B b = new B() ; // 实例化子类对象

b.fun() ; // 调用父类继承来的fun()方法

}

}

范例2-19:利用super方法()访问父类中方法。

class A {

public void print() {

System.out.println("更多课程请访问:www.mldn.cn") ;

}

}

class B extends A {

public void print() { // 覆写的是print()方法

super.print(); // 访问父类中的print()方法

System.out.println("更多课程请访问:www.yootk.com") ;

}

}

public class TestDemo {

public static void main(String args[]) {

B b = new B() ; // 实例化子类对象

b.print() ;

}

}

范例2-20:观察属性覆盖。

class A {

String info = "Hello"; // 定义属性,暂不封装

}

class B extends A {

int info = 100; // 名称相同,发生属性覆盖

public void print() {

System.out.println(super.info);

System.out.println(this.info);

}

}

public class TestDemo {

public static void main(String args[]) {

B b = new B(); // 实例化子类对象

b.print();

}

}

2.3  继承案例

范例2-21:基础实现

class Array { // 定义数组操作类

private int data[]; // 定义一个数组对象,此数组由外部设置长度

private int foot; // 表示数组的操作脚标

/**

 * 构造本类对象时需要设置大小,如果设置的长度小于0则维持一个大小

 * @param len 数组开辟时的长度

 */

public Array(int len) {

if (len > 0) { // 设置的长度大于0

this.data = new int[len]; // 开辟一个数组

} else { // 设置的长度小于等于0

this.data = new int[1]; // 维持一个元素的大小

}

}

/**

 * 向数组中增加元素

 * @param num 要增加的数据

 * @return 如果数据增加成功返回true,如果数组中保存数据已满则返回false

 */

public boolean add(int num) {

if (this.foot < this.data.length) { // 有空间保存

this.data[this.foot++] = num; // 保存数据,修改脚标

return true; // 保存成功

}

return false; // 保存失败

}

/**

 * 取得所有的数组内容

 * @return 数组对象引用

 */

public int[] getData() {

return this.data;

}

}

public class TestDemo {

public static void main(String args[]) {

Array arr = new Array(3); // 实例化数组操作类对象,可操作数组长度为3

System.out.print(arr.add(20) + "、"); // 可以保存数据

System.out.print(arr.add(10) + "、"); // 可以保存数据

System.out.print(arr.add(30) + "、"); // 可以保存数据

System.out.println(arr.add(100) + "、"); // 不可以保存数据,返回false

int[] temp = arr.getData(); // 取得全部数组数据

for (int x = 0; x < temp.length; x++) { // 循环输出数据

System.out.print(temp[x] + "、");

}

}

}

范例2-22:定义并测试排序子类。

class SortArray extends Array { // 定义排序子类

public SortArray(int len) { // Array类里面有无参构造方法

super(len); // 明确调用父类的有参构造,为父类中的data属性初始化

}

/**

 * 因为父类中getData()方法不能满足排序的操作要求,但为了保存这个方法名称,所以进行覆写

 * 在本方法中要使用java.util.Arrays.sort()来实现数组的排序操作

 * @return 排序后的数据

 */

public int[] getData() {

java.util.Arrays.sort(super.getData()); // 排序

return super.getData(); // 返回排序后的数据

}

}

public class TestDemo {

public static void main(String args[]) {

SortArray arr = new SortArray(3); // 实例化数组操作类对象,可操作数组长度为3

System.out.print(arr.add(20) + "、"); // 可以保存数据

System.out.print(arr.add(10) + "、"); // 可以保存数据

System.out.print(arr.add(30) + "、"); // 可以保存数据

System.out.println(arr.add(100) + "、"); // 不可以保存数据,返回false

int[] temp = arr.getData(); // 取得全部数组数据

for (int x = 0; x < temp.length; x++) { // 循环输出数据

System.out.print(temp[x] + "、");

}

}

}

范例2-23:开发反转类并测试。

class ReverseArray extends Array { // 数组反转类

public ReverseArray(int len) { // Array类里面没有无参构造方法

super(len); // 调用父类有参构造

}

/**

 * 取得反转后的数组数据,在本方法中会将数据进行首尾交换

 * @return 反转后的数据

 */

public int[] getData() {

int center = super.getData().length / 2; // 计算反转次数

int head = 0; // 头部脚标

int tail = super.getData().length - 1; // 尾部脚标

for (int x = 0; x < center; x++) { // 反转

int temp = super.getData()[head]; // 数据交换

super.getData()[head] = super.getData()[tail];

super.getData()[tail] = temp;

head++;

tail--;

}

return super.getData(); // 返回反转后的数据

}

}

public class TestDemo {

public static void main(String args[]) {

ReverseArray arr = new ReverseArray(3); // 实例化数组操作类对象,可操作数组长度为3

System.out.print(arr.add(20) + "、"); // 可以保存数据

System.out.print(arr.add(10) + "、"); // 可以保存数据

System.out.print(arr.add(30) + "、"); // 可以保存数据

System.out.println(arr.add(100) + "、"); // 不可以保存数据,返回false

int[] temp = arr.getData(); // 取得全部数组数据

for (int x = 0; x < temp.length; x++) { // 循环输出数据

System.out.print(temp[x] + "、");

}

}

}

2.2  final关键字

范例2-22:观察final定义的类。

final class A {   // 此类不能够有子类

}

class B extends A { // 错误的继承

}

范例2-25:观察final定义的类。

class A {

public final void fun() {} // 此方法不允许子类覆写

}

class B extends A {

public void fun() {} // 错误:此处不允许覆写

}

范例2-26:定义常量。

class A {

final double GOOD = 100.0; // GOOD级别就是100.0

public final void fun() {

GOOD = 1.1;  // 错误:不能够修改常量

}

}

2.5  多态性

范例2-27:观察如下一个程序。

Class A {

public void print() {

System.out.println("A、public void print(){}");

}

}

class B extends A {

public void print() { // 此时子类覆写了父类中的print()方法

System.out.println("B、public void print(){}");

}

}

public class TestDemo {

public static void main(String args[]) {

B b = new B(); // 实例化的是子类对象

b.print(); // 调用被子类覆写过的方法

}

}

范例2-28:对象向上转型(自动完成)。

public class TestDemo {

public static void main(String args[]) {

A a = new B(); // 实例化的是子类对象,对象向上转型

a.print(); // 调用被子类覆写过的方法

}

}

范例2-29:对象向下转型。

public class TestDemo {

public static void main(String args[]) {

A a = new B(); // 实例化的是子类对象,对象向上转型

B b = (B) a ; // 对象需要强制性地向下转型

b.print(); // 调用被子类覆写过的方法

}

}

范例2-30:错误的向下转型操作。

public class TestDemo {

public static void main(String args[]) {

A a = new A(); // 直接实例化子类对象

// 此时并没有发生子类对象向上转型的操作,所以强制转型会带来安全隐患

B b = (B) a; // 强制向下转型,此处产生“ClassCastException”异常

b.print(); // 此语句无法执行

}

}

范例2-31:对象向上转型作用分析。

class A {

public void print() {

System.out.println("A、public void print(){}");

}

}

class B extends A { // 定义A的子类

public void print() { // 此时子类覆写了父类中的print()方法

System.out.println("B、public void print(){}");

}

}

class C extends A { // 定义A的子类

public void print() { // 此时子类覆写了父类中的print()方法

System.out.println("C、public void print(){}");

}

}

public class TestDemo {

public static void main(String args[]) {

fun(new B()) ; // 对象向上转型,等价于:A a = new B() ;

fun(new C()) ; // 对象向上转型,等价于:A a = new C() ;

}

/**

 * 接收A类或其子类对象,不管传递哪个对象都要求调用print()方法

 * @param a A类实例化对象

 */

public static void fun(A a) {

a.print();

}

}

范例2-32:子类扩充父类方法。

class A {

public void print() {

System.out.println("A、public void print(){}");

}

}

class B extends A { // 定义A的子类

public void print() { // 此时子类覆写了父类中的print()方法

System.out.println("B、public void print(){}");

}

/**

 * 在子类中扩充一个新的方法,但是此方法只能由子类对象调用,父类对象不能调用

 */

public void funB() {

System.out.println("B、扩充的funB()方法");

}

}

范例2-33:向下转型,调用子类中的特殊功能。

public class TestDemo {

public static void main(String args[]) {

fun(new B()); // 向上转型,只能调用父类中定义的方法

}

public static void fun(A a) {

B b = (B) a; // 要调用子类的特殊操作,需要向下转型

b.funB(); // 调用子类的扩充方法

}

}

范例2-32:使用instanceof判断。

public class TestDemo {

public static void main(String args[]) {

A a = new B(); // 对象向上转型

System.out.println(a instanceof A);

System.out.println(a instanceof B);

System.out.println(null instanceof A);

}

}

范例2-35:使用instanceof判断。

class A {

public void print() {

System.out.println("A、public void print(){}");

}

}

class B extends A { // 定义A的子类

public void print() { // 此时子类覆写了父类中的print()方法

System.out.println("B、public void print(){}");

}

public void funB() {

System.out.println("B、扩充的funB()方法");

}

}

public class TestDemo {

public static void main(String args[]) {

fun(new B()) ; // 对象向上转型

}

public static void fun(A a) {

a.print() ;

if (a instanceof B) { // 如果a对象是B类的实例

B b = (B) a; // 向下转型

b.funB(); // 调用子类扩充的方法

}

}

}

2.6  抽象类

范例2-36:定义抽象类。

abstract class A { // 定义一个抽象类,使用abstract声明

public void fun() { // 普通方法

System.out.println("存在有方法体的方法!");

}

// 此方法并没有方法体的声明,并且存在abstract关键字,表示抽象方法

public abstract void print();

}

范例2-37:错误的实例化抽象类对象的操作。

public class TestDemo {

public static void main(String args[]) {

A a = new A(); // A是抽象的,无法实例化

}

}

范例2-38:正确使用抽象类。

abstract class A { // 定义一个抽象类,使用abstract声明

public void fun() { // 普通方法

System.out.println("存在有方法体的方法!");

}

// 此方法并没有方法体的声明,并且存在abstract关键字,表示抽象方法

public abstract void print();

}

//一个子类只能够继承一个抽象类,属于单继承局限

class B extends A { // B类是抽象类的子类,并且是一个普通类

public void print() { // 强制要求覆写的方法

System.out.println("Hello World !") ;

}

}

public class TestDemo {

public static void main(String args[]) {

A a = new B() ; // 向上转型

a.print() ; // 被子类覆写过的方法

}

}

范例2-39:没有抽象方法的抽象类。

abstract class A { // 定义一个抽象类

public void print() { // 此为普通方法

System.out.println("更多课程请访问:www.yootk.com") ;

}

}

class X extends A { // 抽象类必须有子类

}

public class TestDemo {

public static void main(String args[]) {

A a = new X() ; // 通过子类实例化抽象类对象

a.print();

}

}

范例2-20:定义抽象类的内部类。

abstract class A { // 定义一个抽象类

abstract class B { // 定义内部抽象类

public abstract void print() ;

}

}

class X extends A { // 继承static内部抽象类

public void print() {

System.out.println("更多课程请访问:www.yootk.com") ;

}

class Y extends B { // 定义内部抽象类的子类,此类不是必须编写

public void print() {

// 方法覆写

}

}

}

范例2-21:利用static定义的内部抽象类为外部抽象类。

abstract class A { // 定义一个抽象类

static abstract class B { // static定义的内部类属于外部类

public abstract void print() ;

}

}

class X extends A.B { // 继承static内部抽象类

public void print() {

System.out.println("更多课程请访问:www.yootk.com") ;

}

}

public class TestDemo {

public static void main(String args[]) {

A.B ab = new X() ; // 向上转型

ab.print() ;

}

}

范例2-22:在抽象类中定义static方法

abstract class A { // 定义一个抽象类

public static void print() { // static方法

System.out.println("更多课程请访问:www.yootk.com") ;

}

}

public class TestDemo {

public static void main(String args[]) {

A.print() ; // 直接调用static方法

}

}

范例2-23:通过内部类的方式定义抽象类子类。

abstract class A { // 定义一个抽象类

public abstract void print(); // 定义抽象方法

private static class B extends A { // 内部抽象类子类

public void print() { // 覆写抽象类的方法

System.out.println("更多课程请访问:www.yootk.com");

}

}

public static A getInstance() { // 此方法可以通过类名称直接调用

return new B();

}

}

public class TestDemo {

public static void main(String args[]) {

// 此时取得抽象类对象时完全不需要知道B类这个子类存在

A a = A.getInstance();

a.print(); // 调用被覆写过的抽象方法

}

}

范例2-22:观察属性与构造问题。

abstract class A { // 定义抽象类

public A() { // 2. 父类构造方法

// 此方法为抽象方法,所以要调用子类中已经被覆写过的方法

this.print(); // 3. 调用print()方法

}

public abstract void print(); // 抽象方法

}

class B extends A {

private int num = 100; // 子类属性的默认值,无用

public B(int num) { // 通过构造设置内容

this.num = num; // 保存属性

}

public void print() { // 2. 调用覆写后方法

// num在子类对象未构造前,还未被初始化,内容是其对应数据类型的默认值

System.out.println("num = " + num);

}

}

public class TestDemo {

public static void main(String args[]) {

new B(30); // 1. 执行构造

}

}

范例2-25:在抽象类的普通方法中调用抽象方法。

abstract class A { // 定义一个抽象类

public void fun() { // 此为普通方法

this.print() ; // 在普通方法中直接调用抽象方法

}

public abstract void print() ; // 此为抽象方法

}

class X extends A { // 抽象类必须有子类

public void print() {

System.out.println("更多课程请访问:www.yootk.com") ;

}

}

public class TestDemo {

public static void main(String args[]) {

A a = new X() ; // 通过子类实例化抽象类对象

a.fun(); // 抽象类中的普通方法

}

}

范例2-26:定义一个行为类。

abstract class Action { // 定义一个抽象的行为类,行为不是具体的

// 定义常量时必须保证两个内容相加的结果不是其他行为,例如:EAT + SLEEP的结果为6,不会和其他值冲突

public static final int EAT = 1; // 定义吃的命令

public static final int SLEEP = 5; // 定义睡的命令

public static final int WORK = 7; // 定义工作的命令

/**

 * 控制操作的行为,所有的行为都通过类中的常量描述,可以使用EAT、SLEEP、WORK

 * 或者进行命令的叠加使用,例如:边吃边工作,使用EAT + WORK来描述

 * @param flag 操作的行为标记

 */

public void command(int flag) {

switch (flag) { // switch只支持数值判断,而if支持条件判断

case EAT: // 当前为吃的操作

this.eat(); // 调用子类中具体的“吃”方法

break;

case SLEEP: // 当前为睡的操作

this.sleep(); // 调用子类中具体的“睡”方法

break;

case WORK: // 当前为工作的操作

this.work(); // 调用子类中具体的“工作”方法

break;

case EAT + WORK: // 行为组合,本处只是举例说明,不演示

this.eat(); // 调用“吃”的方法

this.work(); // 调用“工作”的方法

break;

}

}

public abstract void eat(); // 定义子类的操作标准

public abstract void sleep(); // 定义子类的操作标准

public abstract void work(); // 定义子类的操作标准

}

范例2-27:定义描述机器人的行为子类

class Robot extends Action { // 定义机器人行为

public void eat() { // 覆写行为的操作

System.out.println("机器人补充能量!");

}

public void sleep() { // 此操作不需要但必须覆写,所以方法体为空

}

public void work() { // 覆写行为的操作

System.out.println("机器人正在努力工作!");

}

}

范例2-28:定义人的类。

class Human extends Action { // 定义人类行为

public void eat() { // 覆写行为的操作

System.out.println("人类正在吃饭!");

}

public void sleep() { // 覆写行为的操作

System.out.println("人类正在睡觉休息!");

}

public void work() { // 覆写行为的操作

System.out.println("人为了梦想在努力工作!");

}

}

范例2-29:定义猪的类。

class Pig extends Action {

public void eat() { // 覆写行为的操作

System.out.println("猪正在啃食槽!");

}

public void sleep() { // 覆写行为的操作

System.out.println("猪在睡觉养膘!");

}

public void work() { // 此操作不需要但必须覆写,所以方法体为空

}

}

范例2-50:测试行为。

public class TestDemo {

public static void main(String args[]) {

fun(new Robot()); // 传递机器人行为子类

fun(new Human()); // 传递人类行为子类

fun(new Pig()); // 传递猪的行为子类

}

/**

 * 执行具体的操作行为,假设本处只执行EAT、SLEEP、WORK3个行为

 * @param act 具体的行为对象

 */

public static void fun(Action act) {

act.command(Action.EAT); // 调用“吃”操作

act.command(Action.SLEEP); // 调用“睡”操作

act.command(Action.WORK); // 调用“工作”操作

}

}

2.7  接口

范例2-51:定义接口。

interface A { // 定义接口

public static final String MSG = "YOOTK"; // 全局常量

public abstract void print(); // 抽象方法

}

范例2-52:两种接口功能完全等价。

interface A {

public static final String MSG = "HELLO";

public abstract void fun();

}

interface A {

String MSG = "HELLO";

void fun();

}

范例2-53:接口方法定义时强烈建议加上public。

interface A {

String MSG = "HELLO";

public void fun();

}

范例2-52:实现接口。

interface A { // 定义接口

public static final String MSG = "YOOTK"; // 全局常量

public abstract void print(); // 抽象方法

}

interface B { // 定义接口

public abstract void get(); // 抽象方法

}

class X implements A, B { // X类实现了A和B两个接口

public void print() { // 覆写A接口的抽象方法

System.out.println("A接口的抽象方法!");

}

public void get() { // 覆写B接口的抽象方法

System.out.println("B接口的抽象方法!");

}

}

public class TestDemo {

public static void main(String args[]) {

// 此时X类是A和B两个接口的子类,所以此类对象可以同时实现两个接口的向上转型

X x = new X(); // 实例化子类对象

A a = x; // 向上转型

B b = x; // 向上转型

a.print(); // 调用被覆写过的方法

b.get(); // 调用被覆写过的方法

System.out.println(A.MSG); // 直接访问全局常量

}

}

范例2-55:接口的转换。

public class TestDemo {

public static void main(String args[]) {

A a = new X() ; // 对象向上转型

B b = (B) a ; // a实际上代表的是X类对象

b.get() ; // 调用B接口方法

System.out.println(a instanceof A) ; // 判断a是否是A接口实例,true

System.out.println(a instanceof B) ; // 判断a是否是B接口实例,true

}

}

范例2-56:子类继承抽象类并实现接口。

interface A { // 定义接口

public abstract void print(); // 抽象方法

}

interface B { // 定义接口

public abstract void get(); // 定义抽象方法

}

abstract class C { // 定义抽象类

public abstract void change(); // 定义抽象方法

}

class X extends C implements A, B { // X类继承了抽象类C,实现了A和B两个接口

public void print() { // 覆写接口A中的方法

System.out.println("A接口的抽象方法!");

}

public void get() { // 覆写接口B中的方法

System.out.println("B接口的抽象方法!");

}

public void change() { // 覆写抽象类C的方法

System.out.println("C类的抽象方法!");

}

}

范例2-57:观察接口的多继承。

interface A { // 定义父接口

public void funA();

}

interface B { // 定义父接口

public void funB();

}

interface C extends A, B { // 利用extends,实现接口多继承

public void funC();

}

class X implements C { // 实现C接口子类要覆写全部抽象方法

public void funA() {} // A接口定义的方法

public void funB() {} // B接口定义的方法

public void funC() {} // C接口定义的方法

}

范例2-58:在接口里定义抽象类。

interface A {

public void funA();

abstract class B { // 定义接口中的抽象类

public abstract void funB();

}

}

class X implements A { // X实现了A接口

public void funA() {

System.out.println("Hello World !");

}

class Y extends B { // 内部抽象类的子类,可以选择性继承

public void funB() {}

}

}

范例2-59:在一个接口内部如果使用static去定义一个内部接口,该接口就表示是一个外部接口。

interface A {

public void funA();

static interface B { // 外部接口

public void funB();

}

}

class X implements A.B { // X实现了A接口

public void funB() {}

}

范例2-60:定义USB标准。

interface USB { // 定义标准一定就是接口

public void start(); // USB设备开始工作

public void stop(); // USB设备停止工作

}

范例2-61:定义计算机类。

class Computer {

public void plugin(USB usb) { // 插入USB接口设备(子类对象)

usb.start(); // 开始工作

usb.stop(); // 停止工作

}

}

范例2-62:定义U盘子类。

class Flash implements USB { // 实现USB接口

public void start() {

System.out.println("U盘开始使用");

}

public void stop() {

System.out.println("U盘停止使用");

}

}

范例2-63:测试代码。

public class TestDemo {

public static void main(String args[]) {

Computer com = new Computer(); // 实例化计算机类

com.plugin(new Flash()); // 插入USB接口设备

com.plugin(new Print()); // 插入USB接口设备

}

}

范例2-62:观察程序代码问题。

interface Fruit { // 定义接口

public void eat(); // 定义抽象方法

}

class Apple implements Fruit { // 定义接口子类

public void eat() { // 覆写抽象方法

System.out.println("*** 吃苹果。");

}

}

public class TestDemo {

public static void main(String args[]) {

Fruit f = new Apple(); // 子类实例化父类对象

f.eat(); // 调用被覆写过的方法

}

}

范例2-65:定义新的子类。

class Orange implements Fruit { // 定义接口子类

public void eat() { // 覆写抽象方法

System.out.println("*** 吃橘子。");

}

}

范例2-66:修改客户端代码。

public class TestDemo {

public static void main(String args[]) {

Fruit f = new Orange(); // 子类实例化父类对象

f.eat(); // 调用被覆写过的方法

}

}

范例2-67:增加一个工厂类进行过渡。

class Factory { // 定义工厂类,此类不提供属性

/**

 * 取得指定类型的接口对象

 * @param className 要取得的类实例化对象标记

 * @return 如果指定标记存在,则Fruit接口的实例化对象,否则返回null

 */

public static Fruit getInstance(String className) {

if ("apple".equals(className)) { // 是否是苹果类

return new Apple();

} else if ("orange".equals(className)) { // 是否是橘子类

return new Orange();

} else {

return null;

}

}

}

public class TestDemo {

public static void main(String args[]) {

Fruit f = Factory.getInstance("orange"); // 通过工厂类取得指定标记的对象

f.eat(); // 调用接口方法

}

}

范例2-68:代理设计模式实现。

interface Network{ // 定义Network接口

public void browse() ; // 定义浏览的抽象方法

}

class Real implements Network{ // 真实的上网操作

public void browse(){ // 覆写抽象方法

System.out.println("上网浏览信息") ;

}

}

class Proxy implements Network{ // 代理上网

private Network network ;

public Proxy(Network network){ // 设置代理的真实操作

this.network = network ; // 设置代理的子类

}

public void check(){ // 与具体上网相关的操作

System.out.println("检查用户是否合法");

}

public void browse(){

this.check() ; // 可以同时调用多个与具体业务相关的操作

this.network.browse() ; // 调用真实上网操作

}

}

public class TestDemo {

public static void main(String args[]){

Network net = null ; // 定义接口对象

net = new Proxy(new Real()) ; // 实例化代理,同时传入代理的真实操作

net.browse() ; // 客户只关心上网浏览一个功能

}

}

2.8  Object类

范例2-69:利用Object类来接收对象。

class Book extends Object {

}

public class TestDemo {

public static void main(String args[]) {

Object obja = new Book(); // 向上转型,接收Book子类对象

Object objb = "hello"; // 向上转型,接收String子类对象

Book b = (Book) obja; // 测试向下转型

String s = (String) objb; // 测试向下转型

}

}

本程序为了测试Object可以接收任意类对象,使用Book类

范例2-70:观察自定义类对象与String类对象直接输出。

class Book extends Object { // 子类可以继承Object类中的方法

}

public class TestDemo {

public static void main(String args[]) {

Object obja = new Book(); // 向上转型,接收Book子类对象

Object objb = "yootk"; // 向上转型,接收String子类对象

System.out.println(obja);

System.out.println(obja.toString()); // 直接调用toString()方法输出

System.out.println(objb); // 输出String对象

}

}

范例2-71:覆写toString()方法。

class Book { // 此类为Object子类

private String title;

private double price;

public Book(String title, double price) {

this.title = title;

this.price = price;

}

public String toString() { // 替代了getInfo(),并且toString()可以自动调用

return "书名:" + this.title + ",价格:" + this.price;

}

// setter、getter、无参构造略

}

public class TestDemo {

public static void main(String args[]) {

Book b = new Book("Java开发", 79.9); // 实例化对象

System.out.println(b); // 直接输出对象,默认调用toString()

}

}

范例2-72:实现对象比较。

class Book {

private String title;

private double price;

public Book(String title, double price) {

this.title = title;

this.price = price;

}

public boolean equals(Object obj) {

if (this == obj) { // 地址相同

return true;

}

if (obj == null) { // 对象内容为null

return false;

}

if (!(obj instanceof Book)) { // 不是本类实例

return false;

}

Book book = (Book) obj;

if (this.title.equals(book.title) && this.price == book.price) {

return true;

}

return false;

}

public String toString() { // 替代了getInfo(),并且toString()可以自动调用

return "书名:" + this.title + ",价格:" + this.price;

}

// setter、getter、无参构造略

}

public class TestDemo {

public static void main(String args[]) {

Book b1 = new Book("Java开发", 79.9); // 实例化对象

Book b2 = new Book("Java开发", 79.9); // 实例化对象

System.out.println(b1.equals(b2)); // 对象比较

}

}

范例2-73:接收数组数据。

public class TestDemo {

public static void main(String args[]) {

Object obj = new int[] { 1, 2, 3 }; // 向上转型

System.out.println(obj); // 数组编码:[I@1db9722

if (obj instanceof int[]) { // 谁否是int数组

int data[] = (int[]) obj; // 向下转型

for (int x = 0; x < data.length; x++) {

System.out.print(data[x] + "、");

}

}

}

}

范例2-72:Object类接收接口对象。

interface A {

public void fun();

}

class B extends Object implements A { // 所有类一定继承Object类,所以此处只是强调说明

public void fun() {

System.out.println("更多课程请访问:www.yootk.com");

}

public String toString() {

return "魔乐科技:www.mldn.cn" ;

}

}

public class TestDemo {

public static void main(String args[]) {

A a = new B(); // 实例化接口对象

Object obj = a; // 接收接口对象

A t = (A) obj; // 向下转型

t.fun(); // 调用接口方法

System.out.println(t); // 直接调用toString()输出

}

}

范例2-75:修改可用链表。

class Link { // 链表类,外部能够看见的只有这一个类

private class Node { // 定义的内部节点类

private Object data; // 要保存的数据

private Node next; // 下一个节点引用

public Node(Object data) { // 每一个Node类对象都必须保存相应的数据

this.data = data;

}

/**

 * 设置新节点的保存,所有的新节点保存在最后一个节点之后

 * @param newNode 新节点对象

 */

public void addNode(Node newNode) {

if (this.next == null) { // 当前的下一个节点为null

this.next = newNode ; // 保存节点

} else { // 向后继续保存

this.next.addNode(newNode) ;

}

}

/**

 * 数据检索操作,判断指定数据是否存在

 * 第一次调用(Link):this = Link.root

 * 第二次调用(Node):this = Link.root.next

 * @param data 要查询的数据

 * @return 如果数据存在返回true,否则返回false

 */

public boolean containsNode(Object data) {

if (data.equals(this.data)) { // 当前节点数据为要查询的数据

return true; // 后面不再查询了

} else { // 当前节点数据不满足查询要求

if (this.next != null) { // 有后续节点

return this.next.containsNode(data); // 递归调用继续查询

} else { // 没有后续节点

return false; // 没有查询到,返回false

}

}

}

/**

 * 根据索引取出数据,此时该索引一定是存在的

 * @param index 要取得数据的索引编号

 * @return 返回指定索引节点包含的数据

 */

public Object getNode(int index) {

// 使用当前的foot内容与要查询的索引进行比较,随后将foot的内容自增,目的是下次查询方便

if (Link.this.foot++ == index) { // 当前为要查询的索引

return this.data; // 返回当前节点数据

} else { // 继续向后查询

return this.next.getNode(index); // 进行下一个节点的判断

}

}

/**

 * 修改指定索引节点包含的数据

 * @param index 要修改的索引编号

 * @param data 新数据

 */

public void setNode(int index, Object data) {

// 使用当前的foot内容与要查询的索引进行比较,随后将foot的内容自增,目的是下次查询方便

if (Link.this.foot++ == index) { // 当前为要修改的索引

this.data = data; // 进行内容的修改

} else {

this.next.setNode(index, data); // 继续下一个节点的索引判断

}

}

/**

 * 节点的删除操作,匹配每一个节点的数据,如果当前节点数据符合删除数据

 * 则使用“当前节点上一节点.next = 当前节点.next”方式空出当前节点

 * 第一次调用(Link),previous = Link.root、this = Link.root.next

 * 第二次调用(Node),previous = Link.root.next、this = Link.root.next.next

 * @param previous 当前节点的上一个节点

 * @param data 要删除的数据

 */

public void removeNode(Node previous, Object data) {

if (data.equals(this.data)) { // 当前节点为要删除节点

previous.next = this.next; // 空出当前节点

} else { // 应该向后继续查询

this.next.removeNode(this, data); // 继续下一个判断

}

}

/**

 * 将节点中保存的内容转化为对象数组

 * 第一次调用(Link):this = Link.root;

 * 第二次调用(Node):this = Link.root.next;

 */

public void toArrayNode() {

Link.this.retArray[Link.this.foot++] = this.data; // 取出数据并保存在数组中

if (this.next != null) { // 有后续元素

this.next.toArrayNode(); // 继续下一个数据的取得

}

}

}

// ===================== 以上为内部类 ===================

private Node root; // 根节点定义

private int count = 0 ; // 保存元素的个数

private int foot = 0 ; // 节点索引

private Object [] retArray ; // 返回的数组

/**

 * 用户向链表增加新的数据,在增加时要将数据封装为Node类,这样才可以匹配节点顺序

 * @param data 要保存的数据

 */

public void add(Object data) { // 假设不允许有null

if (data == null) { // 判断数据是否为空

return; // 结束方法调用

}

Node newNode = new Node(data); // 要保存的数据

if (this.root == null) { // 当前没有根节点

this.root = newNode; // 保存根节点

} else { // 根节点存在

this.root.addNode(newNode); // 交给Node类处理节点的保存

}

this.count ++ ; // 数据保存成功后保存个数加一

}

/**

 * 取得链表中保存的数据个数

 * @return 保存的个数,通过count属性取得

 */

public int size() { // 取得保存的数据量

return this.count;

}

/**

 * 判断是否是空链表,表示长度为0,不是null

 * @return 如果链表中没有保存任何数据则返回true,否则返回false

 */

public boolean isEmpty() {

return this.count == 0;

}

/**

 * 数据查询操作,判断指定数据是否存在,如果链表没有数据直接返回false

 * @param data 要判断的数据

 * @return 数据存在返回true,否则返回false

 */

public boolean contains(Object data) {

if (data == null || this.root == null) { // 现在没有要查询的数据,根节点也不保存数据

return false ; // 没有查询结果

}

return this.root.containsNode(data) ; // 交由Node类查询

}

/**

 * 根据索引取得保存的节点数据

 * @param index 索引数据

 * @return 如果要取得的索引内容不存在或者大于保存个数,返回null,反之返回数据

 */

public Object get(int index) {

if (index > this.count) { // 超过了查询范围

return null ; // 没有数据

}

this.foot = 0 ; // 表示从前向后查询

return this.root.getNode(index) ; // 查询过程交给Node类

}

/**

 * 根据索引修改数据

 * @param index 要修改数据的索引编号

 * @param data 新的数据内容

 */

public void set(int index, Object data) {

if (index > this.count) { // 判断是否超过了保存范围

return; // 结束方法调用

}

this.foot = 0; // 重新设置foot属性的内容,作为索引出现

this.root.setNode(index, data); // 交给Node类设置数据内容

}

/**

 * 链表数据的删除操作,在删除前要先使用contains()判断链表中是否存在指定数据

 * 如果要删除的数据存在,则首先判断根节点的数据是否为要删除数据

 * 如果是,则将根节点的下一个节点作为新的根节点

 * 如果要删除的数据不是根节点数据,则将删除操作交由Node类的removeNode()方法完成

 * @param data 要删除的数据

 */

public void remove(Object data) {

if (this.contains(data)) { // 主要功能是判断数据是否存在

// 要删除数据是否是根节点数据,root是Node类的对象,此处直接访问内部类的私有操作

if (data.equals(this.root.data)) { // 根节点数据为要删除数据

this.root = this.root.next; // 空出当前根节点

} else { // 根节点数据不是要删除数据

// 此时根元素已经判断过了,从第二个元素开始判断,即第二个元素的上一个元素为根节点

this.root.next.removeNode(this.root, data);

}

this.count--; // 删除成功后个数要减少

}

}

/**

 * 将链表中的数据转换为对象数组输出

 * @return 如果链表没有数据,返回null,如果有数据,则将数据变为对象数组后返回

 */

public Object[] toArray() {

if (this.root == null) { // 判断链表是否有数据

return null; // 没有数据,返回null

}

this.foot = 0; // 脚标清零操作

this.retArray = new Object[this.count]; // 根据保存内容开辟数组

this.root.toArrayNode(); // 交给Node类处理

return this.retArray; // 返回数组对象

}

/**

 * 清空链表数据

 */

public void clear() {

this.root = null; // 清空链表

this.count = 0; // 元素个数为0

}

}

范例2-76:测试新链表—利用String类型完成。

public class LinkDemo {

public static void main(String args[]) {

Link all = new Link() ; // 实例化链表对象

all.add("A") ; // String转为Object

all.add("B") ; // String转为Object

all.add("C") ; // String转为Object

all.remove("A") ; // String覆写了equals()

Object data [] = all.toArray() ; // 将链表转化为对象数组

for (int x = 0 ; x < data.length ; x ++) {

String str = (String) data[x] ; // Object变为String

System.out.print(str + "、") ;

}

}

}

2.9  综合练习:宠物商店

范例2-77:定义出宠物的标准。

interface Pet {  // 定义一个宠物的标准

/**

 * 取得宠物的名字

 * @return 宠物名字信息

 */

public String getName();

/**

 * 取得宠物的年龄

 * @return 宠物年龄信息

 */

public int getAge();

}

范例2-78:定义宠物商店。

class PetShop { // 一个宠物商店要保存有多个宠物信息

private Link pets = new Link(); // 保存的宠物信息

/**

 * 新的宠物类型上架操作,向链表中保存宠物信息

 * @param pet 要上架的宠物信息

 */

public void add(Pet pet) {

this.pets.add(pet); // 向链表中保存数据

}

/**

 * 宠物下架操作,通过链表删除保存的信息,需要对象比较equals()方法的支持

 * @param pet 要删除的宠物信息

 */

public void delete(Pet pet) {

this.pets.remove(pet); // 从链表中删除宠物信息

}

// 模糊查询一定是返回多个内容,不知道多少个,返回Link即可

/**

 * 宠物数据的模糊查询,首先要取得全部保存的宠物信息

 * 然后采用循环的方式依次取出每一种宠物信息,并且对名称进行判断

 * @param keyWord 模糊查询关键字

 * @return 宠物信息通过Link类型返回,如果有指定查询关键字的宠物信息则通过Link集合返回,否则返回null

 */

public Link search(String keyWord) {

Link result = new Link(); // 保存结果

// 将集合变为对象数组的形式返回,因为集合保存的是Object

// 但是真正要查询的数据在Pet接口对象的getName()方法的返回值

Object obj[] = this.pets.toArray();

for (int x = 0; x < obj.length; x++) {

Pet p = (Pet) obj[x]; // 向下转型找到具体的宠物对象

if (p.getName().contains(keyWord)) { // 查询到了

result.add(p); // 保存满足条件的结果

}

}

return result;

}

}

范例2-79:定义宠物猫子类。

class Cat implements Pet { // 如果不实现接口无法保存宠物信息

private String name;

private int age;

public Cat(String name, int age) {

 this.name = name;

 this.age = age;

}

public boolean equals(Object obj) {

 if (this == obj) {

return true;

 }

 if (obj == null) {

return false;

}

 if (!(obj instanceof Cat)) {

return false;

 }

 Cat c = (Cat) obj;

 if (this.name.equals(c.name) && this.age == c.age) {

return true;

}

 return false;

}

public String getName() { // 覆写接口中的方法

 return this.name;

}

public int getAge() { // 覆写接口中的方法

 return this.age;

}

public String toString() {

 return "猫的名字:" + this.name + ",年龄:" + this.age;

}

// 其余的setter、getter、无参构造略

}

范例2-80:定义宠物狗子类。

class Dog implements Pet {  // 如果不实现接口无法保存宠物信息

private String name;

private int age;

public Dog(String name, int age) {

 this.name = name;

 this.age = age;

}

public boolean equals(Object obj) {

 if (this == obj) {

   return true;

 }

 if (obj == null) {

   return false;

 }

 if (!(obj instanceof Cat)) {

   return false;

 }

 Dog c = (Dog) obj;

 if (this.name.equals(c.name) && this.age == c.age) {

   return true;

 }

 return false;

}

public String getName() { // 覆写接口中的方法

 return this.name;

}

public int getAge() { // 覆写接口中的方法

 return this.age;

}

public String toString() {

 return "狗的名字:" + this.name + ",年龄:" + this.age;

}

// 其余的setter、getter、无参构造略

}

范例2-81:编写测试类。

public class TestDemo {

public static void main(String args[]) {

 PetShop shop = new PetShop() ; // 实例化宠物商店

 shop.add(new Cat("波斯猫",1)) ; // 增加宠物

 shop.add(new Cat("暹罗猫",2)) ; // 增加宠物

 shop.add(new Cat("波米拉猫",1)) ; // 增加宠物

 shop.add(new Dog("松狮",1)) ; // 增加宠物

 shop.add(new Dog("波尔多",2)) ; // 增加宠物

 shop.delete(new Cat("波米拉猫",9)) ; // 删除宠物信息

 Link all = shop.search("波") ; // 关键字检索

 Object obj [] = all.toArray() ; // 将结果转换为对象数组输出

 for (int x = 0 ; x < obj.length ; x ++) {

System.out.println(obj[x]) ;

 }

}

}

2.10  匿名内部类

范例2-82:分析匿名内部类的产生动机。

interface Message { // 定义接口

public void print();

}

class MessageImpl implements Message { // 定义实现子类

public void print() {

System.out.println("Hello World !");

}

}

public class TestDemo {

public static void main(String args[]) {

fun(new MessageImpl()); // 传递子类实例化对象

}

public static void fun(Message msg) { // 接收接口对象

msg.print();

}

}

范例2-83:采用匿名内部类简化类的定义。

interface Message { // 定义接口

public void print();

}

public class TestDemo {

public static void main(String args[]) {

fun(new Message() { // 直接实例化接口对象

public void print() { // 匿名内部类中覆写print()方法

System.out.println("Hello World !");

}

}); // 传递匿名内部类实例化

}

public static void fun(Message msg) { // 接收接口对象

msg.print();

}

}

2.11  基本数据类型的包装类

范例2-82:包装类雏形。

class MyInt { // 基本数据类型包装类

private int num; // 这个类包装的是基本数据类型

/**

 * 包装类是为了基本数据类型准备的,所以构造方法中需要明确接收一个数字

 * @param num

 */

public MyInt(int num) { // 将基本类型包装类

this.num = num;

}

/**

 * 通过包装类取得所包装的基本数据类型

 * @return 保证的数据

 */

public int intValue() { // 将包装的数据内容返回

return this.num;

}

}

public class TestDemo {

public static void main(String args[]) {

MyInt mi = new MyInt(10); // 将int包装为类

int temp = mi.intValue(); // 将对象中包装的数据取出

System.out.println(temp * 2); // 只有取出包装数据后才可以进行计算

}

}

范例2-85:使用int和Integer。

public class TestDemo {

public static void main(String args[]) {

Integer obj = new Integer(10); // 将基本数据类型装箱

int temp = obj.intValue(); // 将基本数据类型拆箱

System.out.println(temp * 2); // 数学计算

}

}

范例2-86:使用double和Double。

public class TestDemo {

public static void main(String args[]) {

Double obj = new Double(10.2); // 将基本数据类型装箱

double temp = obj.doubleValue(); // 将基本数据类型拆箱

System.out.println(temp * 2); // 数学计算

}

}

范例2-87:使用boolean和Boolean(不是Number子类)。

public class TestDemo {

public static void main(String args[]) {

Boolean obj = new Boolean(true); // 将基本数据类型装箱

boolean temp = obj.booleanValue(); // 将基本数据类型拆箱

System.out.println(temp);

}

}

范例2-88:观察自动装箱与自动拆箱。

public class TestDemo {

public static void main(String args[]) {

Integer obj = 10; // 自动装箱

int temp = obj; // 自动拆箱

obj++; // 包装类直接进行数学计算

System.out.println(temp * obj); // 包装类直接进行数学计算

}

}

范例2-89:观察Integer的实例化操作问题。

public class TestDemo {

public static void main(String args[]) {

Integer obja = 10; // 直接装箱实例化

Integer objb = 10; // 直接装箱实例化

Integer objc = new Integer(10); // 构造方法实例化

System.out.println(obja == objb); // 比较结果:true

System.out.println(obja == objc); // 比较结果:false

System.out.println(objb == objc); // 比较结果:false

System.out.println(obja.equals(objc)); // 比较结果:true

}

}

范例2-90:利用Object接收基本数据类型。

public class TestDemo {

public static void main(String args[]) {

Object obj = 10; // 先自动装箱后再向上转型,此时不能进行数学计算

// Object不可能直接向下转型为int

// 所以要取出基本数据类型必须首先向下转型为指定的包装类

int temp = (Integer) obj; // 向下变为Integer后自动拆箱

System.out.println(temp * 2);

}

}

范例2-91:观察double类型的自动装箱与拆箱操作。

public class TestDemo {

public static void main(String args[]) {

Double obj = 10.2; // 自动装箱

System.out.println(obj * 2); // 直接进行数学计算

}

}

范例2-92:观察Boolean类型的自动装箱与拆箱操作。

public class TestDemo {

public static void main(String args[]) {

Boolean flag = true; // 自动装箱

if (flag) { // 直接判断

System.out.println("Hello World !");

}

}

}

范例2-93:将字符串变为int型数据。

public class TestDemo {

public static void main(String args[]) {

String str = "123"; // 字符串,由数字组成

int temp = Integer.parseInt(str); // 将字符串转化为int型数据

System.out.println(temp * 2); // 数学计算

}

}

范例2-92:错误的转换操作。

public class TestDemo {

public static void main(String args[]) {

String str = "1a3"; // 字符串

int temp = Integer.parseInt(str); // 将字符串转化为int型数据

System.out.println(temp * 2); // 数学计算

}

}

范例2-95:观察double转换。

public class TestDemo {

public static void main(String args[]) {

String str = "1.3"; // 字符串

double temp = Double.parseDouble(str); // 将字符串转化为double型数据

System.out.println(temp * 2); // 数学计算

}

}

范例2-96:观察boolean转换。

public class TestDemo {

public static void main(String args[]) {

String str = "true"; // 字符串

boolean flag = Boolean.parseBoolean(str); // 将字符串转化为boolean型

if (flag) {

System.out.println("** 满足条件!");

} else {

System.out.println("** 不满足条件!");

}

}

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值