作为一名实习生,为了夯实基础、查缺补漏,我跟随 B 站学习了以下知识,欲将其留存纪念,故对其中内容进行优化,以使其更为优雅。
面向对象
- 面向对象编程的定义:借助合适的对象来解决问题(如运用 scanner 库进行输入)。
- 运用面向对象编程的缘由:更契合人类的思维模式,使程序代码更易于理解。
- 面向对象的核心要点:学习获取现有的对象并加以运用,以及学习如何自行设计对象并予以使用。
类(设计图):乃是对对象共同特征的描绘。
对象:为真实存在的具体事物。
在 Java 中,务必先设计类,方可获取对象。
如何定义类:
public class 类名 {
// 成员变量(代表属性,通常为名词)
// 成员方法(代表行为,通常为动词)
// 构造器(后续学习)
// 代码块(后续学习)
// 内部类(后续学习)
}
例如:
public class Phone {
// 属性(成员变量)
String brand;
double price;
// 行为(方法)
public void call() {
}
public void playGame() {
}
}
如何获取类的对象:
类名 对象名 = new 类名();
Phone p = new Phone();
如何使用对象:
- 访问属性:对象名。成员变量。
- 访问行为:对象名。方法名 (...)。
案例学习:
在手机案例中所获心得:
于一个类中创建对象的属性与行为,并在测试类中通过 new 对象来进行调用,可使代码更为简洁有序。
例如:
// 在 phone 类中定义类的特征,在 PhoneTest 中对类进行实例化后进行赋值与调用行为
public class PhoneTest {
public static void main(String[] args) {
// 创建手机的对象
Phone p = new Phone();
// 赋值
p.brand = "iphone";
p.price = 10000;
// 获取手机对象中的值
System.out.println(p.brand);
System.out.println(p.price);
// 创建一个新手机
Phone p2 = new Phone();
p2.brand = "iphone2";
p2.price = 20000;
p2.call();
p2.playGame();
// 调用手机中的方法
p.call();
p.playGame();
}
}
定义对象类之后,可通过在实例化时赋予不同的名称来创建出不同的对象。
定义类的注意事项:
- JavaBean 类用于描述一类事务,其中不包含 main 方法。
- 类名的首字母宜大写,应具备见名知意的特性,并采用驼峰命名法。
- 一个 Java 文件中可定义多个 class 类,但仅有一个类可由 public 修饰,且 public 修饰的类名必须与代码文件名一致。
- 成员变量的完整格式为:修饰符 数据类型 变量名称 = 初始化值;一般无需指定初始化值,存在默认值。
对象的成员变量的默认值规则:
定义类的建议:
- 类名首字母宜大写,使用英文,富有意义,满足驼峰命名要求,不使用关键字,符合标识符规定。
- 一个代码文件中可定义多个类,但仅有一个类使用 public 修饰,且 public 修饰的类名必须是 Java 代码的文件名称。
开发中类的设计:
首先审视需求中存在的事物类别,每个事物均应定义为一个独立的类,将事物的名词定义为属性,事物所能执行的操作定义为行为。
面向对象的三大特征 - 封装(如何恰当地设计对象的属性和方法)
- 原则:对象代表何物,便应封装相应的数据,并提供数据对应的行为。
- 例如:
length()
用于获取字符串的长度,toUppercase()
用于将字符串转换为大写。 - 封装的益处:降低学习成本。对象代表何物,就封装相应的数据,并提供相应的行为。
private
修饰符:
- 是一个权限修饰符,可用于修饰成员变量和成员方法。
- 被
private
修饰的成员仅能在本类中访问,需提供get
和set
方法后方可被其他类操作和使用。 get
和set
方法用于为成员变量赋值,方法使用public
修饰。
set
方法和get
方法的作用分别为:
set
方法旨在设置对象的属性值,可对传入的值进行合法性检查,如检查格式是否正确、值是否在合理范围内。通过封装属性的设置过程,提升代码的安全性和可维护性,避免外部直接对属性进行不当修改,使属性的修改处于受控状态。get
方法用于获取对象的属性值,确保属性的获取过程一致且可控。可在获取属性值时进行一些额外处理,如返回属性的副本而非原始引用,以防止外部代码意外修改内部状态,提高代码的可读性和可维护性。外部代码可通过清晰的方法名获取属性值,而无需直接访问对象的内部状态。
构造器的作用是为属性赋予初始值,在对象创建时被调用,使对象在诞生之际就具备完整的意义和可用的状态。
This
关键字:
遵循就近原则,离谁近就使用谁。使用this
关键字后将使用成员变量。例如:this.name = name;
将局部变量中的name
赋值给成员变量中的name
。
在抽象类中定义抽象函数时,默认的修饰符为public abstract
。
Jdk8 的抽象类中可以编写普通方法,但需添加default
和static
进行修饰。
// jdk8 提供默认的方法
default void defaultGet() {
System.out.println("defaultGet");
}
static void staticDel() {
System.out.println("staticDel");
}
在子类实现抽象类时,不强制要求重写default
和static
方法。
Lambda 表达式
Lambda 表达式的优点:简化匿名内部类的调用。
Lambda 表达式 + 方法引用 → 使代码更加精简。
接口的调用方法:
- 通过匿名内部类进行 new。
- 定义子类,让父类接收。
匿名内部类调用:
public class Test02 {
public static void main(String[] args) {
// 通过匿名内部类进行调用
orderService orderService = new orderService() {
@Override
public void get() {
System.out.println("get");
}
};
orderService.get();
// 使用 Lambda 表达式进行调用
new OrderService() {
@Override
public void get() {
System.out.println("get");
}
}.get();
}
}
接口中仅有一个抽象方法,则该接口为一个函数接口(函数接口中只能有一个抽象方法,但可以有多个普通方法)。
@FunctionalInterface
public interface MyFunctionalInterface {
void get();
default void defaultAdd() {
System.out.println("我是默认的方法");
}
}
@FunctionalInterface 标识该接口为函数接口。
Object 父类中的方法可在函数接口中重写。
Lambda 基础语法
() - 参数列表
-> 分割
{} 方法体
(a, b) -> {}
(函数接口的参数列表,无需写类型,需定义函数名称) -> {方法体}
无参方法调用:
public interface AcanthopanaxInterface {
void get();
}
AcanthopanaxInterface acanthopanaxInterface = () -> {
System.out.println("使用 Lambda 表达式调用方法");
};
acanthopanaxInterface.get();
有参方法调用:
public class Test04 {
public static void main(String[] args) {
// 1. 使用匿名内部类调用
YouShenInterface youShenInterface = new YouShenInterface() {
@Override
public String get(int i, int j) {
return i + "--" + j;
}
};
System.out.println(youShenInterface.get(1, 2));
// 2. 使用 Lambda 调用有参数函数方法
YouShenInterface youShenInterface2 = (i, j) -> {
return i + "--" + j;
};
System.out.println(youShenInterface2.get(1, 1));
}
}
public class Test05 {
public static void main(String[] args) {
AcanthopanaxInterface acanthopanaxInterface = () -> {
System.out.println("我是方法");
};
acanthopanaxInterface.get();
// 精简代码
((AcanthopanaxInterface) () -> {
System.out.println("我是方法");
}).get();
}
}