写在开头
本系列内容主要涵盖我在深入学习Java过程中对一些知识点的深入理解和巩固。如果内容表达不准确或存在谬误,欢迎在评论区或私信中进行补充或指正~
目录
本篇内容旨在重新学习和加深印象关于Java接口、包、类的内容。为便于记忆,本文内容稍有简化。
Java接口、内部类、包
接口可以继承吗?
可以。甚至可以多继承。
public interface MyInterface3 extends MyInterface1, MyInterface2 {
void abstractMethod3();
}
接口继承要重写父接口的方法吗?
- 子接口不需要重写父接口的方法。
- 实现类需要重写所有接口的方法,例:接口B继承接口A,类C实现接口B,则需要实现父接口A和子接口B的方法。
接口中可以实现方法吗?
public interface Person {
void run();
default void eat() {
System.out.println("我是默认的吃方法");
}
}
接口 | 抽象类 |
---|---|
仅有static 、final 变量、方法 | 可有其他变量、方法 |
对行为的抽象,是一种行为的规范 | 对类的抽象,是一种模板设计 |
多个接口中的重名成员解决方法
-
多个接口且父类存在重名默认方法
-
实现类重新声明该方法
-
public interface MyInterface1 {
default void defaultMethod() {
System.out.println("我是MyInterface1接口中的默认方法");
}
}
public interface MyInterface2 {
default void defaultMethod() {
System.out.println("我是MyInterface2接口中的默认方法");
}
}
// 声明父类,并在父类中也定义同名方法
public class SuperClass {
public void defaultMethod() {
System.out.println("我是SuperClass中的defaultMethod()方法");
}
}
// CASE1 实现类重新声明该方法
public class MyClass implements MyInterface1, MyInterface2 {
public void defaultMethod() {
System.out.println("我是重写的默认方法");
}
}
// CASE2 类在继承结构中的优先级高于接口。
public class MyClass extends SuperClass implements MyInterface1, MyInterface2 {
@Override
public void defaultMethod() {
System.out.println("我是MyClass中的defaultMethod()方法");
}
public static void main(String[] args) {
MyClass myClass = new MyClass();
myClass.defaultMethod();
// 如果重写了该方法输出: "我是MyClass中的defaultMethod()方法" if overridden,
// 如果没有重写,调用父类的: "我是SuperClass中的defaultMethod()方法"
}
}
-
多个接口且父类中存在重名常量
使用父类名、接口名限定父类、接口中的常量(或属性)
public interface MyInterface1 {
final int NUM = 100;
}
public interface MyInterface2 {
final int NUM = 200;
}
class SuperClass {
static int NUM = 300;
}
// 明确引用来源
public class MyClass extends SuperClass implements Interface1 {
public void printConstants() {
// 使用父类名限定常量
System.out.println("SuperClass.NUM : " + SuperClass.NUM );
// 使用接口名限定常量
System.out.println("Interface1.NUM : " + Interface1.NUM );
// 使用接口名限定常量
System.out.println("Interface2.NUM : " + Interface2.NUM );
}
关于接口的补充:
- 从 JDK 1.8 开始,接口中可以定义默认和静态方法(可定义方法体)。
- 当一个实现类存在 extends 关键字,那么 implements 关键字应该放在其后。
成员内部类和外部类的属性重名如何调用?
就近原则。
可以使用外部类名.this.成员的方式访问外部属性
public class OuterClass { // 定义外部类
private String name = "外部name"; // 定义外部属性
public class InnerClass { //
private String name = "内部name"; // 定义内部类
public void printNames() {
// 访问内部类的name属性
System.out.println("Inner class name: " + name);
// 访问外部类的name属性
System.out.println("Outer class name: " + OuterClass.this.name);
}
}
匿名内部类的使用情景?
- 实现一个 抽象类或接口时,类的定义可实例化都放到了一起,可以简化代码的编写
- 在代码中只用到类的一个实例、方法只调用一次,可以使用匿名内部类
- 用父类引用来调用匿名内部类的实现
- 需求只是实现父类/接口中某个方法,内部类就可以解决这些问题
public void createAnonymousClass() {
// 匿名内部类
Runnable anonymousClass = new Runnable() {
@Override
public void run() {
System.out.println("匿名内部类重写un方法");
}
};
anonymousClass.run(); //调用
}
关于内部类的补充
含有内部类的类被编译器编译后,会生成两个独立的字节码文件:
内部类 | 外部类 |
---|---|
外部类类名 $ 内部类类名.class | 外部类类名.class |
外部类类名$n.class n为匿名内部类实例序号) |
包的作用?
让类更易于查找和使用,也可以避免命名冲突,还可以控制访问
关于包的补充
- 基础的类在 java.lang 包;
- 用于读写的类在 java.io 包;
- 一些工具类放在 java.util 包;