Java SE 09_Generics

来源:互联网 发布:mac php集成开发环境 编辑:程序博客网 时间:2024/05/17 06:29

Java SE 9th day

1、本次课程知识点

1、泛型的作用

2、泛型的基本使用

2、具体内容

2.1 泛型的产生

要求设计一个可以表示坐标的类,(X、Y)

但是此坐标可以同时满足以下几种要求:

● x = 10、y = 100

● x = 10.3、y = 50.2

● x = “东经180度”、y = “北纬210度”

问,这样的坐标类该如何设计?

分析:

因为现在的程序中可以接收三种数据类型的数据,所以为了保证程序的正确性,最好使用Object完成,因为Object可以接收任意的引用数据类型:

现在有三种类型的数据:int、float、String,回想自动装箱的操作

● int → Integer → Object

● float → Float → Object

按照以上特点,完成程序:

package org.util;

 

public class Point { // 表示坐标

    private Object x;

    private Object y;

 

    public Object getX() {

       return x;

    }

 

    public void setX(Object x) {

       this.x = x;

    }

 

    public Object getY() {

       return y;

    }

 

    public void setY(Object y) {

       this.y = y;

    }

}

此时,Point类完成了。

此时,设置一个整形数字,那么来观察是否可以操作:

package org.util;

 

public class Math {

    public static void main(String args[]) {

       Point p = new Point();

       p.setX(11); // int IntegerObject

       p.setY(20); // int IntegerObject

       int x = (Integer) p.getX();// 取出x坐标

       int y = (Integer) p.getY();// 取出y坐标

       System.out.println("x的坐标是:" + x);

       System.out.println("y的坐标是:" + y);

    }

}

x的坐标是:11

y的坐标是:20

此时,达到了设置整数的目的,那么下面继续完成设置小数的操作。

package org.util;

 

public class Math {

    public static void main(String args[]) {

       Point p = new Point();

       p.setX(11.3f);

       p.setY(20.3f);

       float x = (Float) p.getX();// 取出x坐标

       float y = (Float) p.getY();// 取出y坐标

       System.out.println("x的坐标是:" + x);

       System.out.println("y的坐标是:" + y);

    }

}

x的坐标是:11.3

y的坐标是:20.3

下面继续设置字符串作为x和y的坐标

public class Math02 {

    public static void main(String args[]) {

       Point p = new Point();

       p.setX("东经180度");

       p.setY("北纬220度");

       String x = (String) p.getX(); // 取出x坐标

       String y = (String) p.getY(); // 取出y坐标

       System.out.println("x的坐标是:" + x);

       System.out.println("y的坐标是:" + y);

    }

}

x的坐标是:东经180度

y的坐标是:北纬220度

此时,基本的功能已经实现了,但是此种操作是否存在问题呢?

在此操作之中,可以发现所有的内容都是以Object进行操作的,那么就意味着,可以设置任意的类型,即:X可以是整形,Y可以是字符串。

package org.util;

 

public class Math03 {

    public static void main(String args[]) {

       Point p = new Point();

       p.setX(11);

       p.setY("北纬220度");

       int x = (Integer) p.getX();// 取出x坐标

       int y = (Integer) p.getY();// 取出y坐标

       System.out.println("x的坐标是:" + x);

       System.out.println("y的坐标是:" + y);

    }

}

此时程序在编译的时候没有任何的问题,但是在执行的时候出现了以下的错误提示:

Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer

    at org.util.Math03.main(Math03.java:9)

之所以会这样,因为在程序中的所有的属性都可以向Object进行转换,那么此时程序的入口就显得不那么规范了,而且存在安全的漏洞。

但是,从之前所学习过的全部代码来讲,此处只能应用到这里了,没有更好的方法了。

2.2 JDK 1.5新特性 —— 泛型

JDK 1.5之后出现了新的技术 —— 泛型,此技术的最大特点是在类中的属性的类型可以由外部决定。

泛型类定义格式:

