Java基础之接口与内部类
接 口
一方面,有时必须从几个类中派生出一个子类,继承它们所有的属性和方法。但是,Java不支持多重继承。有了接口,就可以得到多重继承的效果。
另一方面,有时必须从几个类中抽取出一些共同的行为特征,而它们之间又没有is-a的关系,仅仅是具有相同的行为特征而已。例如:鼠标、键盘、打
印机、扫描仪、摄像头、充电器、MP3机、手机、数码相机、移动硬盘等都支持USB连接。
接口就是规范,定义的是一组规则,体现了现实世界中“如果你是/要...则必须能...”的思想。继承是一个"是不是"的关系,而接口实现则是 "能不能"
的关系。
接口的本质是契约,标准,规范,就像我们的法律一样。制定好后大家都要遵守
接口的使用
1.java 中使用interface来定义
2.java 中接口和类是并列的关系
3.如何定义接口,定义接口就是定义接口成员
3.1 JDK7以前:只能定义 全局常量和抽象方法
全局常量:pubic static final的;书写是可以省略
抽象方法:pubic abstract的
JDK8:除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法
4接口不能定义构造器,也就是接口不能实例化
5.java 开发中,接口通过让类实现(implements)的方式来使用
如果实现类覆盖了接口中所有抽象方法,则此实现类可以实例化
如果实现类没有覆盖接口中所有的抽象方法,则此实现类还是一个抽象类
6.java 类可以实现多个接口---->弥补了类的单继承性
格式 calss AA extends BB implement CC,DD{} ---->CC DD 是接口
7.接口与接口之间可以继承而且可以多继承
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | public class InterfaceTest { public static void main(String[] args) { System.out.println(Flyale.MIN_SPEED); System.out.println(Flyale.MAX_SPEED); plane p1 = new plane(); p1.fly(); plane p2 = new plane(); p2.fly(); kite k1 = new kite(); k1.fly(); k1.stop(); } } //接口的定义 interface Flyale{ //全局常量 public static final int MAX_SPEED = 7900 ; //第一宇宙速度 public static final int MIN_SPEED = 1 ; //在接口可以写成int MIN_SPEED =1 //抽象方法 public abstract void fly(); //在接口定义的方法也可以这样写void fly(); //可以省略public abstract public abstract void stop(); //在接口定义的方法也可以这样写void stop() } class plane implements Flyale{ @Override public void fly(){ System.out.println( "通过引擎" ); } @Override public void stop(){ System.out.println( "通过关闭引擎" ); } } class kite implements Flyale{ @Override public void fly(){ System.out.println( "依靠风" ); } @Override public void stop() { System.out.println( "收好风筝线" ); } } |
测试结果
1 2 3 4 5 6 | 1 7900 通过引擎 通过引擎 依靠风 收好风筝线 |
示例2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | public class InterfaceTest { public static void main(String[] args) { System.out.println(Flyale.MIN_SPEED); System.out.println(Flyale.MAX_SPEED); plane p1 = new plane(); p1.fly(); plane p2 = new plane(); p2.fly(); kite k1 = new kite(); k1.fly(); k1.stop(); } } //接口的定义 interface Attackable{ void attackble(); //接口里定义方法 } interface Flyale{ //全局常量 public static final int MAX_SPEED = 7900 ; //第一宇宙速度 public static final int MIN_SPEED = 1 ; //在接口可以写成int MIN_SPEED =1 //抽象方法 public abstract void fly(); //在接口定义的方法也可以这样写void fly(); //可以省略public abstract public abstract void stop(); //在接口定义的方法也可以这样写void stop() } class plane implements Flyale{ @Override public void fly(){ System.out.println( "通过引擎" ); } @Override public void stop(){ System.out.println( "通过关闭引擎" ); } } class kite implements Flyale{ @Override public void fly(){ System.out.println( "依靠风" ); } @Override public void stop() { System.out.println( "收好风筝线" ); } } class Bullet implements Flyale,Attackable{ //一个类可以有多个接口中间使用逗号隔开 @Override public void fly(){ } @Override public void stop(){ } @Override public void attackble(){ } } interface AA{ } interface BB{ } interface CC extends AA,BB{ //接口可以定义多个继承的接口,中间使用,号隔开 } |
Java 8 的心特性
Java 8中,你可以为接口添加静态方法和默认方法。从技术角度来说,这是完全合法的,只是它看起来违反了接口作为一个抽象定义的理念。
静态方法:使用 static 关键字修饰。可以通过接口直接调用静态方法,并执行其方法体。我们经常在相互一起使用的类中使用静态方法。你可以在标准库中
找到像Collection/Collections或者Path/Paths这样成对的接口和类。
默认方法:默认方法使用 default 关键字修饰。可以通过实现类对象来调用。我们在已有的接口中提供新方法的同时,还保持了与旧版本代码的兼容性。
比如:java 8 API中对Collection、List、Comparator等接口提供了丰富的默认方法
JAVA 8的新特性,除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法
定义的静态方法只能通过接口去调
定义的默认方法可以通过对象调
接口定义示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public interface CompareA { //静态方法 public static void method1(){ System.out.println( "北京" ); } //默认方法 public default void method2(){ System.out.println( "上海" ); } //默认方法 default void method3(){ System.out.println( "深圳" ); } } |
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public class SubClassTese { public static void main(String[] args) { SubClass s1 = new SubClass(); //接口定义的静态方法只能通过接口来调用 CompareA.method1(); //默认方法通过对象调 s1.method2(); } } class SubClass implements CompareA{ } 测试结果 北京 上海 |
重写方法
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | package com.chenxi.Java8; public class SubClassTese { public static void main(String[] args) { SubClass s1 = new SubClass(); //接口定义的静态方法只能通过接口来调用 CompareA.method1(); //默认方法通过对象调;如果重写接口方法就是调的重写后的方法 s1.method2(); } } class SubClass implements CompareA{ @Override public void method2() { System.out.println( "杭州" ); } } 测试 北京 杭州 |
如果子类或实现类声明了同名同参的方法,在子类没有重写此方法的情况下;默认去去调父类的方法
如果实现类实现了多个接口,而多个接口有同名同参的默认方法,那么在实现类没有重写此方法的情况下,报错
接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public interface CompareA { //静态方法 public static void method1(){ System.out.println( "北京" ); } //默认方法 public default void method2(){ System.out.println( "上海" ); } //默认方法 default void method3(){ System.out.println( "深圳" ); } } |
父类
1 2 3 4 5 | public class SuperClass { public void method3(){ System.out.println( "云南" ); } } |
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public class SubClassTese { public static void main(String[] args) { SubClass s1 = new SubClass(); //接口定义的静态方法只能通过接口来调用 CompareA.method1(); //默认方法通过对象调 s1.method2(); //如果子类或实现类声明了同名同参的方法,子类没有重写此方法的情况下;默认去调父类的方法 s1.method3(); // } } class SubClass extends SuperClass implements CompareA{ @Override public void method2() { System.out.println( "杭州" ); } } 测试 北京 杭州 云南 |
内部类
当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构最好使用内部类。
在Java中,允许一个类的定义位于另一个类的内部,前者称为内部类,后者、称为外部类。
Inner class一般用在定义它的类或语句块之内,在外部引用它时必须给出完整的名称。
Inner class的名字不能与包含它的外部类类名相同;
分类: 成员内部类(static成员内部类和非static成员内部类)局部内部类(不谈修饰符)、匿名内部类
类的内部类
1.java 允许将一个类A声明在另一个类B中,则A类是内部类,类B外部类
2. 内部类的分类 :成员内部类(静态、非静态)VS 局部内部类(方法内、代码块内、构造器内)
3.成员内部类
作为外部类的成员
调用外部类的属性
可以被4中权限修饰
可以被static 修饰
作为类内部类可以定义属性、方法构造器等
final 修饰 表示不可以被继承
可以被abstract 修饰
关注如下3个问题
如何实例化内部类的对象
如何在成员类中区分调用外部类的结果
局部内类的使用
实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | public class InnerClassTest{ public static void main(String[] args) { //创建Dog 实例(静态的成员内部类) Person.Dog dog = new Person.Dog(); dog.show(); //创建Bird实例(非静态的成员内部类) Person p = new Person(); Person.Bird bird = p. new Bird(); bird.sing(); } } class Person{ String name; public Person(){ //构造器里声明的局部内部类 class es{ } } public void eat(){ System.out.println( "人吃饭" ); } //成员内部类:非静态的成员内部类 class Bird{ String name= "杜鹃" ; public Bird(){ } public void sing(){ System.out.println( "我是一只小小鸟" ); Person. this .eat(); //调用外部类的结构 } public void display(String name){ System.out.println(name); //方法形参 System.out.println( this .name); //内部类的属性 System.out.println(Person. this .name); //外部类的属性 } } |
局部内部类的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | public class InnerClassTest1 { public void method(){ class AA{ } } public Comparable getComparable(){ //创建一个实现Comparable接口的类:局部内部类 //方式1 // class MyComparable implements Comparable{ // @Override // public int compareTo(Object o) { // return 0; // } // } // return new MyComparable(); //方式2匿名类的匿名对象 return new Comparable() { @Override public int compareTo(Object o) { return 0 ; } }; } } |
草都可以从石头缝隙中长出来更可况你呢
分类:
java
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏
2020-04-11 MySQL 函数
2019-04-11 docker存储管理