目录
范例2-18:使用private声明父类中的print()方法。
范例2-21:利用static定义的内部抽象类为外部抽象类。
范例2-59:在一个接口内部如果使用static去定义一个内部接口,该接口就表示是一个外部接口。
范例2-70:观察自定义类对象与String类对象直接输出。
范例2-87:使用boolean和Boolean(不是Number子类)。
第一章:面向对象高级知识
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("** 不满足条件!"); } } } |