[访问权限] class类名称<泛型类型1,泛型类型2,……泛型类型n>{

       [访问权限] 泛型类型标识 变量名称;

       [访问权限] 泛型类型标识 方法名称(){}

       [访问权限] 返回值类型声明 方法名称(泛型类型标识 变量名称){}

}

泛型对象定义:

类名称<具体类>对象名称 = new 类名称<具体类>();

注意:在泛型的指定中是无法指定基本数据类型的,必须设置成一个类,这样在设置一个数字的时候就必须使用包装类。

那么使用如上的操作格式来修改之前的操作类。

package genericsdemo;

 

public class Point<T> { // 表示坐标

    private T x;

    private T y;

 

    public T getX() {

       return x;

    }

 

    public void setX(T x) {

       this.x = x;

    }

 

    public T getY() {

       return y;

    }

 

    public void setY(T y) {

       this.y = y;

    }

}

此时,程序中加入泛型操作之后,可以发现一切的操作类型此时都不再由程序固定设置,而是由实例化对象的时候在外部进行了指定。

package genericsdemo;

 

public class Math {

    public static void main(String args[]) {

       Point<Integer> p = new Point<Integer>();

       p.setX(11);

       p.setY(20);

       float x = p.getX();// 取出x坐标

       float y = p.getY();// 取出y坐标

       System.out.println("x的坐标是:" + x);

       System.out.println("y的坐标是:" + y);

    }

}

x的坐标是:11.0

y的坐标是:20.0

发现此时在使用Point类的时候,需要加入一个属性类型的声明,而且加入之后再取出属性的时候本身也变得非常容易,不用再使用向下转型了。

而且,使用上面的操作有一点最方便之处,如果此时设置的内容不是整形,那么程序中将出现错误。

package genericsdemo;

 

public class Math {

    public static void main(String args[]) {

       Point<Integer> p = new Point<Integer>();

       p.setX(11);

        p.setY("北纬220度");// 错误,不能设置String类型

       float x = p.getX();// 取出x坐标

       float y = p.getY();// 取出y坐标

       System.out.println("x的坐标是:" + x);

       System.out.println("y的坐标是:" + y);

    }

}

加入泛型之后,可以对程序的操作起到更加安全的目的。

2.3 泛型的其他注意点

在使用泛型操作的时候,实际上有很多小的注意点,例如:构造方法上依然可以使用泛型或者有一种称为泛型的擦除。

2.3.1 在构造方法上应用泛型

一般开发中,经常使用构造方法设置属性的内容。那么此时实际上构造方法上依然可以使用泛型的类型。

格式:

[访问权限] 构造方法 ( [<泛型类型参数名称>] ){}

范例:

package genericsdemo;

 

public class Point<T> { // 表示坐标

    private T x;

    private T y;

 

    public Point(T x, T y) {

       this.setX(x);

       this.setY(y);

    }

 

    public T getX() {

       return x;

    }

 

    public void setX(T x) {

       this.x = x;

    }

 

    public T getY() {

       return y;

    }

 

    public void setY(T y) {

       this.y = y;

    }

}

那么此时在调用的时候就需要使用构造方法设置内容,当然,设置的内容本身依然由泛型指定。

package genericsdemo;

 

public class Math {

    public static void main(String args[]) {

       Point<Integer> p = new Point<Integer>(10, 20);

       int x = p.getX(); // 取出x坐标

       int y = p.getY(); // 取出y坐标

       System.out.println("x的坐标是:" + x);

       System.out.println("y的坐标是:" + y);

    }

}

x的坐标是:10

y的坐标是:20

2.3.2 擦除泛型

如果在使用的时候没有指定泛型的话,则表示擦除泛型。

泛型一旦擦除后,将按照Object进行接收,以保证程序不出现任何错误。

package genericsdemo;

 

public class Math {

