1、接口在开发的作用
类似于多态在开发中的作用;
以去餐馆吃饭为例:
接口是抽象的,菜单是一个接口(菜单上有一个抽象的照片:西红柿炒鸡蛋)
谁面向接口调用?(顾客面向菜单点菜,调用接口)
谁负责实现这个接口呢?(后台的厨师负责把西红柿炒鸡蛋做好,是接口的实现者)
这个接口有什么用呢?(有这个饭馆的"菜单",让“顾客”和“后厨”解耦合了,他们完全依靠这个抽象的菜单沟通)
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?
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 + 回车
评论