Java面向对象(二)

第6章:面向对象(高级篇)

1、继承的基本概念

  • 继承的格式:
    class 父类{} //定义父类
    class 子类 extends 父类{} //使用extends关键字实现继承

  • // 继承的实现
    class Person{
    private String name;
    private int 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;
    }
    }
    class Student extends Person{
    //此处什么代码都不写
    }
    public class ExtDemo01 {
    public static void main(String[] args) {
    Student student = new Student();
    student.setName("张三");
    student.setAge(18);
    System.out.println("姓名:" + student.getName() + " 年龄:" + student.getAge());
    }
    }
  • 子类也可以定义自己的属性和方法。

    class Person{
    private String name;
    private int 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;
    }
    }
    class Student extends Person{
    private String school;
    public String getSchool(){
    return this.school;
    }
    public void setSchool(String school){
    this.school = school;
    }
    }
    public class ExtDemo01 {
    public static void main(String[] args) {
    Student student = new Student();
    student.setName("张三");
    student.setAge(18);
    student.setSchool("大连大学");
    System.out.println("姓名:" + student.getName() + "\n" +
    "年龄:" + student.getAge() + "\n" + "学校:" + student.getSchool());
    }
    }
  • 只允许多层继承,而不能多重继承。在java中只允许单继承,不能使用多重继承,即一个子类只能继承一个父类。但是允许多层继承,即一个子类可以有一个父类,一个父类还可以有一个父类。

  • 子类是不能直接访问父类中的私有成员的,子类可以调用父类中的非私有方法,但是不能直接调用父类中的私有成员。

2、继承的进一步研究

  1. 子类对象的实例化过程

    子类对象在实例化之前必须首先调用父类中的构造方法后在调用子类自己的构造方法。

    子类的构造方法中隐含一个super()的语法。

    class Student extends Person{
    private String school;
    public Student(){
    super(); //加与不加此句效果相同。 使用super()调用父类中的构造方法。
    System.out.println("子类Student中的构造。");
    }
    }
  2. 方法的覆写

    方法的覆写指的是子类定义了与父类中同名的方法,覆写时要考虑权限,子类覆写的方法不能拥有比父类方法更加严格的访问权限。

    private < default < public

    class Person01{
    void print(){
    System.out.println("Person--->void print(){}");
    }
    }
    class Student01 extends Person01{
    public void print(){
    System.out.println("Student--->public void print(){}");
    }
    }
    public class OverrideDemo01 {
    public static void main(String[] args) {
    new Student01().print();
    }
    }

    当方法被覆写后,子类对象调用的方法将是被覆写后的方法。

    如果想要在之类的方法中访问父类的方法,则使用super关键字。

    class Person01{
    void print(){
    System.out.println("Person--->void print(){}");
    }
    }
    class Student01 extends Person01{
    public void print(){
    super.print();
    System.out.println("Student--->public void print(){}");
    }
    }
    public class OverrideDemo01 {
    public static void main(String[] args) {
    new Student01().print();
    }
    }
  3. 属性的覆盖

    如果子类和父类声明了相同名称的属性则在之类中直接访问时一定是采用“就近访问原则”,即先找到本类中的属性,如果此时调用父类中的属性,直接使用“super.属性”

    class Person02{
    public String info = "MLDN";
    }
    class Student02 extends Person02{
    public String info = "LXH";
    public void print(){
    System.out.println("父类中的属性:" + super.info);
    System.out.println("子类中的属性:" + info);
    }
    }
    public class OverrideDemo02 {
    public static void main(String[] args) {
    new Student02().print();
    }
    }
  4. 方法的重载与覆写的区别

    区别点 重载 覆写
    单词 Overloading Overriding
    定义 方法名称相同,参数类型或个数不同 方法名称、参数类型、返回值类型全相同
    定义 对权限没有要求 被覆写的方法不能拥有更严格的权限
    范围 发生在一个类中 发生在继承类中

3、super关键字的作用

使用super关键字可以从子类中调用父类中的构造方法、普通方法和属性。使用super调用父类中指定的构造方法的操作,与this调用构造方法的要求一样。语句必须放在子类构造方法的首行。

