1.接口
1.引用数据类型
2.特殊的抽象类(可以定义抽象方法)
3.接口为功能(抽象功能)的集合、
4.class定义类,用interface定义接口
5.接口多实现,类是单继承
6.继承与实现非常像 子类有权使用父类(接口)的功能和属性
子类继承父类,可以不重写方法直接使用
实现类实现一个接口,但都为抽象功能,需要实现类自己重写,侧重点关注编写
7.定义开发规范(不同类实习接口,方法名参数都一致,规范)
8.实现解耦,降低耦合度(类似与USB接口,需要适配规则才能适用,不是为某一个外界设备进行设计,而是适配所有适合的设配)。
注意:对于继承关系,耦合度是比接口高的,他是特定于为某些子类服务的,但接口不是,他是一个定义规范,使用用所有符合规则的实现。
语法:
jdk1.7之前:
公共的静态的常量:public static final 可以省略
公共的抽象方法:public abstract 可以省略
jdk1.8之后:
静态方法:被static关键字修饰的方法
只能通过接口名使用,不能通过实现类使用
默认方法:被defalut关键字修饰的方法 可以有方法体
只能通过实现类调用
接口多态:只能调用接口中存在发内容,对实现类新增内容不可见,如果实现类中存在重写方法调用重写后的方法。
使用:
1.接口不能实例化
2.需要通过实现类进行实现 implements
3.通过具体的实现类对象调用
具体实现类:重写所有的抽象方法+按需新增
抽象实现类:按需重写(改为default则可以拥有方法体)+按需新增
需要具体的子类继承,重写抽象方法
4.先继承后实现
5.类和接口之间:只能实现接口,多实现接口
6.接口与接口之间:只能继承不能实现,一个接口可以继承其他接口
7.接口可以多实现,类只能单继承
对于多实现的接中存在同名同参数列表的抽象方法和静态方法,是不会影响抽象方法的实现的,,
因为他和他和编译前的引用变量的类型有关,但对于默认方法,因为连个接口都拥有默认方法,类似于子类的重写特性,不知道该调用哪个方法,需要实现类重写默认方法。
public interface IntefacePractice {
public static void staicMethod(){
System.out.println("我是静态1方法");
}
default void defaultMethod(){
System.out.println("我是默认1方法");
}
//我是静态常量
int a =10;
void abstractMethod();
}
interface IntefacePractice2 extends IntefacePractice{
@Override
default void abstractMethod(){
}
}
interface Inteface2{
void abstractMethod();
public static void staicMethod(){
System.out.println("我是静态3方法");
}
default void defaultMethod(){
System.out.println("我是默认3方法");
}
}
class TextClass implements IntefacePractice,Inteface2{
public static void main(String[] args) {
IntefacePractice textClass = new TextClass();
textClass.abstractMethod();
IntefacePractice.staicMethod();
textClass.defaultMethod();
}
@Override
public void defaultMethod() {
System.out.println("我是默认4方法");
}
@Override
public void abstractMethod() {
System.out.println("abstract");
}
}
运行结果
2.内部类
类中定义的类
外部类 内部类
分类:
成员内部类:内部类定义在成员的位置(可以继承和实现)具有成员的特点,可以被成员修饰符修饰....
注意:成员内部类不能定义静态内容,除了静态常量
成员内部类中可以直接使用外部类的成员,包括私有。
外部类中可以通过成员内部类调用成员内部类属性或功能
通过外部类对象去创建内部类的对象,通过成员内部类对象调用成员内部类成员。
成员内部类与外部类成员重名问题:
私有内部类:
私有内部类:被private关键字修饰的成员内部类
私有内部类可以直接使用外部类的成员,包括私有的
在外部类中,可以直接new 内部类对象 调用成员
私有内部类只能在当前外部类中使用,在其他类中无法使用
静态内部类:
被static修饰的内部类
静态内部类中可以定义静态内容(不能直接使用外部类成员,需要根据对象才能调用)
在静态内部类可以直接使用静态内容,需要通过外部类对象调用外部类成员
使用:
外部类.内部类 名 = new 外部类.内部类();
局部内部类:
定义在局部位置
局部内部类可以定义成员内容,不可以定义静态内容,除了静态常量
只能在局部内部类所在的方法中通过对象访问成员
如果在局部内部类中使用所在方法中局部(参数),要求局部变量被fianl修饰
如果在jdk1.8只会版本默认被final修饰
public class InnerClass {
static int j = 10;
int i = 1;
class Inner{
int i= 2;
public void method(){
int i = 3;
//调用外部类成员变量
System.out.println(InnerClass.this.i);
//调用内部类成员变量
System.out.println(this.i);
//调用局部变量
System.out.println(i);
}
}
int b = 4;
public void method(){
final int i = 4;
class LocalInner{
int a = 10;
public void method(){
System.out.println(i);
System.out.println(a++);
System.out.println(b++);
System.out.println("--------------------------------------------------");
}
}
LocalInner localInner = new LocalInner();
LocalInner localInner2 = new LocalInner();
localInner.method();
localInner2.method();
}
运行结果:
对于外部类的成员变量的值,影响的是所有内部类对象
对于调用局部外部类的方法中的局部变量必须定义为常量
***匿名内部类:
作用:简化实现类|子类,没有自己类本身作用的实现类|子类
1.匿名对象:只能在当前位置使用一次
2.引用指向匿名内部类对象
3.匿名内部类对象作为方法的实参
匿名内部类对象:实现类|子列+创建对象 一步搞定创建匿名内部类对象和匿名内部类类体。
new 接口{}接口实现类类体
//1.直接使用
new IntefacePractice() { //new对象+创建类体
@Override
public void abstractMethod() {
}
};
//2.地址指向引用变量
IntefacePractice a = new IntefacePractice() {
@Override
public void abstractMethod() {
}
};
//3.作为实参传递
method(new IntefacePractice() {
@Override
public void abstractMethod() {
}
});
}
理解:
匿名内部类理解起来是比较抽象的,他通过直接new接口 + 实现类类体,创建一个匿名实现类对象,我们可以通过我们既然通过接口实例化对象,我们就需要对这个接口的抽象方法进行一个补全操作。
内部类编译后的字节码文件 外部类$内部类
3.lamba表达式
作用:简化匿名实现类对象
- 前提:函数式接口(这个接口只有一个必须被重写的抽象方法)
- 强制检查是否为函数式接口:@FunctionalInterface
- 语法:
1. ()->{}() : 接口中抽象方法的参数列表
-> : lambda符号|箭头函数
{}:重写的方法体
2.如果方法体语句只有一句,前后的{}可以省略
3. 如果方法存在参数,参数的类型可以省略
4.如果参数只有一个,前面的括号可以省略
5.如果lambda语句只有一句,前后的{}与return关键字可以一起省
@FunctionalInterface //强制检查该接口是不是函数式接口
public interface LambdaTest {
public void abstractMethod();
}
@FunctionalInterface //强制检查该接口是不是函数式接口
interface LambdaTest2 {
public void abstractMethod(int a);
}
interface LambdaTest3 {
public int abstractMethod(int a);
}
class TestLambda{
public static void main(String[] args) {
// 正常写法
LambdaTest lambdaTest = ()->{
System.out.println();
};
//只有一条语句时
LambdaTest lambdaTest2 = ()-> System.out.println();
//不需要写形参类型 会自动推断
LambdaTest2 lambdaTest3 = (a)-> System.out.println();
//只有一个参数时 可以不用写小括号
LambdaTest2 lambdaTest4 = a-> System.out.println();
//有返回值 但只有一条语句时
LambdaTest3 lambdaTest5 = a-> a;
}
}