Java学习10
今天找了老师,感觉一下子释然了好多,哈哈,有一段时间没这么轻松了
接口
接口通常提取的是行为动作,能插拔的是接口,有了接口就有了可插拔,可插拔表示扩展力很强
接口的基础语法:
- 接口也是一种引用数据类型,编译之后也是一个class字节码文件
- 接口是完全抽象的,(抽象类是半抽象的),或者也可以说接口是特殊的抽象类
- 接口怎么定义,语法是什么?
[修饰符列表] interface 接口名{ } - 接口支持多继承,一个接口可以继承多个接口
- 接口中只包含两部分内容,常量和抽象方法,接口中没有其他内容了
注意:
如果是Java 7,那么接口中可以包含的内容有:
1. 常量
2. 抽象方法
如果是Java 8,还可以额外包含有:
3. 默认方法
4. 静态方法
如果是Java 9,还可以额外包含有:
5. 私有方法
接口的默认方法,可以通过接口实现类对象,直接调用。
接口的默认方法,也可以被接口实现类进行覆盖重写。
-
接口中的所有元素都是public修饰的(都是公开的)
-
接口中的抽象方法定义时:public abstract修饰符可以省略
-
接口中的方法都是抽象方法,所以不能有方法体
-
接口中的常量:public static final可以省略
-
类和类之间叫做继承,类和接口之间叫做实现,这个实现仍然可以看做继承
实现使用implements
没有继承时也默认继承Object -
当一个非抽象的类实现接口的话,必须将接口中的方法全部实现,修饰符public不能丢
回顾:方法重写时访问权限只能更高,不能更低 -
一个类可以同时实现多个接口。这种机制弥补了java中类和类中只支持单继承的缺陷
实现多个接口,其实就类似于多继承 -
接口与接口之间虽然没有继承关系,但是写代码的时候,可以互转,编译器没意见,但是运行时可能出现:ClassCastException
之前有个结论:无论是向上转型还是向下转型,两种类型之间必须有继承关系,没有继承关系编译器会报错(这句话不适用于接口方面)。最终实际上和之前一样,还是需要加instanceof运算符进行判断 -
如果一个类继承了多个接口,这个类的对象可以转型为这些接口
-
继承和实现都存在,extends关键字在前,implements 在后
利用多态创建对象的时候,需要用接口创建,利用类名创建会报错(用接口中的方法)
接口在开发中的作用
面向抽象编程这句话以后可以修改为:面向接口编程。
接口在开发中的作用,类似多态在开发中的作用
多态:面向抽象编程,不要面向具体编程,降低程序的耦合度,提高程序的扩展力
Cat is a Animal,但凡满足is a的表示都可以设置为继承
Customer has a FoodMenu, 但凡满足has a 的表示都以属性的形式存在
面向接口编程,可以降低程序的耦合度,提高程序的扩展力,符合OCP开发原则
接口的使用离不开多态,接口+多态才可以达到解耦合
任何一个接口都有调用者和实现者,接口可以将调用者和实现者解耦合
调用者面向接口调用,实现者面向接口编写实现
类型和类型之间的关系:is a、 has a 、 like a
is a:
凡是能够满足is a的表示“继承关系”
A extends B
has a:
凡是能够满足has a关系的表示“关联关系”,关联关系通常以“属性”的形式存在
A{
B b;
}
like a:
凡是满足like a关系的表示“实现关系”,实现关系通常是:类实现接口
A implements B
抽象类和接口有什么区别
这里只说语法上的区别
抽象类是半抽象的,接口是完全抽象的
抽象类中有构造方法,接口中没有构造方法
接口和接口之间支持多继承,类和类之间只能单继承
一个类可以实现多个接口,一个抽象类只能继承一个类(单继承)
接口中只允许出现常量和抽象方法,抽象类中可以有成员变量、构造方法、抽象方法、实例方法
package和import
为什么要使用package?
package是java中的包机制,包机制的作用是为了方便程序的管理
不同功能的类分别存放在不同的包下(按照功能划分的,不同的软件包具有不同的功能)
package怎么用?
package是一个关键字,后面加包名,例如:
package com.bjpowernode.javase.chapter17;
注意:package语句只允许出现在java程序的第一行
包名有没有命名规范?
一般都采用公司域名倒序的方式(因为公司域名具有全球唯一性)
包命名规范:
公司域名倒序+项目名+模块名+功能名
对于有package的java程序怎么编译?怎么运行?
采用之前的编译和运行不行了
类名不再是:HelloWorld
类名是:com.bjpowernode.javase.chapter17.HelloWorld
编译:javac -d.HelloWorld.java
解释一下:
javac 赋值编译命令
-d 带包编译
. 代表编译之后生成的东西放到当前目录下(点代表当前目录)
运行:java com.bjpowernode.javase.chapter17.HelloWorld
java 完整类名
以后说类名的时候,如果是带着包名描述,表示完整类名,如果没有带
关于import的使用?
A类中使用B类:
A类和B类都在同一个包下:不用import
A类和B类不在同一个包下:需要使用import
java.lang包下的不需要import导入
import怎么使用?
import语句只能出现在package语句之下,class声明语句之上
import语句还可以使用星号的方式,例如:
import com.bjpowernode.javase.chapter17.*
import 完整类名;
import 包名.*;
import java.; 这是不允许的,因为在java语言中规定,这里的只代表某些类的名字。
package com.bjpowernode.javase.chapter17;
import java.util.Scanner; //java.util 是一个包
//import java.util.*
public static void main(String[] args){
Scanner s = new Scanner(System.in);
String str = s.next();
System.out.println(“您输入的字符串是:”+str);
}
访问控制权限
共有四个:
private 私有
protected 受保护
public 公开
default 默认的
private 表示私有的,只有在本类中可以访问
public 表示公开的,最高权限,在哪都行
protected 表示只能在本类,同包、子类中访问
默认 表示只能在本类,以及同包下访问
访问控制修饰符 本类 同包 子类 任意位置
public 可以 可以 可以 可以
protected 可以 可以 可以 不可以
默认 可以 可以 不可以 不可以
private 可以 不可以 不可以 不可以
范围从大到小排序:public>protected>默认>private
访问控制权限修饰符可以修饰什么?
属性(4个都能用)
方法(4个都能用)
类(public和默认都能,其他不行)
接口(public和默认能用,其他不行)
Object类
Object中有哪些方法?
第一种方法:去源代码中找
第二种方法:去查阅java的类库中的帮助文档
API 是应用程序编程接口(Application Program Interface)
整个JDK的类库就是一个javase的API
每一个API都会配置一套API 的帮助文档
SUN公司提前写好的这套类库就是API
protected Object clone()//负责对象克隆的
int hashCode()//获取对象哈希值的一个方法
boolean equals(Object obj)//判断两个对象是否相等
String toString() //将对象转换成字符串形式
protected void finalize() //垃圾回收器负责调用的方法
toString
不重写输出的是类名@地址的哈希值
SUN公司设计toString方法的目的是什么?
toString()方法的设计目的是:通过调用这个方法可以将一个“java对象”转化成“字符串”的形式
SUN公司建议都去所有子类都去重写toString()方法,应该是一个简洁的、详实的、易阅读的
输出引用的时候,会自动调用toString()方法
equals
SUN公司设计equals方法的目的是:判断两个对象是否相等。
判断两个基本数据类型是否相等,直接用“==”就行
判断两个对象是否相等,不能使用“==”,因为“==”比较的是两个对象的内存地址
在Object类中的equals方法中,默认采用的是“==”判断,所以不能判断两个对象是否相等,所以需要重写
一般这样写:(三行)
如果obj等于空或者obj不是本类对象,返回false
如果地址相同,返回true
判断内容是否相同(需要将obj先向下转型)
String类重写toString和equals
由于String类已经重写了equals,另外String不是基本数据类型,所以比较两个字符串时,不能用“==”,应该用equals方法(*****)
String类重写了toString方法,所以会输出引用指向的内容,而不是内存地址
java中判断基本数据类型,用“==”
判断引用数据类型,用“equals”
equals方法重写要彻底,以后只要写类都重写
finalize()方法
这个方法只有一个方法体,里面没有代码,这个方法是protected修饰的
这个方法不需要程序员手动调用,JVM的垃圾回收器负责调用这个方法
finalize()方法只需要重写,不需要手动调用,GC会自动调用
finalize()方法的执行时机:
当一个java对象即将被垃圾回收器回收的时候,垃圾回收器负责调用finalize()方法
finalize()方法实际上是SUN公司为java程序员准备的一个时机,垃圾销毁时机。
如果希望在对象销毁时执行一段代码的话,这段代码要写到finalize()方法当中
java中的垃圾回收器不是轻易启动的,垃圾太少,或者时间未到,种种条件下,有可能启动,也有可能不启动
System.gc(); 建议启动垃圾回收器(只是建议,可能启动,也可能不启动)
hashCode方法:
hashCode方法返回的是哈希码:
实际上是一个java对象的内存地址,经过哈希算法,得出的一个值
所以hasCode()方法的执行结果可以等同看做一个java对象的内存地址
匿名内部类
什么是内部类?
内部类:在类的内部又定义一个新的类,被称为内部类
内部类的分类:
静态内部类:类似于静态变量
局部内部类:类似于局部变量
实例内部类:类似于实例变量
内部类可以用所有修饰符修饰
使用内部类编写的代码,可读性很差,不建议使用
匿名内部类是局部内部类的一种,因为这个类没有名字而得名
学习匿名内部类是为了看懂别人写的代码,但是复杂,而且不能重复使用