目录
十五 . 面向对象的基本要素:封装,继承,多态
15.1 封装:
15.1.1 例子:
15.2 继承
15.2.1 例子
15.3 多态
15.3.1 例子
15.3.2 小结:谈谈多态的继承的联系
十五 . 面向对象的基本要素:封装,继承,多态
15.1 封装:
封装:封装是将数据和功能包装在一个类中,通过对外提供公共接口来隐藏内部实现细节。这样可以保护数据免受外部直接访问和修改,只能通过类提供的方法进行操作,封装提供了数据的安全性和代码的可维护性。
15.1.1 例子:
我们可以创建一个名为"Person"的类来封装一个人的相关信息,如姓名、年龄和性别。通过定义公共方法如"setName"、"setAge"和"setGender"来设置这些属性值,而不直接暴露给外部代码。这样可以确保属性值的正确性和一致性。
public class Person {private String name;private int age;private String gender;public Person(String name, int age, String gender) {this.name = name;this.age = age;this.gender = gender;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public static void main(String[] args) {Person person = new Person("John", 25, "Male");System.out.println("Person Name: " + person.getName());System.out.println("Person Age: " + person.getAge());System.out.println("Person Gender: " + person.getGender());// 修改属性值person.setName("Alice");person.setAge(30);person.setGender("Female");System.out.println("Updated Person Name: " + person.getName());System.out.println("Updated Person Age: " + person.getAge());System.out.println("Updated Person Gender: " + person.getGender());}
}
15.2 继承
继承:继承是指一个类(称为子类或派生类)可以继承另一个类(称为父类或基类)的属性和方法。
子类继承了父类的特性,并且可以在此基础上进行扩展或重写。继承实现了代码的重用和扩展性。
15.2.1 例子
我们可以定义一个"Animal"类作为父类,其中包含通用的属性和方法,如"eat"和"sleep"。然后可以创建子类如"Cat"和"Dog"来继承"Animal"类,并在子类中添加特定的属性和方法,如"meow"方法和"bark"方法。
// 定义父类 Animal
class Animal {// 父类的属性protected String name;// 父类的方法public Animal(String name) {this.name = name;}public void eat() {System.out.println(name + " is eating.");}public void sleep() {System.out.println(name + " is sleeping.");}
}// 定义子类 Cat
class Cat extends Animal {// 子类的属性private String breed;// 子类的方法,并调用父类的构造方法public Cat(String name, String breed) {super(name); // 调用父类的构造方法this.breed = breed;}// 子类的自定义方法public void meow() {System.out.println(name + " is meowing.");}
}// 定义子类 Dog
class Dog extends Animal {// 子类的属性private String breed;// 子类的方法,并调用父类的构造方法public Dog(String name, String breed) {super(name); // 调用父类的构造方法this.breed = breed;}// 子类的自定义方法public void bark() {System.out.println(name + " is barking.");}
}// 测试代码
public class Main {public static void main(String[] args) {Cat cat = new Cat("Kitty", "Persian");cat.eat(); // 调用继承自父类的方法cat.sleep();cat.meow(); // 调用子类自定义的方法Dog dog = new Dog("Buddy", "Labrador");dog.eat(); // 调用继承自父类的方法dog.sleep();dog.bark(); // 调用子类自定义的方法}
}
输出:
Kitty is eating.
Kitty is sleeping.
Kitty is meowing.
Buddy is eating.
Buddy is sleeping.
Buddy is barking.
15.3 多态
多态:多态是指同一种操作可以作用于不同的对象,并根据对象的实际类型执行不同的行为。通过多态,可以提高代码的灵活性和可扩展性。
15.3.1 例子
定义了一个抽象类 Animal
,并具有一个抽象方法 sound
。然后,定义了两个子类 Cat
和 Dog
,它们分别继承自 Animal
并实现了 sound
方法。
在测试类中,创建了一个 Animal
类型的对象数组,并分别用 Cat
和 Dog
的实例来初始化数组的元素。然后通过循环遍历数组,并调用 sound
方法,可以看到根据对象的实际类型,程序会执行不同的行为。这就是多态的体现,相同的方法名 sound
可以作用于不同的对象,并根据对象的实际类型执行不同的行为。
// 定义父类 Animal
abstract class Animal {abstract void sound();
}// 定义子类 Cat
class Cat extends Animal {void sound() {System.out.println("喵喵喵");}
}// 定义子类 Dog
class Dog extends Animal {void sound() {System.out.println("汪汪汪");}
}// 测试类
public class PolymorphismExample {public static void main(String[] args) {// 创建 Animal 对象数组Animal[] animals = new Animal[2];animals[0] = new Cat();animals[1] = new Dog();// 循环遍历数组并调用 sound 方法for (Animal animal : animals) {animal.sound();}}
}
15.3.2 小结:谈谈多态的继承的联系
继承是建立类之间的一种层次关系,子类可以继承父类的属性和方法,并且可以增加自己的特定实现;而多态是在继承关系中,通过父类的类型引用来指向子类的对象,并且根据对象的实际类型执行不同的行为。继承是一种静态的关系,而多态是一种动态的行为。继承和多态通常是一起使用,多态是继承的一种体现。
十六 . synchronized 和 ReentrantLock 的区别?
Java精心设计的高效并发机制,构建大规模应用的基础之一。
16.1 典型回答
synchronized 是Java内建的同步机制,也被人称作Intrinsic Locking,提供互斥的语义和可见性,当一个线程已经获取当前锁时,其他试图获取的线程只能等待或者阻塞在哪里。
Java 5 以前,synchronized 是仅有的同步手段,在代码中,synchronized可以用来修饰方法,可以在特定的代码快上,本质上synchronized方法,等同于把方法全部语句用synchronized块包起来。
ReentrantLock ,通常称为再入锁,Java提供锁的实现,语义和synchronized差不多,再入锁可以直接通过代码,直接调用Lock()方法获取,代码书写更加灵活,ReentrantLock提供了很多实用的方法,实现了很多synchronized无法做到的细节控制,可以控制fairness,也就是公平性,或者利用定义条件等,明确调用unlock()方法释放,不然就会一直持有这个锁。
synchronized和ReentrantLock的性能比较,早期synchronized再很多场景下性能相差比较大,后续进行改进后,再低竞争的场景表现可能优于ReentrantLock。
16.2 深入理解底层锁的概念
16.2.1 synchronized
16.2.2 ReentrantLock
ReentrantLock
是Java提供的可重入锁实现,它具有更细粒度的控制和更多的功能。相较于synchronized
,ReentrantLock
提供了以下优势:
- 公平性(Fairness)控制:
ReentrantLock
可以通过构造方法的参数来指定是否按照线程请求锁的顺序获取锁(公平性),以避免某些线程长时间等待锁而产生饥饿现象。 - 可中断性(Interruptibility):
ReentrantLock
提供了可中断的获取锁的方法,即线程在等待锁的过程中可以被其他线程中断,并通过捕获InterruptedException
来处理中断事件。 - 条件变量(Condition)支持:
ReentrantLock
内置了Condition
接口,可以创建多个条件变量,使线程能够在特定条件满足时等待或被唤醒,从而实现更灵活的线程协作。 - 超时控制(Timeout):
ReentrantLock
提供了尝试获取锁的方法,可以指定一个超时时间,在超过指定时间后如果无法获得锁,则继续执行其他操作,避免线程长时间等待。
在高竞争的多线程场景下,ReentrantLock
通常表现更好,因为它提供了对锁的更细粒度的控制,并且支持更多的高级功能。