一、封装
封装是面向对象编程的三个基本特征之一(另外一个是继承,多态),其核心思想是隐藏对象的内部细节,只对外暴露必要的接口或方法,从而保证程序的安全性和可维护性。封装通过访问控制来实现,访问控制分为public、private、protected和默认访问四种。
封装的好处包括:
-
隐藏细节:封装可以将类内部的细节隐藏起来,只对外部提供必要的接口和方法,避免了外部直接访问类内部细节,从而保证了程序的安全性和可维护性。
-
提高可维护性:封装可以减少外部对类内部的影响,使类的修改对外部的影响降到最小,从而提高了程序的可维护性。
-
提高重用性:封装可以将类的实现细节隐藏起来,只对外暴露必要的接口和方法,使得类的实现细节对外不可见,从而提高了类的重用性。
-
提高灵活性:封装可以使得类的实现细节与外部解耦,从而使得类的实现更加灵活和可变。
封装的实现需要使用访问控制修饰符,通过访问控制修饰符来限制类、属性、方法的访问范围,Java中有四种访问控制修饰符:
-
public:公共访问修饰符,可以被任何类访问。
-
private:私有访问修饰符,只能被类内部的方法和属性访问,对外部不可见。
-
protected:受保护的访问修饰符,只能被子类和同一个包中的类访问。
-
默认访问:没有访问修饰符,只能被同一个包中的类访问。
通过访问控制修饰符可以将类内部的属性和方法进行封装,只对外部暴露必要的接口和方法,从而保证了类的安全性和可维护性。
二、defalut
default
是Java 8中新增的关键字,用于在接口中定义默认方法。默认方法是指接口中可以有实现的方法,而不像之前的接口中只能定义抽象方法。默认方法可以通过接口的实现类直接调用,也可以被覆盖重写。在接口中定义默认方法的语法如下:
- 默认方法必须使用
default
关键字修饰,且不能与abstract
同时使用。 - 默认方法可以被覆盖重写,实现类中实现的方法优先级更高。
- 接口的实现类可以选择不重写默认方法,直接使用接口中定义的默认实现。
- 如果一个类继承了多个接口,且这些接口中有相同的默认方法,那么该类必须重写该默认方法来避免歧义。
- 默认方法可以访问接口中定义的常量,但不能访问接口中的实例变量。
- 默认方法可以被其他默认方法调用。
接口中既可以定义抽象方法,也可以定义默认方法。在Java 8之前,接口中只能包含抽象方法。但是随着Java 8中的引入,默认方法成为了接口的一部分。这样就可以在接口中同时定义抽象方法和默认方法了。默认方法在接口中可以提供一个默认的实现,而不需要实现类强制覆盖它。这样可以避免在接口中添加新的抽象方法时,所有的实现类都需要实现新的方法,从而降低了接口的扩展性。再举一个例子:
public interface InterfaceName {
default void defaultMethod() {
System.out.println("This is the default implementation.");
}
}
public class ClassName implements InterfaceName {
@Override
public void defaultMethod() {
System.out.println("This is the custom implementation.");
}
}
在这个示例中,InterfaceName
接口中定义了一个默认方法 defaultMethod()
,它的默认实现是输出一条消息 "This is the default implementation."。然后,ClassName
类实现了这个接口并重写了 defaultMethod()
方法,它的自定义实现是输出一条消息 "This is the custom implementation."。当通过 ClassName
类创建对象并调用 defaultMethod()
方法时,输出的消息将是 "This is the custom implementation.",而不是 "This is the default implementation."。
默认方法的引入,使得接口有了更强的扩展性和向后兼容性,同时也提高了接口的灵活性和可用性。最后举一个例子:
public interface Animal {
void move();
default void eat() {
System.out.println("I can eat");
}
}
public class Cat implements Animal {
@Override
public void move() {
System.out.println("I can walk and run");
}
}
public class Main {
public static void main(String[] args) {
Animal cat = new Cat();
cat.move();
cat.eat();
}
}
在这个例子中,我们定义了一个Animal接口,并声明了两个方法:move()和eat()。由于eat()方法的实现对于实现该接口的所有类都是相同的,因此我们将其定义为default方法。接下来,我们定义了一个Cat类来实现Animal接口,并提供了自己的实现,即move()方法。当我们使用Cat对象调用move()方法时,它会输出"I can walk and run"。当我们使用Cat对象调用eat()方法时,它会输出"I can eat",因为它继承了Animal接口中默认实现的eat()方法。