class Person{
private String name;
private int age;
public Person(String name, int age){
this.setName = name;
this.setAge = 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 getInfo(){
return "姓名:" + this.getName() + "年龄:" + this.getAge();
}
}
class Student extends Person{
private String school;
public Student(String name, int age, String school){
super(name,age);
this.setSchool(school);
}
public String getSchool(){
return school;
}
public void setSchool(String school){
this.school = school;
}
public String getInfo(){
return super.getInfo() + "学校:" + this.getSchool();
}
}
public class SuperDemo01{
public static void main(String args[]){
Student stu = new Student("张三", 30, "大连大学");
System.out.println(stu.getInfo());
}
}

this与super的区别

区别点 this super
属性访问 访问本类中的属性,如果本类中没有此属性,则从父类中继续查找 访问父类中的属性
方法 访问本类中的方法、如果本类中没有此方法,则从父类中继续查找 直接访问父类中的方法
调用构造 调用本类构造,必须放在构造方法的首行 调用父类构造,必须放在子类构造方法的首行
特殊 表示当前对象 无此概念

注意:this和super调用构造方法是不可以同时出现的,因为两者调用构造方法时都必须放在构造方法的首行。无论子类如何操作,最终必须首先调用父类中的构造方法。

4、final关键字

final在Java中表示最终,也可以称为完结器。可以使用final关键字声明类、属性、方法。

  • 使用final声明的类不能有子类。
  • 使用final声明的方法不能被子类所覆盖。
  • 使用final声明的变量即为常量,常量不可以修改。

使用final声明变量时,要求全部字母大写

class A{
private final String INFO = "hello world!";
}

全局常量
如果一个变量使用 public static final 声明,则此变量称为全局常量。

class A{
public static final String INFO = "hello world!";
}

5、抽象类的基本概念

  1. 描述

    在Java中有一种类专门用来当做父类,这种类称为抽象类。抽象类的作用类似于模板,目的是要设计者根据它的格式来修改并创建新的类。但是不能直接由抽象类创建对象,只能通过抽象类派生出新的类,在由它来创建对象。存在单继承,即一个子类只能继承一个抽象类。

  2. 抽象类的定义和使用规则

    • 包含一个抽象方法的类必须是抽象类
    • 抽象类和抽象方法都要使用abstract关键字声明
    • 抽象方法只需要声明而不需要实现
    • 抽象类必须被子类继承,子类(如果不是抽象类)必须覆写抽象类中全部的抽象方法
  3. 抽象类的定义格式

    abstract class 抽象类名称{
    属性;
    访问权限 返回值类型 方法名称(参数){ // 普通方法
    [return 返回值];
    }
    访问权限 abstract 返回值类型 方法名称(参数); // 抽象方法
    // 在抽象方法中是没有方法体的。
    }

    定义一个抽象类。

    abstract class A{
    public static final String FLAG = "CHINA";
    private String name = "康帅";
    public String getName(){
    return name;
    }
    public void setName(String name){
    this.name = name;
    }
    public abstract void print(); //定义抽象方法
    }

    继承抽象类。

    class B extends A{
    public void print(){
    System.out.println("FLAG = " + FLAG);
    System.out.println("姓名:" + super.getName());
    }
    }

    完整代码:

    abstract class A{
    public static final String FLAG = "CHINA";
    private String name = "康帅";
    public String getName(){
    return name;
    }
    public void setName(String name){
    this.name = name;
    }
    public abstract void print(); //定义抽象方法
    }
    class B extends A{
    public void print(){
    System.out.println("FLAG = " + FLAG);
    System.out.println("姓名:" + super.getName());
    }
    }
    public class AbstractDemo01 {
    public static void main(String[] args) {
    B b = new B(); //实例化子类对象
    b.print(); // 调用被子类覆写过的方法
    }
    }
  4. 抽象类的相关概念

    • 抽象类不能使用final关键字声明。

    • 抽象类中允许存在构造方法。

      abstract class A{
      public A(){
      System.out.println("A、抽象类中的构造方法。");
      }
      }
      class B extends A{
      public B(){
      System.out.println("B、子类中的构造方法。");
      }
      }
      public class AbstractDemo01 {
      public static void main(String[] args) {
      B b = new B(); // 实例化子类对象
      }
      }
      输出:
      A、抽象类中的构造方法。
      B、子类中的构造方法。
    • 抽象方法不要使用private声明。
      因为抽象方法必须被子类覆写,而如果使用了private声明,则子类是无法覆写的。

