写点什么

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

作者:胖虎不秃头
  • 2022 年 10 月 09 日
    河南
  • 本文字数:4419 字

    阅读完需:约 14 分钟

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

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 + 回车


发布于: 刚刚阅读数: 3
用户头像

还未添加个人签名 2022.07.29 加入

还未添加个人简介

评论

发布
暂无评论
Surpass Day——Java 接口在开发中的作用、关于Object类、内部类_Java_胖虎不秃头_InfoQ写作社区