Java面试--面向对象

面向对象

一、类与对象

类的成员变量---对象状态

类的成员函数---对象行为

类的静态变量

类的静态函数

1.没有 this 引用,静态变量全局唯一一份

2.普通函数引用静态变量、函数---可以

3.对象上引用静态变量、函数---可以,但编译器会警告

4.静态函数引用普通成员变量、函数---编译错误【静态函数里没有 this 引用,不知道该引用那个对象的成员变量和成员函数】

扫描二维码关注公众号,回复: 3406799 查看本文章

 

类的特殊函数

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 指针指向具体实例的类所在的表就可以了。

物理结构

猜你喜欢

转载自blog.csdn.net/jianghao233/article/details/82853699