  5. 抽象类与普通类

    抽象类就是比普通类多定义了一个抽象方法,除了不能直接进行对象的实例化操作之外并没有任何的不同。

6、接口的基本概念

  1. 描述

    接口可以被理解为一种特殊的类,它是由全局常量公共的抽象方法组成。

  2. 接口的定义格式

    interface 接口名称{
    全局常量;
    抽象方法;
    }

    接口中的抽象方法必须定义为public访问权限,在接口中如果不写public,则默认也是public访问权限。

  3. 接口的定义

    interface A{
    public static final String AUTHOR = "康帅"; // 定义全局常量
    public abstract void print(); //定义抽象方法
    public abstract String getInfo(); // 定义抽象方法
    }

    简化形式:

    interface A{
    String AUTHOR = "康帅"; // 定义全局常量
    void print(); //定义抽象方法
    String getInfo(); // 定义抽象方法
    }

    与抽象类一样,接口若要使用也必须通过子类,子类通过implements关键字实现接口。

    class 子类 implements 接口A, 接口B, ...{
    }

    这里一个子类可以同时实现多个接口,拜托了Java的单继承局限。

    接口实现:

    interface A{
    public String AUTHOR = "康帅"; // 定义全局常量
    public void print(); // 定义抽象方法
    public String getInfo(); // 定义抽象方法
    }
    interface B{
    public void say();
    }
    class X implements A,B{
    public void print() {
    System.out.println("帅哥:" + AUTHOR);
    }
    public String getInfo() {
    return "HELLO";
    }
    public void say() {
    System.out.println("Hello World!");
    }
    }
    public class InterfaceDemo01 {
    public static void main(String[] args) {
    X x = new X();
    x.say();
    x.print();
    }
    }
    输出:
    Hello World!
    帅哥:康帅

    继承抽象类并实现接口

    class 子类 extends 抽象类 implements 接口A, 接口B, ...{
    }

    子类同时继承抽象类和实现接口

    interface A{
    public String AUTHOR = "康帅"; // 定义全局常量
    public void print(); // 定义抽象方法
    public String getInfo(); // 定义抽象方法
    }
    abstract class B{
    public abstract void say();
    }
    class X extends B implements A{
    public void print() {
    System.out.println("帅哥:" + AUTHOR);
    }
    public String getInfo() {
    return "HELLO";
    }
    public void say() {
    System.out.println("Hello World!");
    }
    }
    public class InterfaceDemo01 {
    public static void main(String[] args) {
    X x = new X();
    x.say();
    x.print();
    }
    }

    Java中允许一个抽象类实现多个接口。

    interface A{
    public String AUTHOR = "康帅"; // 定义全局常量
    public void print(); // 定义抽象方法
    public String getInfo(); // 定义抽象方法
    }
    abstract class B implements A{ // 定义抽象类,实现接口
    public abstract void say(); // 此时抽象类中存在3个抽象方法
    }
    class X extends B{
    public void print() {
    System.out.println("帅哥:" + AUTHOR);
    }
    public String getInfo() {
    return "HELLO";
    }
    public void say() {
    System.out.println("Hello World!");
    }
    }
    public class InterfaceDemo01 {
    public static void main(String[] args) {
    X x = new X();
    x.say();
    x.print();
    }
    }

    Java中一个接口是不允许继承抽象类的,但是允许一个接口继承多个接口。
    接口的继承

    interface 子接口 extends 父接口A, 父接口B, ...{
    }

7、对象的多态性

  1. 在Java中的体现形式

    1. 方法的重载与覆写。

    2. 对象的多态性。

      1. 向上转型: 子类对象 -----> 父类对象
      2. 向下转型: 父类对象------>子类对象

      对于向上转型,程序会自动完成,而对于向下转型,必须明确的指明要转型的子类类型。

  2. 对象转型格式

    对象向上转型: 父类 父类对象 = 子类实例;
    对象向下转型: 子类 子类对象 = (子类)父类实例;

    这里类似于前面数据类型的转化:自动转换和强制类型转化

    对象向上转型

