Java从零开始 第9讲 Object类,内部类

Object类

Object类是所有类的父类,即你创建一个没有继承的类,此类就默认继承Object类。

Object也可以用于接收数据,使用Object可以接收任意的应用数据类型

Object类是一个官方给出的,已经定义好的类,通过Ctrl + 左键 点击声明语句中的Object(如下)就可以查看Object类的源码
在这里插入图片描述

toString和equals方法

Object类中有一些十分重要的方法,其中就包括toString和equals,这两种方法都需要重写来对他们进行提升

toString方法

toString方法是在print类中默认调用的

package oop;

public class OOPSenior {

    public static void main(String[] args) {
        
        Father father = new Father();
        System.out.println(father);
        System.out.println(father.toString());

    }
}

class Father{

    void say(){
        System.out.println("父类中say方法被调用了");
    }

}


运行结果:
oop.Father@b4c966a
oop.Father@b4c966a

Process finished with exit code 0

注意在以上代码中,System.out.println(father);和System.out.println(father.toString());输出了相同的结果,即输出father时默认调用了toString方法

toString在Object类中的源码十分简单:

    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

所以为了给类一个更好的描述,推荐给每个类都重写toString方法,这样直接执行System.out.println(类名);的时候,就会运行你重写的toString内容

package oop;

public class OOPSenior {

    public static void main(String[] args) {

        Father father = new Father();
        System.out.println(father);
        System.out.println(father.toString());

    }
}

class Father{

    void say(){
        System.out.println("父类中say方法被调用了");
    }

    @Override
    public String toString(){
        return "这是father类";// 可以写任何你想要输出的
    }

}


运行结果:
这是father类
这是father类

Process finished with exit code 0

equals方法

在Object类源码中equals类也很简单

    public boolean equals(Object obj) {
        return (this == obj);
    }

让我们同样看看equals能来代替什么:

public class OOPSenior {

    public static void main(String[] args) {

        Father father1 = new Father("大明");
        Father father2 = new Father("大明");
        System.out.println(father1 == father2);
        System.out.println(father1.equals(father2));

    }
}

class Father{
    String name;
    Father(String name){
        this.name = name;
    }

}

运行结果:
false
false

Process finished with exit code 0

在这里,两个对象拥有相同的名字,但是仍然不相等,因为他们有着不同的内存地址,这意味着无论两个对象属性多么一致,都会返回false,除非一个对象跟他自己比。

所以我们需要重写equals方法来改善这一点

public class OOPSenior {

    public static void main(String[] args) {

        Father father1 = new Father("大明");
        Father father2 = new Father("大明");
        System.out.println(father1 == father2);
        System.out.println(father1.equals(father2));

    }
}

class Father{
    String name;
    Father(String name){
        this.name = name;
    }
    
    @Override
    public boolean equals(Object obj){
        if(this == obj)// 如果这是一个对象和自己比较
            return true;
        if(obj == null)// 如果两个对象都非空,当然this肯定非空可以省略
            return false;
        if(obj instanceof Father){// 如果传入的类也是Father类
            if(this.name.equals(((Father) obj).name))// 这里写具体判断条件,这里我用名字相同作为判断条件
                return true;
        }
        return false;
    }

}

运行结果:
false
true

Process finished with exit code 0

可以看到通过equals已经能够正确的比较我们希望比较的值了
特别注意:这里的 ==方法仍然返回的是false,和toString方法不一样,equals并不是完全和 ==符号等效)

内部类

内部类,即为定义在另一个类或者方法里面的类,所以包括内部类的类可以被称为外部类
内部类主要分为四种:成员内部类,局部内部类,匿名内部类,和静态内部类,让我们分别介绍他们
特别注意:这四个类型并不是完全平行的,如匿名内部类是局部内部类的一种)

成员内部类

成员内部类即跟成员属性有相同位置,直接定义在另一个类下的类。成员内部类可以访问其外部类的所有属性和方法(即使是private修饰的),内部类通过如下方式创建对象(外部类名为Outter,内部类为Inner):
Outter outter = new Outter();
Outter.Inner inner = outter.new Inner();

在内部类和外部类有同样名字的属性或方法时,会优先访问内部类,如果要访问外部类,则需要:
外部类.this.成员变量
外部类.this.成员方法

局部内部类

局部内部类即被定义在一个方法中的类,局部内部类就像是一个局部变量,仅能作用于该方法内,因此不能用任何权限修饰符修饰

虽然看起来局部内部类作用很鸡肋,但是局部内部类的存在并不是毫无作用,而是为了让代码更适应于抽象的方法,如果一些方法在其被抽象定义的时候就要求传入一个类的对象时,你可以通过定义局部内部类的方法传入对象

匿名内部类

我们之前曾经讲过匿名对象,匿名内部类跟匿名对象很像,都只能使用一次,创建一次对象之后便不能再使用。匿名内部类的定义不需要class,只需要new:

new 父类构造器(参数列表) |实现接口() {       //匿名内部类的类体部分      
}

匿名内部类必须满足以下条件:

  • 继承一个类或者实现一个接口(二选其一)
  • 不能定义构造函数
  • 不能存在静态成员变量或方法
  • 不能是抽象的
  • 只能访问final类型的局部变量
  • 必须符合所有对局部内部类的限制

其他都很好理解,但是注意第四条,只能访问final类型的局部变量,这其实是因为匿名内部类在被JVM编译时会单独作为一份class的字节码文件存在,而在运行过程中,非final定义的变量可能会变化,但是该class字节码文件已经备份,无法更改其中的量,所以Java语言规定了匿名内部类中只能使用final修饰的变量
特别注意:如果你在外定义了一个变量并且在匿名内部类中被使用,该变量自动视为被final修饰了)

静态内部类

静态内部类也是定义在另一个类里面的类,只不过加了一个static修饰,和静态成员属性一样,静态内部类也是不需要依赖于外部类对象的(直接创建静态内部类的对象),并且同样无法使用非static的变量或者方法

转载请注明出处

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值