Java OOP(面向对象编程):
- 类(Class):类是对象的模板或蓝图。它定义了一组属性(变量)和一组方法(函数),这些属性和方法可以被类的对象共享。
- 对象(Object):对象是类的实例。每个对象都有其独特的属性值。通过类创建的每个对象都共享该类的属性和方法。
- 封装(Encapsulation):封装是OOP的一个重要概念,它通过将数据(变量)和操作数据的函数捆绑在一起,隐藏对象的内部实现细节,只通过对象的方法来访问这些数据。这有助于保护数据不被外部代码随意修改,提高了数据的安全性和软件的健壮性。
- 继承(Inheritance):继承是从已有的类派生出一个新类。新类(子类)继承了父类(基类)的所有属性和方法,并且可以添加或覆盖父类的行为以定制自己的特性。这提供了代码的重用性,并且允许你构建一个层次结构的类,体现了“is a”的关系。
- 多态(Polymorphism):多态是指一个接口可以有多种实现方式,或者父类引用可以指向子类对象。它允许你使用一个接口或超类来引用不同类型的对象,这样就可以编写不依赖于具体实现而只依赖于接口或超类的代码。这增加了代码的灵活性和可扩展性。
- 抽象(Abstraction):抽象是通过隐藏某些细节来简化复杂事物的过程。在Java中,你可以定义抽象类和抽象方法来创建抽象层,让子类去实现具体的细节。抽象可以帮助你定义接口和规范,让子类按照规定的方式来扩展父类的功能。
- 接口(Interface):接口是一种完全抽象的类,它定义了一组方法,但不需要实现这些方法。任何类可以实现一个或多个接口,并且必须提供接口中定义的所有方法的实现。接口常用于定义一组类应该如何交互,而不需要指定具体的实现细节。
- 重载(Overloading)和重写(Overriding):重载是指在同一类中,方法名相同但参数列表(参数类型、数量、顺序)不同的方法。重载可以提高代码的可读性,因为相同的操作可以有不同的名称。重写是指在子类中定义一个与父类中同名同参数的方法,以覆盖父类中的实现。重写是实现多态的一种方式,子类可以根据需要提供不同的实现。
- 静态变量和静态方法:静态变量是属于类而不是实例的变量,所有实例共享同一个静态变量。静态方法也不需要对象就可以调用,通常用于定义与类相关而不是与特定对象相关的方法。
- 关键字:Java OOP中还有一些重要的关键字,如
this
、super
、final
、null
等,它们在面向对象编程中扮演着重要的角色。
1.类(Class):类是对象的模板或蓝图。
public class Person {
// 属性
String name;
int age;
// 方法
void introduce() {
System.out.println("Hello, my name is " + name + " and I'm " + age + " years old.");
}
}
2.对象(Object):对象是类的实例。
public class Main {
public static void main(String[] args) {
// 创建一个Person对象(对象是类的实例)
Person person = new Person();
person.name = "Alice";
person.age = 25;
person.introduce(); // 输出: Hello, my name is Alice and I'm 25 years old.
}
}
3.封装(Encapsulation):将数据(变量)和操作数据的函数捆绑在一起,隐藏对象的内部实现细节,只通过对象的方法来访问这些数据
封装主要体现在类的属性和方法被隐藏在类的内部,外部只能通过对象的方法来访问这些属性。例如:
public class Person {
private String name; // 私有属性,只能在类内部访问
private int age; // 私有属性,只能在类内部访问
public void setName(String name) { // 公有方法,外部可以通过对象来访问和修改name属性
this.name = name;
}
public void setAge(int age) { // 公有方法,外部可以通过对象来访问和修改age属性
this.age = age;
}
}
4.继承(Inheritance):继承是从已有的类派生出一个新类
继承允许创建一个新类,继承另一个类的属性和方法。子类可以添加新的属性或覆盖父类的方法。例如:
public class Animal {
String name;
public void eat() {
System.out.println(name + " is eating.");
}
}
public class Dog extends Animal { // Dog类继承了Animal类
public void bark() { // Dog类有自己的方法bark()
System.out.println("Woof!");
}
}
5.多态(Polymorphism):多态是指一个接口可以有多种实现方式,或者父类引用可以指向子类对象
多态允许一个接口或超类的引用指向任何实现了该接口或继承了该超类的子类的对象。例如:
eg1:
interface Animal {
void makeSound(); // 接口方法,可以被实现类自定义实现方式
}
class Dog implements Animal { // Dog类实现了Animal接口,并提供了makeSound()的实现方式
public void makeSound() { // Dog类自定义了makeSound()的实现方式为“Woof!”
System.out.println("Woof!"); // 输出: Woof!
}
}
eg2:
class Animal {
public void makeSound() {
System.out.println("Generic animal sound");
}
}
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Woof!");
}
}
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Meow!");
}
}
public class Main {
public static void main(String[] args) {
Animal animal; // 声明一个Animal类型的引用变量
animal = new Animal(); // 创建一个Animal对象并赋值给animal引用变量
//这两行等同于Animal animal = new Animal();
animal.makeSound(); // 输出: Generic animal sound
animal = new Dog(); // 创建一个Dog对象并赋值给animal引用变量,因为animal是父类引用,可以指向子类对象
animal.makeSound(); // 输出: Woof!
animal = new Cat(); // 创建一个Cat对象并赋值给animal引用变量,同样animal是父类引用,可以指向子类对象
animal.makeSound(); // 输出: Meow!
}
}
6.抽象(Abstraction):抽象可以帮助你定义接口和规范,让子类按照规定的方式来扩展父类的功能
抽象是通过定义抽象类或抽象方法来隐藏某些细节的过程。例如:
abstract class Vehicle { // 抽象类,不能直接实例化
abstract void startEngine(); // 抽象方法,子类必须提供实现
}
class Car extends Vehicle { // Car类继承了抽象类Vehicle
public void startEngine() { // Car类提供了startEngine()的具体实现
System.out.println("Car's engine started."); // 输出: Car's engine started.
}
}
7.接口(Interface):接口是一种完全抽象的类
接口是一种完全抽象的类,它定义了一组方法,但不需要实现这些方法。任何类可以实现一个或多个接口,并且必须提供接口中定义的所有方法的实现。例如:
interface Speakable { // 定义了一个接口Speakable
void speak(); // 接口中的方法,必须由实现类提供具体实现
}
class Dog implements Speakable { // Dog类实现了Speakable接口,并提供了speak()的实现方式
public void speak() { // Dog类提供了speak()的具体实现,输出“Woof!”
System.out.println("Woof!"); // 输出: Woof!
}
}
8.重载(Overloading)和重写(Overriding)
重载是在同一个类中,方法名相同但参数列表不同的方法例如。
class Calculator {
int add(int a, int b) { // 普通方法add(),接收两个int参数
return a + b;
}
double add(double a, double b) { // 重载方法add(),接收两个double参数
return a + b;
}
}
重写是在子类中定义一个与父类中同名同参数的方法,以覆盖父类中的实现。例如:
(子类重写父类的方法:)
class AdvancedCalculator extends Calculator {
@Override // 使用@Override注解表明这是一个重写的方法
int add(int a, int b) { // 重写父类的add()方法,返回值类型和参数类型都与父类一致
return a * b; // 输出结果:20(4 * 5 = 20)
}
}
9.静态变量和静态方法
静态变量
静态变量也称为类变量,因为它们属于类本身,而不是类的任何特定实例。这意味着无论创建了多少个类的实例,都只有一个静态变量的副本。所有实例共享同一个静态变量。
public class MyClass {
// 静态变量
public static int staticVariable;
public static void main(String[] args) {
MyClass obj1 = new MyClass();
MyClass obj2 = new MyClass();
obj1.staticVariable = 10; // 设置 obj1 的 staticVariable 值为 10
obj2.staticVariable = 20; // 设置 obj2 的 staticVariable 值为 20
System.out.println("obj1's staticVariable: " + obj1.staticVariable); // 输出 10,因为 obj1 和 obj2 共享同一个 staticVariable
System.out.println("obj2's staticVariable: " + obj2.staticVariable); // 输出 20
}
}
静态方法
静态方法也称为类方法,因为它们属于类本身,而不是类的任何特定实例。这意味着您可以在没有创建类的实例的情况下调用静态方法。
public class MyClass {
// 静态方法
public static void staticMethod() {
System.out.println("This is a static method.");
}
public static void main(String[] args) {
// 调用静态方法,不需要创建类的实例
MyClass.staticMethod(); // 输出 "This is a static method."
}
}
总结:
总结:静态变量和静态方法都属于类,而不是类的实例。这意味着无论创建了多少个类的实例,都只有一个静态变量和一个静态方法的副本。通过使用静态变量和静态方法,可以方便地在不创建对象的情况下与类交互。
10.补充:
10.1)抽象类和实现接口的区别异同:
抽象类(Abstract Class)和接口(Interface)都是面向对象编程中的重要概念,它们都可以用来实现多态,但它们之间存在一些重要的区别。
相同点:
- 两者都支持多态:通过子类继承抽象类或实现接口,可以实现多态。
- 两者都定义规范:抽象类和接口都可以定义规范,规定子类必须实现的方法。
不同点:
- 定义方式:抽象类是一个不完全的类,可以包含具体方法和变量;而接口是一个完全抽象的类,只包含抽象方法和常量。
- 继承方式:一个类只能继承一个抽象类,但可以实现多个接口。
- 方法实现:抽象类可以有具体的方法实现,而接口只能定义方法声明。
- 访问修饰符:抽象类可以包含公有、受保护、默认(包级别)和私有成员,而接口只能包含公有成员。
- 常量:抽象类可以有常量,而接口不能有常量。
- 实例化对象:不能直接实例化抽象类,但可以实例化实现了接口的类。
- 包含抽象方法:抽象类可以有抽象方法,也可以有具体方法;而接口只能有抽象方法。
- 子类与父类关系:如果一个类继承了一个抽象类,那么它必须实现父类的所有抽象方法;如果一个类实现了接口,那么它必须实现接口中定义的所有方法。
- 设计目的:抽象类的设计目的是为了创建一个通用的类,它可以包含一些通用的属性和方法,同时也可以包含一些特定的属性和方法;而接口的设计目的是为了创建一个通用的规范,它只包含一些通用的方法,而不包含任何具体的实现。
10.2)接口与抽象类的关系:
相同点:
- 两者都位于继承树的顶端,用于被其他的类实现和继承。
- 两者都可以包含抽象方法,实现接口或是继承抽象类的普通子类都必须实现这些抽象方法。
- 抽象类和接口都可以定义静态常量。
不同点:
- 接口中的方法都是抽象方法,而抽象类中的方法可以为抽象的,也可以为非抽象的(抽象方法一定要放在抽象类中,但抽象类中不一定含有抽象方法)。
- 接口必须通过实现来完成,而抽象类是通过继承来完成的。
- 类与类之间是继承关系,类与接口之间是实现关系。
- 一个类最多只能有一个直接父类,包括抽象类;但是一个类可以直接实现多个接口,通过实现多个接口可以弥补Java中的单继承的不足。
- 抽象类定义的是一类事物的基本功能,而接口定义了事物的扩展功能。
- 普通类可以实现多个接口,但是只能单继承一个抽象类;抽象类可以实现多个接口,但是只能单继承一个类(普通类、抽象均可)。接口可以继承多个接口,但是不能继承类(普通类、抽象均不可)。
- 抽象类可以有构造方法、普通成员变量、非抽象的普通方法,而接口中不能有构造方法、普通成员变量,只可以有抽象方法和常量。
- 接口里面的抽象方法的访问类型只能是public和默认类型(public abstract),而抽象类中的抽象方法的访问类型可以是public、protected和(默认类型)。
11.二十七个Java常见关键字
1)public:
用于声明一个成员(变量、方法、类等)为公共的,可以在任何地方被访问。
public class MyClass {
public int myVariable; // 公共变量
public void myMethod() { // 公共方法
// 代码
}
}
2)private:
用于声明一个成员为私有的,只能在当前类中被访问。
class MyClass {
private int myVariable; // 私有变量
private void myMethod() { // 私有方法
// 代码
}
}
3)protected:
用于声明一个成员为保护的,可以在当前包内的其他类或不同包中的子类中被访问。
protected class MyClass {
protected int myVariable; // 保护变量
protected void myMethod() { // 保护方法
// 代码
}
}
4)default
(没有标识符):用于声明一个成员为默认的,只能在当前包中的类中被访问。
class MyClass {
int myVariable; // 默认变量
void myMethod() { // 默认方法
// 代码
}
}
5)void:
用于声明一个方法不返回任何值。
void myMethod() { // 不返回任何值的方法
// 代码
}
6)class
:用于声明一个类。类是对象的模板,定义了对象的属性和方法。
class MyClass { // 类声明
// 成员变量和方法定义等
}
7)interface:
用于声明一个接口,定义了一组方法的规范,实现该接口的类必须实现这些方法。接口可以被继承或实现。
public interface MyInterface {
void myMethod(); // 定义一个没有实现的方法
}
public class MyClass implements MyInterface {
public void myMethod() {
System.out.println("MyClass implements MyInterface");
}
}
8)abstract
:用于声明一个抽象类或抽象方法。抽象类不能被实例化,而抽象方法必须在实现该接口的类中被实现。
abstract class MyAbstractClass { // 抽象类声明
// 抽象方法或非抽象方法定义等
}
abstract void myAbstractMethod(); // 抽象方法声明
9)final
:用于声明一个常量、方法或类为最终的,不能被修改或继承。
final int MY_CONSTANT = 10; // 最终常量
final void myFinalMethod() { // 最终方法,不能被子类覆盖
// 代码
}
final class MyFinalClass { // 最终类,不能被继承
// 成员变量和方法定义等
}
10)boolean
:用于声明一个布尔变量,只能取值为 true
或 false
。
boolean isTrue = true; // 布尔变量声明和初始化
11)if
、else
、switch
、case
、default
:用于控制程序流程的语句。
if (condition) { // 如果条件为真,执行语句块
// 代码
} else { // 如果条件为假,执行语句块
// 代码
}
switch (variable) { // 根据变量的值执行相应的代码块
case value1:
// 代码块1
break;
case value2:
// 代码块2
break;
default: // 如果变量值不匹配任何case,执行默认代码块
// 代码块3
break;
}
12)while
、do-while
、for
、break
、continue
:用于循环控制的语句。
while (condition) { // 当条件为真时,重复执行语句块
// 代码
}
do { // 重复执行语句块,直到条件为假
// 代码
} while (condition);
for (initialization; condition; update) { // 初始化,当条件为真时重复执行语句块,然后更新
// 代码
}
break; // 跳出当前循环或switch语句
continue; // 跳过当前循环的剩余部分,进入下一次循环
13)try
、catch
、throw
、finally
:用于异常处理的语句。
try { // 尝试执行代码块,如果抛出异常,则执行相应的catch块或finally块
// 代码
} catch (ExceptionType1 e) { // 捕获特定类型的异常并处理它
// 处理代码
} catch (ExceptionType2 e) { // 可以有多个catch块来处理不同类型的异常
// 处理代码
} finally { // 无论是否发生异常,都会执行finally块中的代码
// 代码
}
14)new
:用于创建对象实例的运算符。
MyClass obj = new MyClass(); // 创建MyClass类的对象实例,并将其引用赋值给obj变量
15)this
:在类的方法或构造器中,this
关键字用于引用当前对象实例。
public class MyClass {
int myVariable;
public void myMethod() {
this.myVariable = 10; // 使用this来引用当前对象的myVariable属性
}
}
16)super
:在类的方法或构造器中,super
关键字用于引用当前对象的父类实例。
public class MySubClass extends MySuperClass {
public void myMethod() {
super.myVariable = 10; // 使用super来引用父类实例的myVariable属性
}
}
17)static
:用于声明静态变量、静态方法或静态块。静态变量和静态方法属于类而不是实例,所有实例共享同一个静态变量,调用静态方法不需要创建对象实例。
public class MyClass {
static int staticVariable; // 静态变量
static void staticMethod() { // 静态方法
// 代码
}
}
18)const
(仅适用于接口中的字段):用于在接口中声明常量。常量的值不能被修改。
interface MyInterface {
const int MY_CONSTANT = 10; // 常量声明
}
19)final
:还可以用于修饰变量,使其成为常量,并且不能被修改。常用于定义配置参数或魔法数字。
final int MY_CONSTANT = 10; // 常量声明和初始化
20)null
:用于表示一个空引用,即没有引用任何对象。
Object obj = null; // 将引用设置为null
21)return
:用于从方法中返回值。
int add(int a, int b) {
return a + b; // 返回两个整数的和
}
22)throw
:用于抛出一个异常。
throw new Exception("异常信息"); // 抛出一个新的异常
23)try-with-resources
:用于自动关闭实现了AutoCloseable
接口的资源。
try (Resource resource) { // 使用try-with-resources语句自动关闭资源
// 使用资源的代码
} catch (Exception e) { // 处理异常的代码
}
24)synchronized
:用于标记一段代码,一次只允许一个线程访问该代码。
public void synchronized myMethod() { // 同步方法,一次只允许一个线程访问该方法
// 代码
}
public void myOtherMethod() {
synchronized(this) { // 同步块,使用对象作为锁
// 代码
}
}
25)volatile
:用于标记一个变量,确保该变量的修改对所有线程都是可见的。
public class MyClass {
volatile boolean flag = false; // 标记为volatile的变量
}
26)assert
:用于在开发和测试阶段进行断言检查。如果条件为假,则抛出AssertionError
异常。
assert condition : "断言失败"; // 如果condition为假,则抛出AssertionError异常
27)enum
:用于声明一个枚举类型,包含固定数量的常量值。
public enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}
public void synchronized myMethod() { // 同步方法,一次只允许一个线程访问该方法
// 代码
}
public void myOtherMethod() {
synchronized(this) { // 同步块,使用对象作为锁
// 代码
}
}