    class A{
    public void fun1(){
    System.out.println("A-->public void fun1()");
    }
    public void fun2(){
    this.fun1();
    }
    };
    class B extends A{
    public void fun1(){
    System.out.println("B-->public void fun1()");
    }
    public void fun3(){
    System.out.println("B-->public void fun3()");
    }
    };
    public class PolDemo01 {
    public static void main(String[] args) {
    B b = new B(); // 子类实例化对象
    A a = b; // 向上转型
    a.fun1(); //此方法被子类覆写过
    }
    }
    输出:
    B-->public void fun1()

    从程序的运行结果来看,此时虽然是使用父类对象调用了fun1方法,但是实际上调用的方法是被子类覆写过的方法。也就是说,如果对象发生了向上转型关系后,所调用的方法一定是被子类覆写过的方法。但是在此时一定要注意,此时的对象a是无法调用B类中的fun3()方法的,因为此方法只在子类中定义而没有在父类中定义。如果要想调用子类自己定义的其他方法,则肯定要使用子类实例,所以此时可以将对象进行向下转型。

    对象的向下转型

    class A{
    public void fun1(){
    System.out.println("A-->public void fun1()");
    }
    public void fun2(){
    this.fun1();
    }
    };
    class B extends A{
    public void fun1(){
    System.out.println("B-->public void fun1()");
    }
    public void fun3(){
    System.out.println("B-->public void fun3()");
    }
    };
    public class PolDemo01 {
    public static void main(String[] args) {
    A a = new B(); // 发生了向上转型关系
    B b = (B) a; // 向下转型
    b.fun1();
    b.fun2();
    b.fun3();
    }
    }
    输出:
    B-->public void fun1()
    B-->public void fun1()
    B-->public void fun3()

    在进行对象的向下转型前,必须首先发生对象向上转型(也就是告诉父类哪些是它的子类,之后才能向下转型)

8、instanceof关键字

  1. 描述

    使用instanceof关键字判断一个对象到底是那个类的实例。

  2. 格式

    对象 instanceof 类 ---> 返回 boolean 类型
  3. 验证instanceof关键字的作用

    class A{
    public void fun1(){
    System.out.println("A-->public void fun1()");
    }
    public void fun2(){
    this.fun1();
    }
    };
    class B extends A{
    public void fun1(){
    System.out.println("B-->public void fun1()");
    }
    public void fun3(){
    System.out.println("B-->public void fun3()");
    }
    };
    public class PolDemo01 {
    public static void main(String[] args) {
    A a1 = new B(); // 发生了向上转型关系
    System.out.println("A a1 = new B()" + (a1 instanceof A));
    System.out.println("A a1 = new B()" + (a1 instanceof B));
    A a2 = new A();
    System.out.println("A a2 = new A()" + (a2 instanceof A));
    System.out.println("A a2 = new A()" + (a2 instanceof B));
    }
    }
    输出:
    A a1 = new B()true
    A a1 = new B()true
    A a2 = new A()true
    A a2 = new A()false

    可以发现通过子类实例化的对象同时是子类和父类的实例,所以可以直接进行向上或向下转型

    但是如果直接使用父类实例化对象,则一定就不在是子类实例了,所以是不能转型的。

    在类设计时永远不要去继承一个已经实现好的类。
    在类的设计中永远不要去继承一个已经实现好的类,只能继承抽象类或实现接口,因为一旦发生对象的向上转型关系后,所调用的方法一定是被子类所覆写过的方法。

9、抽象类与接口实例化

  1. 描述

    在Java中可以通过对象的多态性为抽象类和接口实例化,这样再使用抽象类和接口时即可调用被子类所覆写过的方法。

  2. 为抽象类实例化

    abstract class A{
    public abstract void print();
    };
    class B extends A{
    public void print(){
    System.out.println("Hello world!");
    }
    };
    public class AbstractCaseDemo01 {
    public static void main(String[] args) {
    A a = new B(); // 通过子类为抽象类实例化
    a.print(); // 调用的方法是被子类覆写过的方法
    }
    }
    输出:
    Hello world!
  3. 为接口进行实例化

    interface A{
    public abstract void print();
    };
    class B implements A{
    public void print(){
    System.out.println("Hello world!");
    }
    };
    public class AbstractCaseDemo01 {
    public static void main(String[] args) {
    A a = new B(); // 通过子类为接口实例化
    a.print(); // 调用的方法是被子类覆写过的方法
    }
    }
    输出:
    Hello world!
    1. 字符串判断

