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 →Integer→Object
p.setY(20); // int →Integer→Object
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]);
}
}
}
实际上从开发中此种模式也是经常使用到的。所以一定要理解其代码的意义,使用接口进行解耦合操作。所有类之间的关联使用接口完成,使程序具有更大的灵活性。
- Java SE 09_Generics
- java se 09
- java SE教程09
- JAVA SE — Day 09
- java se
- Java SE
- java se
- java se
- java se
- JAVA SE
- JAVA SE
- 09 11 29Java SE学习笔记
- 09 12 02 Java SE 学习笔记
- 09 12 02 Java SE 学习笔记
- 09 12 03Java SE学习笔记
- 09 12 07 Java SE学习笔记
- 《Java SE》初学Java
- 【Java SE】认识Java
- 伊拉克
- 第十篇 学习心得
- 548 - Tree
- JavaSE 7th day —— Package &Access Permissions
- Java SE 8th day Eclipse
- Java SE 09_Generics
- 字符串之统计元音
- Java SE 10_Multi-threading
- Java SE 11_Frequently-used Class Library(1)
- Codeforces Round #222 (Div. 2) ABCD
- C++中的'&'和const的使用注意事项!
- Java SE 12_Frequently-used Class Library(2)
- Java SE 13_Regular Expression
- Java SE 14th IO (1)