Java的三大特性是封装、继承和多态,它们是面向对象编程(OOP)的核心概念,下面分别介绍这三大特性:
一.封装(Encapsulation)
封装是指将对象的属性(字段)和行为(方法)组合成一个独立的单元,并隐藏对象的内部实现细节,只通过定义好的接口(方法)与外界交互。
特点:
-
隐藏内部实现:将类的成员变量(属性)设置为私有(private),防止外部直接访问。
-
提供公共接口:通过公共方法(如 getter 和 setter)来访问和修改私有属性,从而控制对属性的访问权限。
-
提高安全性:封装可以防止外部代码对内部数据的非法访问,确保数据的完整性和安全性。
示例代码:
public class Person {
// 私有属性
private String name;
private int age;
// 提供公共方法访问和修改属性
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age > 0) {
this.age = age;
} else {
System.out.println("年龄不能为负数");
}
}
}
封装的核心修饰词就是private,其限制外部方法访问类中数据,从而达到封装的效果
从图表可以看出,private的具体限制效果
二.继承(Inheritance)
继承是指一个类(子类)可以继承另一个类(父类)的属性和方法。子类继承父类后,可以重写父类的方法,也可以添加新的属性和方法。
特点:
-
代码复用:子类可以直接使用父类的属性和方法,减少重复代码。
-
扩展性:子类可以扩展父类的功能,通过重写父类的方法来实现多态。
-
层次化结构:通过继承可以形成类的层次结构,更符合现实世界的逻辑关系。
示例代码:
// 父类
class Animal {
public void eat() {
System.out.println("动物会吃东西");
}
}
// 子类
class Dog extends Animal {
// 重写父类的方法
@Override
public void eat() {
System.out.println("狗吃骨头");
}
// 添加新的方法
public void bark() {
System.out.println("狗会叫");
}
}
public class TestInheritance {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat(); // 输出:狗吃骨头
dog.bark(); // 输出:狗会叫
}
}
1. 继承的基本概念
继承是一种“**是一种**”(is-a)关系,表示子类是父类的一个特例。例如,`Dog` 是一种 `Animal`,`Car` 是一种 `Vehicle`。这种关系可以用继承来表示。
- **父类(基类)**:被继承的类,提供了通用的属性和方法。
- **子类(派生类)**:继承父类的类,可以扩展父类的功能,添加新的属性和方法,或者重写父类的方法。
---
2. 继承的语法
在 Java 中,使用 `extends` 关键字来实现继承。语法如下:
```java
class ParentClass {
// 父类的属性和方法
}
class ChildClass extends ParentClass {
// 子类的属性和方法
}
```
---
3. 继承的特点
3.1 父类成员的继承规则
- **继承的成员**:子类继承父类的所有非私有成员(包括属性和方法)。如果父类的成员是私有的(`private`),子类无法直接访问,但可以通过父类的公共方法(如 getter 和 setter)间接访问。
- **构造方法**:子类不会继承父类的构造方法,但可以通过 `super()` 调用父类的构造方法来初始化父类部分。
3.2 方法的重写(Override)
子类可以重写父类的方法,以提供特定的实现。重写的方法必须满足以下条件:
- 方法名、参数列表必须与父类被重写的方法完全相同。
- 返回类型必须与父类被重写的方法相同或兼容(协变返回类型)。
- 访问权限不能比父类被重写的方法更严格。
示例:
```java
class Parent {
public void show() {
System.out.println("父类的 show 方法");
}
}
class Child extends Parent {
@Override
public void show() {
System.out.println("子类重写的 show 方法");
}
}
```
3.3 成员变量的隐藏
如果子类定义了一个与父类同名的成员变量,那么子类的成员变量会隐藏父类的成员变量。访问时,需要通过 `super` 关键字来访问父类的成员变量。
示例:
```java
class Parent {
int num = 10;
}
class Child extends Parent {
int num = 20;
public void print() {
System.out.println(num); // 输出子类的 num
System.out.println(super.num); // 输出父类的 num
}
}
```
3.4 构造方法的调用
- 子类的构造方法中默认会调用父类的无参构造方法(通过 `super()`)。
- 如果父类没有无参构造方法,子类必须显式调用父类的某个构造方法(通过 `super()`)。
示例:
```java
class Parent {
Parent(String name) {
System.out.println("父类构造方法:" + name);
}
}
class Child extends Parent {
Child() {
super("Hello"); // 显式调用父类的构造方法
System.out.println("子类构造方法");
}
}
```
---
4. 继承的使用场景
继承主要用于以下场景:
1. **代码复用**:子类可以直接使用父类的属性和方法,减少重复代码。
2. **层次化结构**:通过继承可以形成类的层次结构,更符合现实世界的逻辑关系。例如,`Animal` 类可以作为父类,`Dog`、`Cat` 等作为子类。
3. **扩展功能**:子类可以通过重写父类的方法来扩展功能,或者添加新的属性和方法。
---
5. 继承的限制
- **单继承**:Java 不支持多继承,即一个类只能继承一个父类。但可以通过接口实现多继承的效果。
- **`final` 类**:如果一个类被声明为 `final`,那么它不能被继承。
---
6. 继承的优缺点
1.优点
- **代码复用**:减少重复代码,提高开发效率。
- **层次化结构**:便于理解和维护代码。
- **扩展性**:通过继承和重写,可以灵活地扩展功能。
2.缺点
- **耦合性高**:子类与父类紧密耦合,父类的修改可能影响子类。
- **过度使用**:可能导致类的层次结构过于复杂,增加理解难度。
---
7. 示例代码
下面是一个完整的继承示例,展示如何使用继承、重写方法和调用父类构造方法。
// 父类
class Animal {
private String name;
public Animal(String name) {
this.name = name;
}
public void eat() {
System.out.println(name + " 吃东西");
}
public void sleep() {
System.out.println(name + " 睡觉");
}
}
// 子类
class Dog extends Animal {
public Dog(String name) {
super(name); // 调用父类构造方法
}
// 重写父类的 eat 方法
@Override
public void eat() {
System.out.println(super.name + " 吃骨头");
}
// 添加新的方法
public void bark() {
System.out.println(super.name + " 汪汪叫");
}
}
public class TestInheritance {
public static void main(String[] args) {
Dog dog = new Dog("旺财");
dog.eat(); // 输出:旺财 吃骨头
dog.sleep(); // 输出:旺财 睡觉
dog.bark(); // 输出:旺财 汪汪叫
}
}
8.总结
继承是面向对象编程中一个强大的特性,它允许通过扩展和复用父类的功能来实现子类的特定功能。合理使用继承可以提高代码的可维护性和可扩展性,但需要注意避免过度使用,以免导致类的层次结构过于复杂。
三.多态(Polymorphism)
1.认识多态
多态是指同一个接口或父类使用不同的底层实现对象,在运行时根据对象的实际类型调用对应的方法。多态分为两种:方法重载(编译时多态)和方法覆盖(运行时多态)。
特点:
-
提高代码的灵活性:通过多态,可以使用父类类型的变量引用子类对象,调用方法时会根据实际对象的类型执行对应的方法。
-
增强可扩展性:新增子类时,无需修改原有代码,只需保证子类继承父类并重写方法即可。
示例代码:
// 父类
class Animal {
public void makeSound() {
System.out.println("动物发出声音");
}
}
// 子类1
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("狗叫:汪汪");
}
}
// 子类2
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("猫叫:喵喵");
}
}
public class TestPolymorphism {
public static void main(String[] args) {
Animal animal1 = new Dog();
Animal animal2 = new Cat();
animal1.makeSound(); // 输出:狗叫:汪汪
animal2.makeSound(); // 输出:猫叫:喵喵
}
}
2.多态实现的条件
在认识多态中,必须先认识到几个概念
1.在继承关系的基础上-》向上转型
2.子类与父类有相同的构造方法,变量,参数链接;
3.通过父类对象的引用,去调用这个重写的方法
这三个部分,就可以完成动态绑定,而动态绑定是多态的基础!!!
父类引用指向子类对象:这是运行时多态的基础。
方法覆盖(Override):子类重写父类的方法,运行时根据对象的实际类型调用对应的方法。
动态绑定:虚拟机在运行时根据对象的实际类型来调用方法。
class Parent { public void show() { System.out.println("父类的 show 方法"); } }//父类 class Child extends Parent { @Override//注解 检测错误的一种重要方式 public void show() { System.out.println("子类重写的 show 方法"); } }//子类 public class TestDynamicBinding { public static void main(String[] args) { Parent obj1 = new Parent();//父类show方法 Parent obj2 = new Child();//子类重写show方法 obj1.show(); // 输出:父类的 show 方法 obj2.show(); // 输出:子类重写的 show 方法 } }
四.总结
封装、继承和多态是Java面向对象编程的三大核心特性,它们相辅相成:
-
封装是基础,通过封装隐藏内部细节,提供接口与外界交互。
-
继承是扩展,通过继承实现代码复用和层次化结构。
-
多态是核心,通过多态实现灵活的代码设计和可扩展性。
这三大特性共同构成了面向对象编程的强大能力,使得代码更加模块化、可维护和可扩展。