    在进行字符串判断时要把字符串常量写在前面。

    这个做可以避免空指针指向异常

    public class EqualDemo01{
    public static void main(String args[]){
    String str = null;
    System.out.println("HELLO".equals(str));
    }
    }

    因为str的内容是null,而字符串本身就是一个实例化对象。

10、设计模式---代理模式

  1. 描述

    代理设计就是指由一个代理主题来操作真实主题,真实主题执行具体的业务操作,而代理主题负责其他相关的业务处理。

  2. 代理上网

    代理操作:

    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 ProxyDemo {
    public static void main(String[] args) {
    Network net = null;
    net = new Proxy(new Real());
    net.browse();
    }
    }
    输出:
    检查用户是否合法
    上网浏览信息

11、设计模式---适配器设计

  1. 描述

    对于Java程序来说,如果一个类要实现一个接口,则必须要覆写此接口中的全部抽象方法,如果此时接口中定义的抽象方法过多,但是在子类中又用不到这么多的抽象方法,所以此时就需要一个中间的过渡,但是此过渡类又不希望被直接使用,所以将此过渡类定义为抽象类最合适。即一个接口首先被一个抽象类先实现(此抽象类通常称为适配器类),并在此抽象类中实现接口的若干办法(方法体为空)则以后的子类直接继承此抽象类,就可以有选择地覆写所需要的方法。

  2. 适配器设计实现

    interface Window{ // 定义接口
    public void open();
    public void close();
    public void activated();
    public void iconified();
    public void deiconified();
    }
    // 定义抽象类实现接口,在此类中覆写方法,但是所有的方法体为空
    abstract class WindowAdapter implements Window{
    public void activated(){}
    public void open() {}
    public void close() {}
    public void iconified() {}
    public void deiconified() {}
    }
    // 子类直接继承WindowAdapter类有选择地实现需要的方法
    class WindowImpl extends WindowAdapter{
    public void open(){
    System.out.println("窗口打开。");
    }
    public void close(){
    System.out.println("窗口关闭。");
    }
    }
    public class AdapterDemo {
    public static void main(String[] args) {
    Window win = new WindowImpl(); // 实现接口对象
    win.open();
    win.close();
    }
    }
    输出:
    窗口打开。
    窗口关闭。

12、内部类的扩展

  1. 描述

    实际在一个抽象类中也可以定义多个接口或抽象类,在一个接口中也可以定义多个抽象类或接口。

  2. 在一个抽象类中包含接口

    abstract class D{
    public abstract void printA();
    interface B{ // 定义内部接口
    public void printB();
    }
    };
    class E extends D{
    public void printA(){
    System.out.println("HELLO ----> A");
    }
    class Y implements B{ // 定义内部类实现内部接口
    public void printB(){
    System.out.println("HELLO ---->B");
    }
    };
    };
    public class InnerExtDemo01 {
    public static void main(String[] args) {
    D.B b = new E().new Y(); // 实例化内部接口对象
    b.printB(); // 调用内部接口的抽象方法
    }
    }
    输出:
    HELLO ---->B
  3. 在一个接口中包含一个抽象类

    interface F{
    public void printA();
    abstract class B{
    public abstract void printB();
    };
    };
    class X implements F{
    public void printA(){
    System.out.println("HELLO--->A");
    }
    class Y extends B{
    public void printB(){
    System.out.println("HELLO---->B");
    }
    };
    };
    public class InnerExtDemo02 {
    public static void main(String[] args) {
    F.B b = new X().new Y(); // 实例化内部接口对象
    b.printB();
    }
    }
    输出:
    HELLO---->B
  4. 注意

    在抽象类中可以定义多个内部抽象类,在接口中可以定义多个内部接口。

13、抽象类和接口的关系

  1. 抽象类和接口的关系

    区别点 抽象类 接口
    定义 包含一个抽象方法的类 抽象方法和全局常量的集合
    组成 构造方法、抽象方法、普通方法、常量、变量 常量、抽象方法
    使用 子类继承抽象类(extends) 子类实现接口(implements)
    关系 抽象类可以实现多个接口 接口不能继承抽象类,但允许继承多个接口
    常见设计模式 模板设计 工厂设计、代理设计
    对象 都通过对象的多态性产生实例化对象 都通过对象的多态性产生实例化对象
    局限 抽象类有单继承的局限 接口没有此局限
    实际 作为一个模板 作为一个标准或表示一种能力
    选择 如果抽象类和接口都可以使用,则优先使用接口, 避免单继承的局限
    特殊 一个抽象类中可以包含多个接口,一个接口中可以包含多个抽象类
  2. 类的设计原则

