目录
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方法;