    public static void main(String args[]) {

       Point p = new Point(10, 20);

       int x = (Integer) p.getX(); // 取出x坐标

       int y = (Integer) p.getY(); // 取出y坐标

       System.out.println("x的坐标是:" + x);

       System.out.println("y的坐标是:" + y);

    }

}

但是在以上的操作代码中依然会存在警告信息,那么该如何去掉警告信息呢?

package genericsdemo;

 

public class Math {

    public static void main(String args[]) {

       Point<Object> p = new Point<Object>(10, 20);

       int x = (Integer) p.getX();// 取出x坐标

       int y = (Integer) p.getY();// 取出y坐标

       System.out.println("x的坐标是:" + x);

       System.out.println("y的坐标是:" + y);

    }

}

但是,以上的操作虽然去掉了警告信息,但是没有意义。

不指定泛型流程图:

2.4 通配符

在泛型中通配符使用较多,而且在日后的系统类库中有很多的地方都要使用这些操作

例如:现在有如下的操作代码

package genericsdemo03;

public class Test {

    public static void main(String[] args) {

       Object obj = "Hello";

    }

}

以上的语法实际上是表示进行了向上的转型操作,因为String是Object的子类,但是现在在泛型中却没有此概念。

2.4.1 ?

在进行对象转换的时候可以使用自动的向上转型,但是在使用泛型的时候却没有此种操作。

package genericsdemo03;

public class Point<T> { // 表示坐标

    private T x;

    private T y;

 

    public T getX() {

       return x;

    }

    public void setX(T x) {

       this.x = x;

    }

 

    public T getY() {

       return y;

    }

    public void setY(T y) {

       this.y = y;

    }

}

那么下面定义两个Point类的对象。

package genericsdemo03;

 

public class Math {

    public static void main(String args[]) {

       Point<Object> p1 = new Point<Object>();

       Point<Integer> p2 = new Point<Integer>();

       p1 = p2; //此时无法转型

    }

}

D:\javatest>javac Math.java

Math.java:28: 错误: 不兼容的类型

                p1 = p2; // 此时无法转型

                     ^

  需要: Point<Object>

  找到:    Point<Integer>

1 个错误

此时的程序发现,根本就无法进行转换操作。

引用传递时同样存在以上无法转换问题,如下,对主方法进行修改。

范例:泛型类中使用引用传递

public class Math {

    public static void main(String args[]) {

        Point<Integer> p = new Point<Integer>();

        fun(p);

    }

 

    public static void fun(Point<Object> temp) {//如果去掉<Object>则程序可正常运行

        System.out.println("内容:" + temp);

    }

}

D:\javatest>javac Math.java

Math.java:27: 错误: 无法将类 Math中的方法 fun应用到给定类型;

                fun(p);

                ^

  需要: Point<Object>

  找到: Point<Integer>

  原因: 无法通过方法调用转换将实际参数Point<Integer>转换为Point<Object>

1 个错误

此时的程序实际上已经不完全属于对象的转型操作了,属于一个大的类型和小的类型的划分。

例如:将“Point<Object> p1 = new Point<Object>();”表示为整个商场的全部商品,而“Point<Integer> p2 =new Point<Integer>();”表示每一个顾客购买的商品。如果现在执行“p1 = p2;”那么就意味着,本顾客所购买的商品就是商场中的全部商品。这样肯定说不通,所以不能接收。

不能使用以上的方式接收最大的影响在于方法的参数接收上。

package genericsdemo03;

public class Math {

    public static void main(String args[]) {

       Point<Object> p1 = new Point<Object>();

       Point<Integer> p2 = new Point<Integer>();

       fun(p1);

       fun(p2);

    }

 

    public static void fun(Point<?> po) {// 表示此时可以接收任意的类型

       System.out.println(po.getX());

       System.out.println(po.getY());

    }

}

null

null

null

null

程序中的“?”表示可以接收任意的泛型类型,但是只是接收输出,并不能修改。

2.4.2 泛型上限

上限就指一个的操作泛型最大的操作父类,例如,现在最大的上限设置成“Number”类型,那么此时,所能够接收到的类型只能是Number及其子类(如Integer)。