    一个类不要去继承一个已经实现好的类,只能继承抽象类或者实现接口,如果接口和抽象类都可以使用,那么优先使用接口,避免单继承局限。

14、Object类

  1. 基本作用

    在Java中所有的类都有一个公共的父类Object,一个类只要没有明显地继承一个类,则肯定是Object类的子类。


    下面两行代码含义相同:

    class Person extends Object{}
    class Person{}
  2. 主要方法

    Object类中的主要方法:

    方法名称 类型 描述
    public Object() 构造 构造方法
    public boolean equals(Object obj) 普通 对象比较
    public int hashCode() 普通 取得Hash码
    public String toString() 普通 对象打印时调用

    toString()

    对象输出时一定会调用Object类中的toString()方法打印内容。

    如:应用toString() 方法取得对象的内容

    class Person04{
    private String name;
    private int age;
    public Person04(String name, int age){
    this.name = name;
    this.age = age;
    }
    public String toString(){
    return "姓名:" + this.name + "年龄:" + this.age;
    }
    }
    public class ObjectDemo01 {
    public static void main(String[] args) {
    Person04 person04 = new Person04("Kang", 18);
    System.out.println("对象信息:" + person04);
    }
    }
    输出:
    对象信息:姓名:Kang年龄:18

    程序的Person04类中覆写了Object类中的toString()方法,这样直接输出对象时调用的是被子类覆写过的toString()方法。


    equals()

    Object类提供的equals()方法默认是比较地址的,并不能对内容进行比较。

    对象的比较:

    class Person05{
    private String name;
    private int age;
    public Person05(String name, int age){
    this.name = name;
    this.age = age;
    }
    public boolean equals(Object obj){ // 覆写Object类中的equals()方法
    if (this == obj){ // 如果两个对象的地址相同则肯定是同一个对象
    return true;
    }
    if (!(obj instanceof Person05)){
    return false;
    }
    Person05 per = (Person05)obj; // 将传进来的对象进行向下转型
    if (per.name.equals(this.name) && per.age == this.age){
    return true;
    }else {
    return false;
    }
    }
    public String toString(){
    return "姓名:" + this.name + "年龄:" + this.age;
    }
    }
    public class ObjectDemo02 {
    public static void main(String[] args) {
    Person05 per1 = new Person05("Kang", 18);
    Person05 per2 = new Person05("Kang", 18);
    System.out.println(per1.equals(per2)?"是同一个人":"不是同一个人");
    System.out.println(per1.equals("Hello")?"是同一个人":"不是同一个人");
    }
    }
    输出:
    是同一个人
    不是同一个人

    程序说明:在Person05类中覆写的equals()方法,首先判断传递进来的对象与当前对象的地址是否相同,如果相同,则肯定是同一个对象,因为在equals()方法中传递的参数是Object类型,所以任何对象都可以接收,这样再对象向下转型前就必须进行判断,判断传进来的对象是否是Person05的实例,如果不是直接返回false,如果是则对各个属性的值进行判断。

  3. 接收任意引用类型的对象

    Object类是所有对象的父类,则所有对象都可以向Object进行转换,在这其中也包含了数组和接口类型,即一切的引用数据类型都可以使用Object进行接收。


    使用Object接收接口实例

    interface H{
    public String getInfo();
    }
    class J implements H{
    public String getInfo(){
    return "Hello World!!!";
    }
    }
    public class ObjectDemo03 {
    public static void main(String[] args) {
    H h = new J(); // 为接口实例化
    Object obj = h; // 对象向上转型
    H x = (H) obj; // 对象向下转型
    System.out.println(x.getInfo());
    }
    }
    输出:
    Hello World!!!

    使用Object接收数组

