Surpass Day13——Java 接口在开发中的作用、关于Object类、内部类

目录

1、接口在开发的作用

2、继承、关联、实现

3、抽象类和接口的语法区别

4、关于Object类

4.1 什么是ApI?

4.2 Object类中的方法

4.3 关于toString方法

4.4 关于equals方法

4.5 关于finalize()方法

4.6 关于hashCode方法

5、内部类

5.1 定义

5.2 内部类的分类

5.3 代码解释

5.4 匿名内部类


1、接口在开发的作用

类似于多态在开发中的作用;

  • 多态:面向抽象编程(面向接口编程),不要面向具体编程。降低程序的耦合度,提高程序的扩展力,符合OCP的开发原则;

  • 接口的使用离不开多态机制(接口+多态才可达到解耦合);

  • 接口可以解耦合,解的是调用者实现者的耦合;

  • 调用者面向接口调用,实现者面向接口实现

以去餐馆吃饭为例:

接口是抽象的,菜单是一个接口(菜单上有一个抽象的照片:西红柿炒鸡蛋)

谁面向接口调用?(顾客面向菜单点菜,调用接口)

谁负责实现这个接口呢?(后台的厨师负责把西红柿炒鸡蛋做好,是接口的实现者)

这个接口有什么用呢?(有这个饭馆的"菜单",让“顾客”和“后厨”解耦合了,他们完全依靠这个抽象的菜单沟通)

public class Super {
    public static void main(String[] args) {
        //创建厨师对象
        Meau c1 = new ChineseCook();
        //创建顾客对象
        Customer customer = new Customer(c1);
        //顾客点菜
        customer.order();
    }
}
interface Meau{
    void ChaoDan();
    void RouSi();
}
class Customer{
    //Customer has a Meau!顾客手里有一个菜单
    //实例变量:属性
    private Meau meau;
    //提供点菜的方法
    public void order(){
        //调用get方法或直接访问先拿菜单
        Meau m = this.getMeau();
        m.ChaoDan();
        m.RouSi();
        //meau.RouSi();
        //meau.ChaoDan();
    }
​
    public void setMeau(Meau meau) {
        this.meau = meau;
    }
​
    public Meau getMeau() {
        return meau;
    }
​
    public Customer() {
    }
​
    public Customer(Meau meau) {
        this.meau = meau;
    }
//如果以下这么写就写死了,焊死了,没有可插拔了
    //ChineseCook c1;
    //JapaneseCook c2;
}
class ChineseCook implements Meau{
    public void ChaoDan(){
        System.out.println("中餐师傅做炒蛋");
    }
    public void RouSi(){
        System.out.println("中餐师傅做肉丝");
    }
}
class JapaneseCook implements Meau{
    public void ChaoDan(){
        System.out.println("日本师傅做炒蛋");
    }
    public void RouSi(){
        System.out.println("日本师傅做肉丝");
    }
}

2、继承、关联、实现

is a:继承
Cat is a Animal;(猫是一个动物)
凡是满足is a的表示都可以设置为“继承”;
A extends B
has a:关联
I has a Animal;(我有一支笔)
凡是能够用has a来描述的,统一以“属性(关联)”的方式存在;
A{
    B b;
}
like a:实现
Cook like a FoodMeau;(厨师像一个菜单一样)
凡是能够满足like a关系的表示类“实现”接口;
A implement B;

3、抽象类和接口的语法区别

抽象类是半抽象的; 接口是完全抽象的;

抽象类中有构造方法; 接口中没有构造方法;

接口和接口之间支持多继承; 一个抽象类只能继承一个类(单继承);

接口中只允许出现常量和抽象方法;

注意:以后接口使用的比抽象类多,接口一般都是对“行为”的抽象


4、关于Object类

4.1 什么是ApI?

  • 应用程序编程接口;

  • 整个JDK的类库就是一个javase的API;

  • 每一个API都会配置一套API帮助文档;

  • SUN公司提前写好的这套类库就是API(一般每一份API都对应一份API帮助文档);

4.2 Object类中的方法

protected Object clone() //负责对象克隆的

int hashCode() //获取对象哈希值的一个方法

boolean equals(Object obj) //判断两个对象是否相等

String toString() //将对象转换成字符串形式

protected void finalize() //垃圾回收器负责调用的方法

4.3 关于toString方法

1)源代码

public String toString(){
    return this.getClass().getName() + "@" + Integar.toHexString(hashCode());
}
//源代码上toString()方法的默认实现是:
//类名@对象的内存地址转换为十六进制的形式

2)作用:

调用toString方法可以将一个"java对象"转换成字符串表示形式

3)建议所有子类都去重写toString()方法,toString()方法应该是一个简洁的、详实的、易阅读的

public class Hello{
    public static void main(String[] args) {
        Time t1 = new Time(1970,1,1);
        String s1 = t1.toString();
        System.out.println(s1);
        //System.out.println(t1);
    }
}
class Time{
    int year;
    int month;
    int day;
    public Time(){
​
    }
    public Time(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }
    //重写之前:输出Time@a09ee92
    public String toString(){
        return this.year + "年" +this.month+ "月" + this.day + "日";
    }//重写之后:输出1970年1月1日
}

4.4 关于equals方法

1)源代码

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