泛型上限设置格式:

声明对象:

类名称< extends>对象名称

定义类:

[访问权限]类名称<泛型标识 extends>{}

范例:在Point类中只能设置数字的坐标

package genericsdemo03;

public class Point<T extends Number> {// 表示坐标,最高只能是Number

    private T x;

    private T y;

 

    public T getX() {

       return x;

    }

 

    public void setX(T x) {

       this.x = x;

    }

 

    public T getY() {

       return y;

    }

 

    public void setY(T y) {

       this.y = y;

    }

}

以上的泛型类型明确的指出,最大的操作父类是Number,能设置的内容只能是其子类Integer、Float等等。

package genericsdemo03;

public class Math {

    public static void main(String args[]) {

       Point<Integer> p1 = new Point<Integer>();// 设置的是Number的子类

    }

}

如果此时设置了泛型是字符串的话,则会出现错误。

而且,使用泛型的上限也可以在方法上使用,例如:接收参数。

范例:传递中声明对象

class Point<T> {// 此处不设置上限,由方法设置

……

}

 

public class Math {

    public static void main(String args[]) {

       Point<Integer> p2 = new Point<Integer>();

       fun(p2);

    }

 

    public static void fun(Point<?extends Number> po) {// 表示此时可以接收Number的子类

       System.out.println(po.getX());

       System.out.println(po.getY());

    }

}

null

null

当然,也可以用于直接声明对象:

class Point<T> {// 此处不设置上限,由方法设置

……

}

 

public class Math {

    public static void main(String args[]) {

       Point<? extends Number>p = null;

       p = new Point<Integer>();

    }

}

2.4.3 泛型下限

泛型下限指的是只能设置其具体的类或者父类。

泛型下限设置格式:

声明对象:

类名称< super>对象名称

定义类:

[访问权限]类名称<泛型标识 extends>{}

注意:以上的定义类存在问题,待考究!!!

范例:定义一个方法,此方法只能接收String或Object类型的泛型对象。

package genericsdemo03;

public class Point<T> {

    private T x;

    private T y;

 

    public T getX() {

       return x;

    }

 

    public void setX(T x) {

       this.x = x;

    }

 

    public T getY() {

       return y;

    }

 

    public void setY(T y) {

       this.y = y;

    }

}

在方法中设置泛型的下限:

package genericsdemo03;

public class Math {

    public static void main(String args[]) {

       Point<String> p1 = new Point<String>();

       Point<Object> p2 = new Point<Object>();

       fun(p1);

       fun(p2);

    }

    public static void fun(Point<?super String> po) {

       System.out.println(po.getX());

       System.out.println(po.getY());

    }

}

2.5 泛型接口

泛型不光可以在类上使用,还可以在接口中进行定义。操作的语法如下:

Interface 接口名称<泛型类型,泛型类型,……>()

范例:定义泛型接口

package genericsdemo04;

 

public interface Demo<T> { // 定义泛型接口

    public void print(T param); // 此抽象方法中使用了泛型类型

}

泛型接口定义完成之后,下面就需要定义子类实现此接口,实现的方法有两种。

范例:第一种实现手段(在子类的定义上声明泛型类型)

package genericsdemo04;

 

public class DemoImp<T> implements Demo<T> {

    public void print(T param) {

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

    }

}

下面对以上的程序进行测试:

package genericsdemo04;

 

public class Test {

    public static void main(String args[]) {

       Demo<String> demo = new DemoImp<String>();

       demo.print("hello");

    }

}

param = hello

范例:第二种实现手段(直接在接口中指定具体类型)

package genericsdemo04;

public class DemoImp2 implements Demo<DemoImp2> {

    public void print(DemoImp2 param) {

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

    }

}

此时print()方法中只能接收DemoImp2对象实例。

package genericsdemo04;

public class Test {

    public static void main(String args[]) {

       Demo demo = new DemoImp2();

       demo.print(new DemoImp2());

    }

}