    public class ObjectDemo04 {
    public static void main(String[] args) {
    int temp[] = {1, 3, 5, 7, 9};
    Object obj = temp; // 使用Object接收数组
    print(obj);
    }
    public static void print(Object o){ // 接收一个对象
    if (o instanceof int[]){ // 判断对象的类型
    int x[] = (int[]) o; // 向下转型
    for (int i = 0; i < x.length; i++) {
    System.out.print(x[i] + "\t");
    }
    }
    }
    }
    输出:
    1 3 5 7 9

    使用print()方法输出时先通过instanceof判断类型是否是一个整型数组,然后进行输出操作。

15、包装类

  1. 包装类介绍

    Java的设计提倡一切皆对象的思想。这样就会出现一个矛盾:数据类型的划分,分为基本数据类型和引用数据类型。让基本数据类型称为对象就需要把基本数据类型包装成类的形式。
    包装类

    基本数据类型 包装类
    int Integer
    char Character
    short Short
    long Long
    float Float
    double Double
    boolean Boolean
    byte Byte

    包装类的继承关系:

    1. Integer、Byte、Float、Double、Short、Long都属于Number类的子类,Number类本身提供了一些列的返回以上6种基本数据类型的操作。
    2. Character属于Object的直接子类。
    3. Boolean属于Object的直接子类。

    Number类是一个抽象类,主要将数字包装类中的内容变为基本数据类型。
    Number类定义:

    方法 类型 描述
    public byte byteValue() 普通 以byte形式返回指定的数值
    public abstract double doubleValue() 普通 以double形式返回指定的数值
    public abstract float floatValue() 普通 以float形式返回指定的数值
    public abstract int intValue() 普通 以int形式返回指定的数值
    public abstract long longValue() 普通 以long形式返回指定的数值
    public short shortValue() 普通 以short形式返回指定的数值
  2. 装箱与拆箱

    装箱操作:将一个基本数据类型变成包装类。

    拆箱操作:将一个包装类变为基本数据类型。


    手工装箱拆箱操作

    public class WrapperDemo01 {
    public static void main(String[] args) {
    int x = 30;
    Integer i = new Integer(x); // 装箱,将基本数据类型变为包装类
    int temp = i.intValue(); // 拆箱,将一个包装类变为基本数据类型
    }
    }

    JDK1.5之后提供自动装箱拆箱操作

    public class WrapperDemo02 {
    public static void main(String[] args) {
    Integer i = 30; // 自动装箱成Integer
    Float f = 30.3f; // 自动装箱成Float
    int x = i; // 自动拆箱为 int
    float y = f; // 自动拆箱为 float
    }
    }
  3. 包装类的应用

    用的最多的就是把字符串变为基本数据类型的操作。例如:将一个全由数字组成的字符串变为一个int或float类型的数据。Integer类和Float类中分别提供的方法:
    Integer类(字符串转int)

    public static int parseInt(String s) throws NumberFormatException

    Float类(字符串转float)

    public static float parseFloat(String s) throws NumberFormatException

    注意:使用这两种方法时,字符串必须有数字组成。

    字符串变基本数据类型:

    public class WrapperDemo3 {
    public static void main(String[] args) {
    String str1 = "30";
    String str2 = "30.3";
    int x = Integer.parseInt(str1); // 将字符串变为int
    float f = Float.parseFloat(str2); // 将字符串变为 float
    System.out.println("x * f = " + x * f);
    }
    }
    输出:
    x * f = 909.0

16、匿名内部类

匿名内部类就是指没有一个具体名称的类。

//匿名内部类
interface A01{
public void printInfo(); // 定义接口抽象方法
}
class X01{
public void fun1(){ // 定义fun1方法
this.fun2(new A01() { // 匿名内部类
@Override
public void printInfo() { // 实现接口的抽象方法
System.out.println("Hello World!!!");
}
});
}
public void fun2(A01 a){ // 接收接口实例
a.printInfo(); // 调用接口方法
}
}
public class NoInnerClassDemo02 {
public static void main(String[] args) {
new X01().fun1();
}
}
输出:
Hello World!!!

解释代码:

  1. 直接实例化接口对象

    new A01(){}

    接口本身是不能直接进行实例化的,所以在接口实例化后要有一个大括号,用于实现接口中的抽象方法。

  2. 实现抽象方法

    new A(){
    public void printInfo(){
    System.out.println("Hello World!!!");
    }
    }
posted @   e路有你  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示