1. 三大特性
1.1 封装
Java 的封装特性是面向对象编程(OOP)的核心之一,其核心理念是将数据(属性)和操作这些数据的方法(行为)封装在一个类中,并通过访问控制限制对数据的直接访问,确保对象的内部状态受到保护。
1.1.1 封装核心概念
数据隐藏(Data Hiding)
通过将类的属性声明为 private
,限制外部直接访问。提供 public
的方法(如 getter 和 setter)来控制对属性的访问和修改。隐藏对象内部实现细节,仅暴露必要的接口,提升代码安全性和灵活性。
访问控制(Access control)
使用访问修饰符控制类成员的可见性。private:仅在类内部可访问。protected:在类内部及子类、同一包中可访问。public:对所有类都可访问。默认(包访问权限):仅在同一包内可访问。
只暴露必要的功能
提供明确的接口,防止外部随意修改类的内部实现。通过方法限制对数据的非法或不合理操作。
1.1.2 封装的实现步骤
1. 将类的属性设为private。
2. 提供 public 的 getter 和 setter 方法,用于读取和修改属性值。
3. 在 setter 方法中加入数据验证逻辑,确保数据的有效性。
示例代码
public class Person {
// 私有属性
private String name;
private int age;
// 公共的 getter 方法
public String getName() {
return name;
}
// 公共的 setter 方法
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
// 在 setter 中添加数据校验
public void setAge(int age) {
if (age >= 0 && age <= 150) {
this.age = age;
} else {
System.out.println("年龄必须在 0 到 150 之间");
}
}
}
public class Main {
public static void main(String[] args) {
Person person = new Person();
person.setName("Fiona");
person.setAge(22);
System.out.println("姓名: " + person.getName());
System.out.println("年龄: " + person.getAge());
// 尝试设置非法年龄
person.setAge(-5); // 输出:年龄必须在 0 到 150 之间
}
}
1.1.3 封装的优点
①数据安全性
• 防止外部代码直接访问或修改对象的私有属性。
• 提供验证机制(如 setter 方法)以确保数据的有效性。
②代码灵活性
• 对象的内部实现可以随时更改,而不影响外部代码。
• 用户通过公共接口与对象交互,减少对具体实现的依赖。
③提高可维护性
• 将属性和行为绑定在一个类中,逻辑清晰,易于维护。
④模块化
• 每个类封装自己的数据和逻辑,减少代码之间的耦合性。
1.1.4 封装中的注意事项
①适当的访问权限控制
• 并非所有属性都需要设置为 private,根据实际情况决定访问级别。
②滥用 getter 和 setter
•不要将所有属性都直接暴露给外界。
• 考虑是否需要对属性添加访问限制或业务逻辑。
③组合封装与继承
• 封装和继承需要配合使用,避免将所有细节暴露给子类。
封装通过隐藏内部实现细节并仅暴露必要的接口,提高了数据的安全性、代码的灵活性和可维护性。在 Java 中,封装主要通过 private 关键字、getter 和 setter 方法以及访问控制修饰符实现。
1.2 继承
Java 的继承特性是面向对象编程(OOP)的核心概念之一,它允许一个类从另一个类继承属性和方法,从而实现代码的重用和扩展。
1.2.1 继承的定义
继承是指一个类(子类或派生类)继承另一个类(父类或基类)的属性和方法。
• 关键词:extends
• 子类不仅能继承父类的所有非私有属性和方法,还可以重写或新增方法以实现自己的特性。
示例代码
// 父类
class Animal {
String name;
void eat() {
System.out.println(name + " is eating.");
}
void sleep() {
System.out.println(name + " is sleeping.");
}
}
// 子类
class Cat extends Animal {
void play() {
System.out.println(name + " is playing.");
}
}
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.name = "MiMi";
cat.eat(); // 从父类继承的方法
cat.sleep(); // 从父类继承的方法
cat.play(); // 子类自己的方法
}
}
输出
MiMi is eating.
MiMi is sleeping.
MiMi is playing.
1.2.2 继承的关键特性
①单继承
• Java 中的类只支持单继承,一个类只能继承一个父类。
• 例如:class Child extends Parent
②super
关键字
• 用于调用父类的构造方法或方法。
• 可以显式调用父类的属性或方法,避免子类覆盖的方法干扰。
示例代码
class Animal {
void eat() {
System.out.println("Animal is eating.");
}
}
class Dog extends Animal {
void eat() {
System.out.println("Dog is eating.");
}
void callParentEat() {
super.eat(); // 调用父类的方法
}
}
③构造器的继承
• 子类的构造方法默认会调用父类的无参构造方法。
• 如果父类没有无参构造方法,子类必须显式调用父类的有参构造方法。
④方法重写(Overriding)
• 子类可以重写父类的方法以实现自己的行为。
• 重写的方法需具有相同的名称、返回值类型和参数列表。
• @Override
注解用于标识重写,便于编译器检查。
⑤继承的访问控制
• 子类可以访问父类的 public
和 protected
成员,不能直接访问 private
成员。
• 如果子类和父类在同一包中,还可以访问默认成员(包访问权限)。
⑥最终类与方法
• 使用 final
关键字修饰的类不能被继承。
• 使用 final
修饰的方法不能被子类重写。
1.2.3 继承的优点
①代码复用性
• 子类可以直接复用父类的代码,无需重复编写相同逻辑。
②代码扩展性
• 子类可以在父类的基础上扩展新功能。
③提高维护性
• 通过继承实现公共功能的抽象,使代码更易于维护。
④实现多态
• 父类引用可以指向子类对象,从而实现动态绑定。
1.2.4 继承的限制与注意事项
①单继承限制
• Java 不支持多继承,但可以通过实现多个接口来实现类似效果。
②父类的依赖
• 子类的实现依赖于父类,可能会导致父类修改时对子类产生较大影响。
③构造器调用限制
• 子类的构造方法必须调用父类的构造方法,且必须是第一行代码。
④过度继承问题
• 继承层次过深可能导致代码难以理解和维护。
• 可以考虑使用组合(Composition)代替继承。
1.2.5 继承与组合的比较
示例:继承与多态的结合
class Animal {
void sound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override
void sound() {
System.out.println("Dog barks");
}
}
class Cat extends Animal {
@Override
void sound() {
System.out.println("Cat meows");
}
}
public class Main {
public static void main(String[] args) {
Animal myAnimal; // 父类引用
myAnimal = new Dog(); // 子类对象
myAnimal.sound(); // 输出:Dog barks
myAnimal = new Cat(); // 子类对象
myAnimal.sound(); // 输出:Cat meows
}
}
继承是 Java 的三大特性之一,它允许子类重用父类的代码,同时支持方法重写和多态特性。虽然继承提高了代码复用性和扩展性,但也需要注意合理设计继承层次,避免产生过强的耦合和维护成本过高的问题。在实际开发中,可以根据需求选择继承或组合实现代码复用和扩展。
1.3 多态
多态(Polymorphism)是面向对象编程(OOP)的三大特性之一,指同一个接口在不同对象中可以有不同的实现。多态可以提高代码的灵活性、可扩展性和可维护性。
1.3.1 多态的基本概念
①编译时多态(静态绑定)
• 通过方法重载(Method Overloading)实现。
• 方法的调用在编译时决定。
②运行时多态(动态绑定)
• 通过方法重写(Method Overriding)实现。
• 方法的调用在运行时根据实际对象类型决定。
1.3.2 编译时多态(方法重载)
• 同一个类中,方法名称相同,但参数列表不同(参数的个数或类型不同)。
• 编译器根据方法签名确定调用哪个方法。
示例代码:方法重载
class Calculator {
// 重载方法:add
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
int add(int a, int b, int c) {
return a + b + c;
}
}
public class Main {
public static void main(String[] args) {
Calculator calculator = new Calculator();
System.out.println(calculator.add(1, 2)); // 输出:3
System.out.println(calculator.add(1.5, 2.5)); // 输出:4.0
System.out.println(calculator.add(1, 2, 3)); // 输出:6
}
}
1.3.3 运行时多态(方法重写)
• 定义:子类通过重写父类方法,实现不同的行为。
• 特点:必须有继承关系;使用父类引用指向子类对象;方法调用在运行时根据对象实际类型动态绑定。
示例代码:方法重写与多态
class Animal {
void sound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override
void sound() {
System.out.println("Dog barks");
}
}
class Cat extends Animal {
@Override
void sound() {
System.out.println("Cat meows");
}
}
public class Main {
public static void main(String[] args) {
Animal myAnimal; // 父类引用
myAnimal = new Dog(); // 指向 Dog 对象
myAnimal.sound(); // 输出:Dog barks
myAnimal = new Cat(); // 指向 Cat 对象
myAnimal.sound(); // 输出:Cat meows
}
}
1.3.4 多态的优点
①灵活性
• 可以针对父类编写通用代码,通过多态机制执行子类的特定实现。
②可扩展性
• 新增子类时,不需要修改父类代码,只需实现或重写方法。
③代码复用
• 可以重用父类代码,提高开发效率。
⑤接口统一性
• 不同子类实现相同接口,调用时不需关心具体实现。
1.3.5 多态的应用场景
①统一接口操作
• 通过父类引用或接口操作多种子类实例。
②抽象类和接口
• 定义一组行为规范,不同类可以根据需求实现这些行为。
示例:接口的多态
interface Shape {
void draw();
}
class Circle implements Shape {
@Override
public void draw() {
System.out.println("Drawing a Circle");
}
}
class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Drawing a Rectangle");
}
}
public class Main {
public static void main(String[] args) {
Shape shape; // 接口引用
shape = new Circle();
shape.draw(); // 输出:Drawing a Circle
shape = new Rectangle();
shape.draw(); // 输出:Drawing a Rectangle
}
}
1.3.6 注意事项
①多态的前提
• 必须有继承关系。
• 必须有方法重写。
②父类引用只能调用父类定义的方法
• 即使子类有额外方法,父类引用也无法直接访问。
• 解决方案:类型转换。
Dog dog = new Dog();
Animal animal = dog;
((Dog) animal).bark(); // 调用 Dog 的特有方法
③静态方法和多态
• 静态方法不能被重写,因此不支持运行时多态。
④构造方法不支持多态
• 构造方法不能被继承,也不参与多态。
Java 的多态包括编译时多态(方法重载)和运行时多态(方法重写),是面向对象编程的核心特性之一。通过多态,代码可以具有更高的灵活性、可扩展性和可维护性,广泛应用于接口、抽象类、框架设计等场景。
2. 关键术语
2.1 简单性(Simplicity)
• Java 的语法简洁直观,去除了 C++ 中复杂的特性(如指针、多重继承、显式内存管理)。
• 更容易学习和使用,尤其对初学者友好。
2.2 面向对象(Object-Oriented)
• Java 是一种完全面向对象的编程语言,支持类、对象、继承、封装、多态和抽象等 OOP 特性。
• 一切操作围绕对象展开,提高代码的可重用性和可扩展性。
2.3 分布式(Distributed)
• Java 提供了对分布式计算的支持,可以使用网络协议(如 HTTP 和 FTP)实现分布式系统。
• 内置的 RMI(远程方法调用) 和 EJB(企业 Java Bean) 等技术帮助开发分布式应用。
2.4 健壮性(Robustness)
• Java 提供了强大的内存管理机制(如垃圾回收器),减少了内存泄漏的可能性。
• 拥有异常处理机制(try-catch-finally
),提高程序的容错性。
• 去除了指针操作,避免因指针错误导致的程序崩溃。
2.5 安全性(Security)
• 字节码验证器:确保字节码的安全性和合法性。
• 类加载器:防止恶意类的加载。
• 沙箱模型:限制未授权代码的执行范围。
• 被广泛用于网络和企业级应用的开发。
2.6 体系结构中立(Architecture-Neutral)
• Java 的编译器生成的字节码(.class
文件)与平台无关,可以在任何安装了 JVM 的平台上运行。
• 确保应用程序能够在不同硬件或操作系统上保持一致的行为。
2.7 可移植性(Portability)
• Java 应用程序只需编译一次,就可以在任何支持 JVM 的设备上运行(“一次编译,到处运行”)。
• 通过屏蔽平台的差异(如文件系统和内存管理)提高可移植性。
2.8 解释型(Interpreted)
• Java 的字节码由 JVM 解释执行,不需要重新编译。
• 提供即时编译(JIT)功能,进一步提升执行效率。
2.9 高性能(High Performance)
• Java 使用即时编译器(JIT)优化字节码的执行速度。
• 虽然比纯静态编译语言稍慢,但得益于改进的 JVM 和优化算法,Java 性能已接近原生代码。
2.10 多线程(Multithreading)
• Java 原生支持多线程,允许同时执行多个任务(如后台任务、用户界面操作等)。
• 提供了丰富的多线程 API,如 Thread
类和 Runnable
接口。
• 提升应用程序的并发性能,广泛用于服务器和高性能计算场景。
2.11 动态性(Dynamic)
• Java 支持动态加载类,允许在运行时决定需要加载的类和对象。
• 支持反射(Reflection),可以在运行时分析类、方法和字段。
• 动态绑定(Dynamic Binding)允许在运行时决定方法的调用,实现更高的灵活性。