第二部分主要从接口、内部类进行简要总结。
一、接口
抽象类的特点
-
不能被实例化:抽象类不能直接创建对象。
-
包含抽象方法:可以包含一个或多个抽象方法,这些方法没有具体的实现。
-
被子类实现:任何继承抽象类的子类必须实现(重写)所有抽象方法,否则该子类也必须被声明为抽象类。
-
包含普通方法和属性:可以包含普通方法和属性,这些方法和属性有具体的实现。
接口 interface特点
-
提供形式,未提供任何具体实现方式
-
接口类默认就是public的
-
方法默认是public 抽象的
-
接口实现->implements,可以多实现来实现“多重继承的效果”
接口的使用:接口管理类-》把相关要管理的类都通过实现接口可以实现统一管理,差异大的也可以通过代理实现接口调用,实现代码复用及解耦。我当前的理解使用接口还是为了代码的维护方便,接口相比于继承中的方法重写最大的优点就是解耦,不需要依赖于继承中的具体类,而统一用接口来接收处理相关的业务逻辑。
接口可以多继承(java中类只能单继承)
public interface A {
void methodA();
}
public interface B {
void methodB();
}
public interface C extends A, B {
void methodC();
接口继承的特点
-
方法签名继承:当接口继承另一个接口时,它会继承父接口的所有方法签名(包括抽象方法和默认方法)。
-
默认方法和静态方法:从Java 8开始,接口可以包含默认方法和静态方法。当一个接口继承另一个包含默认或静态方法的接口时,它会自动继承这些方法。
-
灵活性:接口的多继承允许开发者设计出更加模块化和可重用的代码结构。
-
实现细节:当一个类实现一个多继承的接口时,它必须提供所有父接口中声明的方法的实现。
接口常见设计模式:策略模式和适配器模式。
接口中的域
1.接口当中的常量,可以省略public static final,注意:不写也照样是这样。
2.接口当中的常量,必须进行赋值;不能不赋值。
3.接口中常量的名称,使用完全大写的字母,用下划线进行分割。
接口嵌套
接口可以嵌套在类或者其他接口中。
以下是一个特例:
getD()
方法产生了一个private 接口对象,直接使用A对象无法调用此方法,因为返回对象是private的,返回值必须交给有权使用它的对象,这里另一个 A对象 通过 receiveD()
方法接受了它。
class A {
interface B {
void f();
}
private interface D {
void f();
}
public class DImp2 implements D {
@Override
public void f() {}
}
public D getD() {
return new DImp2();
}
private D dRef;
public void receiveD(D d) {
dRef = d;
dRef.f();
}
public static void main(String[] args) {
A a = new A();
// Can't access to A.D:
//- A.D ad = a.getD();
// Doesn't return anything but A.D:
//- A.DImp2 di2 = a.getD();
// cannot access a member of the interface:
//- a.getD().f();
// Only another A can do anything with getD():
A a2 = new A();
a2.receiveD(a.getD());//it's OK
}
}
接口工厂
接口工厂实现步骤:
1.定义通用接口
2.定义工厂接口,方法会获取通用接口对象
3.写一个类实现通用接口
4.写一个类实现工厂接口,并在方法中返回实例化实现类对象。
5.写一个调用工厂类,在此类中定义静态方法供外部调用,方法参数为工厂接口,并在方法中实现具体的调用逻辑。
通过这种方式可以将接口与实现的代码完全分离,使得可以透明地将某个实现替换为另一个实现。
例子:
interface Game {//通用方法接口
boolean move();
}
interface GameFactory {//工厂接口
Game getGame();
}
class Checkers implements Game {//通用方法接口实现类
private int moves = 0;
private static final int MOVES = 3;
@Override
public boolean move() {
System.out.println("Checkers move " + moves);
return ++moves != MOVES;
}
}
class CheckersFactory implements GameFactory {
//工厂实现类,返回Checkers类对象
@Override
public Game getGame() {
return new Checkers();
}
}
//第二个实现类及工厂
class Chess implements Game {
private int moves = 0;
private static final int MOVES = 4;
@Override
public boolean move() {
System.out.println("Chess move " + moves);
return ++moves != MOVES;
}
}
class ChessFactory implements GameFactory {
@Override
public Game getGame() {
return new Chess();
}
}
//这里playGame方法可以传入不同的工厂实现类完成对应方法调用。
public class Games {
public static void playGame(GameFactory factory) {
Game s = factory.getGame();
while (s.move()) {
;
}
}
public static void main(String[] args) {
playGame(new CheckersFactory());
playGame(new ChessFactory());
}
}
第二、内部类
-
内部类创建对象(.new用法):
-
内部类创建:外部类引用对象.new 内部类
-
必须用外部类对象来创建内部类。静态内部类除外
2.内部类的对象它能访问其外围对象的所有成员,内部类还拥有其外围类的所有元素的访问权。
3.使用.this
外部类的名字后面紧跟圆点和 this,生成对外部类对象的引用。
4.内部类向上转型
1.内部类实现接口向上转型与普通的类实现接口向上转型实质效果是一样的
2.之所以使用内部类是因为可以在外部类提供一个获取内部类的方法(内部类实现接口,方法返回接口对象),同时内部类实现了一个接口重写了方法,但设计时不希望内部类的其他方法被调用或者访问可以用此方法。
5.匿名内部类
1.没有名字:匿名内部类是一个没有名字的局部内部类,定义在方法中、代码块中等。
2.即时创建对象:匿名内部类写出来就会产生一个匿名内部类的对象。
3.继承关系:匿名内部类可以继承一个类或实现一个接口,通常用于简化代码编写和创建子类对象。
4.访问外部类成员:匿名内部类可以直接访问外部类的所有成员变量和方法,包括私有的。
5.作用域限制:匿名内部类的作用域仅限于定义它的方法或代码块内。
6.默认包含外部类对象的引用:匿名内部类默认包含了外部类对象的引用。
7.由于内部类没有构造,所以可以通过代码块的方式进行变量的初始化。
6.嵌套类
内部类声明为 static,这通常称为静态嵌套类。
静态嵌套类特点:
-
要创建嵌套类的对象,并不需要其外围类的对象。
-
不能从嵌套类的对象中访问非静态的外围类对象。
静态嵌套类可以使用在接口类中,嵌套类可以作为接口的一部分。你放到接口中的任何类都自动地是 public 和 static 的。
从多层嵌套类中访问外部类的成员:一个内部类被嵌套多少层并不重要——它能透明地访问所有它所嵌入的外围类的所有成员。
7.内部类继承
内部类的继承和普通类有一些不同之处,因为内部类的创建需要外部类的引用,所以在内部类的继承上需要外部类的协助。
public class A {
class CC{
}
}
public class B extends A.CC{
B(A a) {
a.super();
}
public static void main(String[] args) {
A a = new A();
B b = new B(a);
}
}
内部类不可以被覆盖,除非明确继承内部类。
8.局部内部类
局部内部类不能有访问说明符,因为它不是外围类的一部分;
但是它可以访问当前代码块内的常量,以及此外围类的所有成员。
第二部分简要总结到此结束~
希望阅读至此的你有所收获!