以上这个方法是Object类的默认实现,默认采用==判断两个java对象是否相等,而==判断的是java对象的内存地址是否相等,需要重写equals

2)作用:

判断两个java对象是否相等

3)代码表示

public class Hello{
    public static void main(String[] args) {
        Time t1 = new Time(2008,8,8);
        Time t2 = new Time(2008,8,8);
        System.out.println(t1 == t2);//这是比较的是两个对象保存的内存地址是否相等?
        boolean b = t1.equals(t2);
        System.out.println(b);
        //System.out.println(t1.equals(t2));
    }
}
class Time {
    int year;
    int month;
    int day;
​
    public Time() {
​
    }
​
    public Time(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }
​
    //重写equals方法
    public boolean equals(Object obj) {
        //如果obj为空,如果obj不是Time类型没必要比较,直接返回false
        if (obj == null||!(obj instanceof Time))
            return false;
        //如果obj保存的地址相同没必要比较,直接返回true
        if (this == obj) {
            return true;
        }
        //这里直接向下转型,obj一定是Time类型
        Time t = (Time) obj;
        return this.year == t.year && this.month == t.month && this.day == t.day;
    }
}

4)String类已经重写了equals和toString方法,String中存在构造方法且字符串比较不能用"=="

5)基本数据类型比较能使用"==",所有的引用数据类型比较需要调用equals方法;

4.5 关于finalize()方法

1)源代码

protected void finalize() throws Throwable{ }

2)finalize()方法只有一个方法体里面没有代码,而且这个方法是protected修饰的;

3)这个方法不需要程序员手动调用,JVM的垃圾回收负责调用这个方法;

4)finalize()方法实际上是SUN公司为java程序员准备的一个时机,垃圾销毁时机,如果希望在对象销毁的时机执行一段代码的话,这段代码要写到finalize()方法当中;

5)

public class Gc {
    public static void main(String[] args) {
        Peason p = new Peason();
        p = null;
    }
}
class Peason{
    protected void finalize() throws Throwable{
        System.out.println("对象垃圾即将被销毁!!!");
    }
}

java中的垃圾回收器不是轻易启动的,垃圾太少,或者时间没到,种种条件下可能启动也可能不启动;

System.gc();//可以建议垃圾回收器启动,但不一定启动;

4.6 关于hashCode方法

1)源代码

public native int hashCode();

2)这个方法不是抽象方法,带有native关键字,底层调用C++程序;

3)hashCode()方法返回的是哈希码;

实际上就是一个java对象的内存地址,经过哈希算法得出一个值,所以hashCode()方法的执行结果可以等同看做一个java对象的内存地址

4)

public class HashCode{
    public static void main(String[] args) {
        Object o = new Object();
        int hashCOdeValue = o.hashCode();
        System.out.println(hashCodeValue);
    }
}

5、内部类

5.1 定义

内部类:在类的内部又定义了一个新的类,被称为内部类

5.2 内部类的分类

静态内部类:类似于静态变量;

实例内部类:类似于实例变量;

局部内部类:类似于局部变量;匿名内部类属于局部内部类的一种(没有名字)

5.3 代码解释

class Test{
    //静态内部类
    static class Inner1{
    }
    //实例内部类
    class Inner2{
    }
    public void doSome(){
        //局部变量
        int i = 10;
        //局部内部类
        class Inner3{
        }
    }
    public void doOther(){
        new Test.new Inner2//这样使用
        //doSome()方法中的内部类Inner3,在doOther()中不能用
    }
}

使用内部类编写的代码可读性很差

5.4 匿名内部类

是局部内部类的一种,没有名字

public class Test {
    public static void main(String[] args) {
        MyMath mm = new MyMath();
        //ComputerImp c = new ComputerImp()
        //mm.mySum(c,100,200);
        //以上两行代码可以直接换成下面一行
         mm.mySum(new ComputerImp(),100,200);
    }
}
//负责计算的接口
interface Computer{
    //抽象方法
    int sum(int a,int b);
}
//编写一个Computer接口的实现类用来创建对象
class ComputerImp implements Computer{
    //对方法的实现
    public int sum(int a,int b){
        return a + b;
    }
}
//数学类
class MyMath{
    //数学求和方法
    public void mySum(Computer c,int x,int y){
        int retValue = c.sum(x,y);
        System.out.println(x + "+" + y + "=" + retValue);
    }
}

使用匿名内部类之后

public class Test {
    public static void main(String[] args) {
        MyMath mm = new MyMath();
        mm.mySum(new Computer(){
            int sum(int a,int b){
                return a + b;
            }
        },100,200);//这里并不是接口可以直接new了,中间的{}代表了对接口的实现
    }
}
interface Computer{
    int sum(int a,int b);
}
class ComputerImp implements Computer{
    //对方法的实现不用写了,用匿名内部类实现
}
//数学类
class MyMath{
    //数学求和方法
    public void mySum(Computer c,int x,int y){
        int retValue = c.sum(x,y);
        System.out.println(x + "+" + y + "=" + retValue);
    }
}

不建议用匿名内部类,因为没有名字,没办法重复使用,代码太乱,可读性太差

注意:使用IDEA自动写匿名内部类

mm.mySum(new Computer(){},写完这个之后,需要纠正错误:

光标移动到红色下划线下面,快捷键:Alt + 回车

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胖虎不秃头

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值