面向对象
一、类与对象
类的成员变量---对象状态
类的成员函数---对象行为
类的静态变量
类的静态函数
1.没有 this 引用,静态变量全局唯一一份
2.普通函数引用静态变量、函数---可以
3.对象上引用静态变量、函数---可以,但编译器会警告
4.静态函数引用普通成员变量、函数---编译错误【静态函数里没有 this 引用,不知道该引用那个对象的成员变量和成员函数】
类的特殊函数
1.构造函数
2.equals
3.hashCode[a.hashCode() == b.hashCode() a.equals(b)]【下面可以得到上面,上面不能得到下面】
4.toString
代码展示:Employee.java
package interview.oop.company;
import java.util.List;
import java.util.Objects;
public class Employee {
public static List<Employee> allEmployees;
private final String name;
private final int salary;
public Employee(String name, int salary) {//构造函数(和类名一样,没有返回值)
this.name = name;
this.salary = salary;
}
public Employee(String name) { //函数重载
this(name, 0); //引用自己的构造函数
}
public void doWork() {
}
public void getPaid(BankEndPoint bank) {
bank.payment(name, salary);
}
// Package private for logic in the package to control
// when employees are loaded.
static void loadAllEmployees() {
// Loads all employees from database.
}
@Override
public int hashCode() {
return Objects.hash(name, salary);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Employee other = (Employee) obj;
return Objects.equals(this.name, other.name)
&& Objects.equals(this.salary, other.salary);
}
@Override
public String toString() {
return "Employee [name=" + name
+ ", salary=" + salary + "]";
}
public String getName() {
return name;
}
public int getSalary() {
return salary;
}
}
Tester.java
package interview.oop.company;
import java.util.LinkedList;
public class Tester {
public static void main(String[] args) {
Employee employee1 = new Employee("John", 10000); //必须填入参数
Employee employee2 = new Employee("Mary", 20000);
Employee employee3 = new Employee("John", 10000);
System.out.println("Testing equals");
System.out.println("employee1 == employee3 ? "
+ (employee1 == employee3)); // == 看是否是同一个对象
System.out.println("employee1.equals(employee3) ? "
+ employee1.equals(employee3));// 重写了equals 看是否值相同
System.out.println("employee2.equals(employee3) ? "
+ employee2.equals(employee3));
System.out.println(employee2);
}
}
输出:
二、接口与实现
接口的必要性
函数是如何实现的并不关心,直接引用即可,这就是接口
接口与类相比
1.由编译器强制的一个模块间协作的合约(Contract)
2.无成员变量
3.成员函数只有声明不能有实现
接口的声明
1.Java :interface 关键字,与 class 实现很像,用 nterface 后,函数中不能有实现;
2.C++:一个全部是纯虚函数的类
3.Python(大部分动态语言):依靠注释声明
接口与抽象类的区别:
1.在 C++ 中没有不同,一个全部是纯虚函数的类就是接口
2.在 Java 中:
从实现角度:1.抽象类可以有成员变量 2.抽象类可以有部分实现 3.抽象类不可以多重继承,接口可以;
接口多重实现:
抽象类:提供公有的实现;
接口:描述类有什么功能和能力
例:包装链表类,实现 Iterable 接口
代码实现:
Tester.java
package interview.oop.linkedlist;
public class Tester {
public static void main(String[] args) {
LinkedList<Integer> list = LinkedList.newEmptyList();
for (int i = 0; i < 100; i++) {
list.add(i);
}
for (Integer value : list) {
System.out.println(value);
}
LinkedList<String> stringList = LinkedList.newEmptyList();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100; i++) {
sb.append("a");
stringList.add(sb.toString());
}
for (String value : stringList) {
System.out.println(value);
}
}
}
LinkedList.java
package interview.oop.linkedlist;
import java.util.Iterator;
import java.util.NoSuchElementException;
import interview.common.Node;
public class LinkedList<T> implements Iterable<T> {
private Node<T> head;
private Node<T> tail;
public static <T> LinkedList<T> newEmptyList() {
return new LinkedList<T>();
}
private LinkedList() {
head = null;
tail = null;
}
public void add(T value) {
Node<T> node = new Node<>(value);
if (tail == null) {
head = node;
} else {
tail.setNext(node);
}
tail = node;
}
private class ListIterator implements Iterator<T> {
private Node<T> currentNode;
public ListIterator(Node<T> head) {
currentNode = head;
}
@Override
public boolean hasNext() {
return currentNode != null;
}
@Override
public T next() {
if (currentNode == null) {
throw new NoSuchElementException();
}
T value = currentNode.getValue();
currentNode = currentNode.getNext();
return value;
}
}
@Override
public Iterator<T> iterator() {
return new ListIterator(head);
}
}
三、继承与封装
继承(extends 关键字)
1.is-a 关系
2.子类 增加或修改 基类(增加成员变量,函数)【但无法执行 删除 操作】
3.Java 中所有函数相当于 C++ 虚函数【所有函数子类都可以重写】
代码实现:
Manager.java
package interview.oop.company;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Manager extends Employee {
private final List<Employee> reporters;
public Manager(String name, int salary,
List<Employee> reporters) {
super(name, salary);
this.reporters = Collections.unmodifiableList(
new ArrayList<>(reporters));
}
@Override
public void getPaid(BankEndPoint bank) {
super.getPaid(bank);
getStocks();
}
@Override
public void doWork() {
Employee worker = selectReporter();
worker.doWork();
}
@Override
public String toString() {
return "Manager [name=" + getName()
+ ", salary=" + getSalary() + "]";
}
private Employee selectReporter() {
loadReporters();
return null;
}
private void getStocks() {
}
private void loadReporters() {
reporters.clear();
reporters.add(new Employee("John", 10000));
reporters.add(new Employee("Mary", 20000));
}
}
输出:
封装
1.默认也称 package private
2.尽量 只使用 private 和 public
例 派生类中修改封装可见性【不建议修改 】
private --- public 对外部来说相当于增加函数, 这样是可以的;
public --- private 对外部来说相当于减少函数, 这样是不行的
例
输出:【均返回 a+b】new B 则调用的就是 B 里面的 a+b
150
150
四、不可变对象(Immutable Object)
定义:对象一旦创建完成,内部所有对象的成员变量就不能再改变了
特性:1.可以引用传递,可以缓存
2.线程安全
通过 final 关键字来实现不可变性
1.类声明---类不可以被继承
2.函数声明--函数不可以在派生类中重写
3.变量声明--变量不可以指向其他对象,但变量内容可以改
4.static final 变量 --- 用于定义常量,名称一般大写
实现不可变性
1.只凭 final 关键字无法保证不可变性
2.从接口定义、类的实现上保证不可变性
3.Collections.unmodifiable ***
代码实现:、
Employee.java
package interview.oop.company;
import java.util.List;
import java.util.Objects;
public class Employee {
public static List<Employee> allEmployees;
private final String name;
private final int salary;
public Employee(String name, int salary) {//构造函数(和类名一样,没有返回值)
this.name = name;
this.salary = salary;
}
public Employee(String name) { //函数重载
this(name, 0); //引用自己的构造函数
}
public void doWork() {
}
public void getPaid(BankEndPoint bank) {
bank.payment(name, salary);
}
// Package private for logic in the package to control
// when employees are loaded.
static void loadAllEmployees() {
// Loads all employees from database.
}
@Override
public int hashCode() {
return Objects.hash(name, salary);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Employee other = (Employee) obj;
return Objects.equals(this.name, other.name)
&& Objects.equals(this.salary, other.salary);
}
@Override
public String toString() {
return "Employee [name=" + name
+ ", salary=" + salary + "]";
}
public String getName() {
return name;
}
public int getSalary() {
return salary;
}
}
Manager.java
package interview.oop.company;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Manager extends Employee {
private final List<Employee> reporters;
public Manager(String name, int salary,
List<Employee> reporters) {
super(name, salary);
this.reporters = Collections.unmodifiableList(//新增代码[不可变]
new ArrayList<>(reporters));//新增代码
}
@Override
public void getPaid(BankEndPoint bank) {
super.getPaid(bank);
getStocks();
}
@Override
public void doWork() {
Employee worker = selectReporter();
worker.doWork();
}
@Override
public String toString() {
return "Manager [name=" + getName()
+ ", salary=" + getSalary() + "]";
}
private Employee selectReporter() {
loadReporters();
return null;
}
private void getStocks() {
}
private void loadReporters() { //新增代码
reporters.clear();
reporters.add(new Employee("John", 10000));
reporters.add(new Employee("Mary", 20000));
}
}
输出:、
五、泛型
ArrayList:获取第 n 个元素非常快,但插入删除非常慢;
LinkedList:插入删除非常快,但获取第 n 个元素非常慢;【需要遍历】
泛型定义:从 List 到 List<T>
1.规定 List 中的元素只能是类型T
2.ArrayList<Integer>,ArrayList<String>
3.LinkedList<Integer>,LinkedList<String>
语法:
1.List<Integer> list = new ArrayList<>()
2.List<Integer> list = LinkedList.of(1,2,3)
3.List<Integer> list = LinkedList.newEmptyList();
[编译器看不出来]
4. Object.equals(emptyIntList,LinkedList.<Integer>newEmptyList());
5. class ArrayList<T>{...
6.public <V> void printList(List<V> list){...
代码实现:
LinkedList.java
package interview.oop.linkedlist;
import java.util.Iterator;
import java.util.NoSuchElementException;
import interview.common.Node;
public class LinkedList<T> implements Iterable<T> { //修改代码(支持泛型)
private Node<T> head;
private Node<T> tail;
public static <T> LinkedList<T> newEmptyList() {//修改代码(支持泛型)
return new LinkedList<T>();
}
private LinkedList() {
head = null;
tail = null;
}
public void add(T value) {//修改代码(支持泛型)
Node<T> node = new Node<>(value);
if (tail == null) {
head = node;
} else {
tail.setNext(node);
}
tail = node;
}
private class ListIterator implements Iterator<T> {//修改代码(支持泛型)
private Node<T> currentNode;
public ListIterator(Node<T> head) {
currentNode = head;
}
@Override
public boolean hasNext() {
return currentNode != null;
}
@Override
public T next() {
if (currentNode == null) {
throw new NoSuchElementException();
}
T value = currentNode.getValue();
currentNode = currentNode.getNext();
return value;
}
}
@Override
public Iterator<T> iterator() {
return new ListIterator(head);
}
}
Tester.java
package interview.oop.linkedlist;
public class Tester {
public static void main(String[] args) {
LinkedList<Integer> list = LinkedList.newEmptyList();
for (int i = 0; i < 100; i++) {
list.add(i);
}
for (Integer value : list) {
System.out.println(value);
}
LinkedList<String> stringList = LinkedList.newEmptyList();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100; i++) {
sb.append("a");
stringList.add(sb.toString());
}
for (String value : stringList) {
System.out.println(value);
}
}
}
输出:(0-99/a-99个a)
Java Type Erasure
1.早期 Java 没有泛型
2.为了兼容性,在运行时将所有泛型内容 Erase
3.运行时,List、List<String>、List<Integer> 没有区别
运行时如何知道泛型类型:
1.void <T> printList(List<T> list); ---只能输出[1,2,3]
2.void <T> printList(List<T> list,class<T> elementType); --- 可以输出 Integer list of : [1,2,3]
Covariance
1.ArrayList<Integer> 是 List<Integer> ? 正确
2.List<Integer> 是 List<Object> ? 错误
分析:
补充:C++ 中的虚函数表
定义:将可以重写的代码做成一个表放起来,每一个链有自己的表,当 new 时,将 vtable 指针指向具体实例的类所在的表就可以了。
物理结构