param = genericsdemo04.DemoImp2@1ff61bcf

2.6 泛型方法

泛型除了在类中定义之外,还可以在方法上定义,而且在方法上使用泛型,此方法所在的类不一定是泛型的操作类。

泛型方法的简单定义:

[访问权限] <泛型标识>泛型标识 方法名称([泛型标识 参数名称])

范例:定义一个泛型方法

package genericsdemo05;

public class Demo {

    public <T> T print(T param) { // 定义泛型方法

       return param;

    }

}

Demo类中的print()方法里面接收泛型的类型,而且此方法的返回值也是指定的泛型类型。下面使用以上的类型操作。

package genericsdemo05;

public class Test {

    public static void main(String[] args) {

       Demo d = new Demo();

       System.out.println(d.print(1));// 如果输入1表示类型是Integer

    }

}

1

当然,也可以将此方法的返回值定义成一个泛型的数组。

范例:泛型数组的应用(重要

publicclass Math {

    public static void main(String args[]) {

       Integer i[] = fun(1, 2, 3, 4, 5);//注意此处同样不能使用基本数据类型,如int

       String j[] = { "A", "B", "C", "D" };

       Object k[] = fun(1, 0.1, 'a', "Hello", true);// 接收各种数据类型

       print(i);

       print(fun(j));

       print(fun(k));

       System.out.println("主方法输出:");

       for (Integer t : i) {// 此处可以为比i大的操作父类,如Number、Object

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

       }

       System.out.println();

       for (String t : j) {// 此处可该为Object

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

       }

       System.out.println();

       for (Object t : k) {// 此处只能是Object

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

       }

    }

 

    public static <T> T[] fun(T... param) {// 接收可变数组,此处不能写出

                                       //(Tparam[]),否则不能接收数组i和k

       return param;

    }

 

    public static <T> void print(T param[]) {// 此处也可以写成(T...param)

       for (T x : param) {// 注意与主方法输出做比较,此处只能为T

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

       }

       System.out.println();

    }

}

1、2、3、4、5、

A、B、C、D、

1、0.1、a、Hello、true、

主方法输出:

1、2、3、4、5、

A、B、C、D、

1、0.1、a、Hello、true、

2.7 泛型的嵌套的设置

现在只是突出语法,具体的操作意义需要等待后面的类库之中才能够更加明白。

package genericsdemo06;

public class Info<T> {

    private T param;

 

    public T getParam() {

       return param;

    }

 

    public void setParam(T param) {

       this.param = param;

    }

}

之后定义一个Person类型。

package genericsdemo06;

public class Person<T> {

    private T info;

 

    public T getInfo() {

       return info;

    }

 

    public void setInfo(T info) {

       this.info = info;

    }

}

此时如果要将Info的类型设置到Person之中,那么同时即要指定Person的泛型类型,又要指定Info中的泛型类型。

package genericsdemo06;

public class Test {

    public static void main(String[] args) {

       Person<Info<String>> per = new Person<Info<String>>();

       per.setInfo(new Info<String>());

       per.getInfo().setParam("MLDN.java");

       System.out.println(per.getInfo().getParam());

    }

}

MLDN.java

以上的操作在后面将会有所应用。

2.8 泛型的操作范例

现在有如下的题目要求:

要求设计一个程序,定义一个Person类,Person类中要存放具体的信息,但是信息分为基本信息或联系方式等等,那么此时该如何设计呢?

此时最好的设计是需要定义一个表示信息的操作标准。但是此时这个标准肯定使用接口实现,但是现在在接口并不编写任何的操作。

范例:定义标识接口——信息

package genericsdemo07;

public interface Info {

}

接口没有任何的操作代码,所以,此种接口在设计上称为标识接口,表示一种能力。

之后定义Person类,Person类中的信息只能由Info的子类决定,所以此时指定了上限。

范例:定义Person类

package genericsdemo07;

class Person<T extends Info> {// 此处指定了上限,必须是Info接口的子类

    private T info; // 此变量的类型由外部决定

 

    public Person() {

 

    }

 

    public Person(T info) {

       setInfo(info);

    }

 

    public T getInfo() {

       return info;

    }

 

    public void setInfo(T info) {

       this.info = info;

    }

 

    public String toString() {// 覆写Object类中的toString()方法

       return this.info.toString();

    }

}

以上的操作中,能设置的内容只能是Info的子类。

范例:定义第一个表示信息的类——个人基本信息,此类实现接口

package genericsdemo07;

public class Basic implements Info {

    private String name;

    private int age;

 

    public Basic() {

       super();

    }

 

    public Basic(String name,int age) {

       super();

       this.name = name;

       this.age = age;

    }

 

    public String getName() {

       return name;

    }

 

    public void setName(String name) {

       this.name = name;

    }

 

    public int getAge() {

       return age;

    }

 

    public void setAge(int age) {

       this.age = age;

    }

 

    public String toString() {

       return "人的信息:\n" +

                "\t|- 姓名:" +this.getName() + "\n" +

                "\t|- 年龄:"+this.getAge();

    }

}

以上只是基本信息,但是在人中还有联系方式的子类。

范例:定义第二个表示信息的类——联系方式,此类实现接口

package genericsdemo07;

public class Contact implements Info {

    private String address;

    private String zipcode;

 

    public Contact() {

       super();

    }

 

    public Contact(String address, String zipcode) {

       super();

       this.address = address;

       this.zipcode = zipcode;

    }

 

    public String getAddress() {

       return address;

    }

 

    public void setAddress(String address) {

       this.address = address;

    }

 

    public String getZipcode() {

       return zipcode;

    }

 

    public void setZipcode(String zipcode) {

       this.zipcode = zipcode;

    }

 

    public String toString(){

       return "地址信息:\n"+

              "\t|- 地址:"+this.getAddress()+ "\n" +

              "\t|- 邮编:"+this.getZipcode();

    }

}

范例:设置测试类

public class Math {

    public static void main(String[] args) {

       // 将Basic类型设置为泛型类型,声明并实例化Person对象

       Person<Basic> per = new Person<Basic>();

       // 实例化Basic匿名对象,并将其对象同serInfo()方法传入Person对象中

       per.setInfo(new Basic("张三", 30));

       // 通过调用Person类中的getInfo()方法取得信息并输出

       System.out.println(per.getInfo());

      

       // 实例化Person对象,同时设置info属性的信息

       Person<Contact> perc = new Person<Contact>(new Contact("高州","525200"));

       // 通过调用toString()方法直接输出

       System.out.println(perc);

    }

}

人的信息:

    |- 姓名:张三

    |- 年龄:30

地址信息:

    |- 地址:高州

    |- 邮编:525200

以上的Person中的信息属性只能是Info的子类,从而保证了操作的正确性。

注意:比较以上两种实例化对象的方法,以及输出方法。

3、总结

1、本章只是阐述了泛型的基本操作及基本语法。

2、可以通过“?”、“? extends 类”、“? super 类”指定泛型的操作界限

3、泛型如果没有设置的话,则将会进行擦除,擦除之后按照Object进行接收

4、泛型可以在接口上设置,指定泛型接口的子类需要明确的给出操作类型

4、作业 —— 宠物商店

实现一个宠物店,一个宠物商店中存在多种宠物。

定义宠物标准:Pet

package org.petshopdemo;

public interface Pet { // 如果有需要则 扩展此处接口即可

    public String getName();// 得到宠物的名字

 

    public int getAge(); // 得到宠物的年龄

 

    public float getPrice(); // 得到宠物的价格

}

宠物标准定义完成之后,下一步最关心的是宠物商店。

一个宠物商店要包含多种宠物。

定义宠物商店:PetShop

package org.petshopdemo;

public class PetShop {

    private Pet pets[]; // 表示有多个宠物

    private int foot; // 定义脚标

 

    public Petshop(int len) {// 宠物的个数可以通过外部指定

        if (len > 0) { // 判断输入的个数长度是否大于0

            this.pets =new Pet[len];

        } else {

            this.pets =new Pet[1];//至少保留一个宠物

        }

    }

 

    public boolean add(Pet pet) {// 增加宠物,返回是否增加成功的信息

        if (this.foot <this.pets.length) {// 可以增加宠物

            this.pets[this.foot] = pet;// 保存宠物

            this.foot++;// 修改脚标

            return true; // 增加成功

        } else {

            return false; // 增加失败

        }

    }

 

    // 因为查询的时候可能返回多个内容,所以还应该以数组的形式表示

    public Pet[] search(String keyWord) {// 根据关键字查询

        Pet[] result = null;//声明数组,但是,大小不指定

        int count = 0; // 记录有多少中宠物符合信息

        for (int i = 0; i <this.pets.length; i++) {

            if (this.pets[i] !=null) { // 表示有宠物信息

                if (this.pets[i].getName().indexOf(keyWord) != -1) {//查询到结果

                    count++; // 修改查询个数

                }

            }

        }

        result = new Pet[count];// 根据查找的个数开辟数组空间

        count = 0;

        for (int i = 0; i <this.pets.length; i++) {

            if (this.pets[i] !=null) { // 表示有宠物信息

                if (this.pets[i].getName().indexOf(keyWord) != -1) {//查询到结果

                    result[count] = this.pets[i];// 返回查询的内容

                    count++; // 修改查询个数

                }

            }

        }

        return result;

    }

}

定义宠物猫:

package org.petshopdemo;

public class Cat implements Pet {

    private String name;

    private int age;

    private float price;

 

    public Cat(String name,int age, float price) {

        super();

        this.name = name;

        this.age = age;

        this.price = price;

    }

 

    public String getName() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

    public int getAge() {

        return age;

    }

 

    public void setAge(int age) {

        this.age = age;

    }

 

    public float getPrice() {

        return price;

    }

 

    public void setPrice(float price) {

        this.price = price;

    }

 

    public String toString() {

        return "宠物猫的名字:" + this.name +",年龄:" + this.age +",价格:" + this.price;

    }

}

定义宠物狗:

package org.petshopdemo;

public class Dog implements Pet {

    private String name;

    private int age;

    private float price;

 

    public Dog(String name,int age, float price) {

        super();

        this.name = name;

        this.age = age;

        this.price = price;

    }

 

    public String getName() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

    public int getAge() {

        return age;

    }

 

    public void setAge(int age) {

        this.age = age;

    }

 

    public float getPrice() {

        return price;

    }

 

    public void setPrice(float price) {

        this.price = price;

    }

 

    public String toString() {

        return "宠物狗的名字:" + this.name +",年龄:" + this.age +",价格:" + this.price;

    }

}

建立测试类,测试类之间的关系。

package org.petshopdemo;

public class TestPetShop {

    public static void main(String[] args) {

       Petshop shop = new Petshop(5);// 定义能存放5个宠物的商店

       shop.add(new Cat("黑猫", 3, 89.4f));// 增加宠物,成功

       shop.add(new Cat("白猫", 2, 19.4f));// 增加宠物,成功

       shop.add(new Cat("花猫", 3, 89.4f));// 增加宠物,成功

       shop.add(new Dog("白狗", 3, 89.4f));// 增加宠物,成功

       shop.add(new Dog("黑狗", 3, 89.4f));// 增加宠物,成功

       shop.add(new Dog("猪狗", 3, 89.4f));// 增加宠物,失败

       Pet p[] = shop.search("白");

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

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

       }

    }

}

实际上从开发中此种模式也是经常使用到的。所以一定要理解其代码的意义,使用接口进行解耦合操作。所有类之间的关联使用接口完成,使程序具有更大的灵活性。

 

0 0
原创粉丝点击