• 【再探】Java — 面向对象编程特性与内部类


     封装、继承、多态及抽象是面向编程的四大特性。

    1 易错知识点记录

    1.1 继承

    1.1.1 类的初始化顺序

    1)类的静态模块(除了构造器,其是特殊的静态方法)先加载执行,且父类的静态模块先与子类的静态模块加载。

    2)非静态模块(实例变量初始化、非静态代码块)会先于构造器执行。父类实例化完成后,子类才会进行实例化。

    问:为啥父类的静态模块先与子类的静态模块执行?

    1. JVM 加载类时,父类会被首先加载;
    2. 如果父类的静态模块没实例化完成,子类就可能没法正确地从父类继承而来静态信息。
    1. public class InitOrder {
    2. public static void main(String[] args) {
    3. new Son();
    4. /**
    5. * Father 静态模块,staticNum = 2
    6. * Son 静态模块,staticStr = Hello
    7. * father 实例模块, num = 9
    8. * Father 构造器
    9. * son 实例模块,str = Init
    10. * Son 构造器
    11. */
    12. }
    13. private static class Father {
    14. static int staticNum = 2;
    15. int num = 9;
    16. static {
    17. System.out.println("Father 静态模块,staticNum = " + staticNum);
    18. }
    19. {
    20. System.out.println("father 实例模块, num =" + num);
    21. }
    22. public Father() {
    23. System.out.println("Father 构造器");
    24. }
    25. }
    26. private static class Son extends Father {
    27. static String staticStr = "Hello";
    28. String str = "Init";
    29. static {
    30. System.out.println("Son 静态模块,staticStr = " + staticStr);
    31. }
    32. {
    33. System.out.println("son 实例模块,str = " + str);
    34. }
    35. public Son() {
    36. System.out.println("Son 构造器");
    37. }
    38. }
    39. }

    1.2 多态

    1)“缺陷”:私有方法不会有多态行为

    2)构造器内部的多态行为:在父类的构造器中如果使用this来调用实例方法(且该方法被子类重新),那么此时会有多态行为,即真正执行的是子类的方法。

    1. public class Polymorphic {
    2. public static void main(String[] args) {
    3. Father father = new Son();
    4. /**
    5. * Father 构造器
    6. * father.fun1()
    7. * son.fun2()
    8. * Son 构造器
    9. */
    10. }
    11. private static class Father {
    12. public Father() {
    13. System.out.println("Father 构造器");
    14. fun1();
    15. fun2();
    16. }
    17. private void fun1() {
    18. System.out.println("father.fun1()");
    19. }
    20. public void fun2() {
    21. System.out.println("father.fun2()");
    22. }
    23. }
    24. private static class Son extends Father{
    25. public Son() {
    26. System.out.println("Son 构造器");
    27. }
    28. private void fun1() {
    29. System.out.println("son.fun1()");
    30. }
    31. @Override
    32. public void fun2() {
    33. System.out.println("son.fun2()");
    34. }
    35. }
    36. }

    1.3 接口

    1. 接口中的域隐式式final static。
    1. 因为接口本身不能被实例化,所以接口不能有实例变量。
    2. final 可以保持接口变量的稳定性,防止继承中被覆盖。
    3. 保持一致性,如果可以被修改,那么实现该接口的类可能会在不同时刻看到不同的值,从而可能导致行为的不一致。

    2)继承的子接口可以重复定义方法,但是如果只是返回值不同,而其他签名相同,则会编译报错。

    1.4 内部类

    1)内部类与迭代器。

    像List、Set 等容器中,它们的主要职责是存储数据。但是好多时候我们需要遍历这些数据。 根据“单一职责”的要求,我们把存储与遍历这两个不同的职责写入到两个类中。

    而我们常常会把迭代器写为容器的内部类,这样方便迭代器访问其数据。

    1. public class CustomInnerIterator {
    2. public static void main(String[] args) {
    3. CustomList<Integer> customList = new CustomList<>();
    4. for (int i = 0; i < 15; i++) customList.addItem(i);
    5. Iterator<Integer> iterator = customList.createIterator();
    6. while (iterator.hasNext()) System.out.println(iterator.next());
    7. }
    8. private interface Iterator<T> {
    9. boolean hasNext();
    10. T next();
    11. T current();
    12. }
    13. private static class CustomList<T> {
    14. private final int INIT_SIZE = 10;
    15. private Object[] dataArray;
    16. private int size = 0;
    17. public CustomList() {
    18. dataArray = new Object[INIT_SIZE];
    19. }
    20. private void grow() {
    21. if (size > dataArray.length / 2) {
    22. dataArray = Arrays.copyOf(dataArray, dataArray.length + INIT_SIZE);
    23. }
    24. }
    25. public void addItem(T elemnt) {
    26. grow();
    27. dataArray[size++] = elemnt;
    28. }
    29. public Iterator<T> createIterator() {
    30. return new CustomIterator();
    31. }
    32. public class CustomIterator implements Iterator<T> {
    33. int pos = 0;
    34. @Override
    35. public boolean hasNext() {
    36. return size > pos;
    37. }
    38. @Override
    39. public T next() {
    40. return (T)dataArray[pos++];
    41. }
    42. @Override
    43. public T current() {
    44. return (T)dataArray[pos];
    45. }
    46. }
    47. }
    48. }

    2)普通内部类不能有静态模块。

    普通内部类(非静态内部类)与外部类的对象紧密相关,普通内部类实例的生命依附于外部类的实例。 而静态模块是类级别的,在普通内部类定义静态模块没有任何意义。

    3)局部内部类与匿名内部类的区别:局部内部类可以使用构造器。

    1. public class LocalAndAnonymity {
    2. public static void main(String[] args) {
    3. Interface interface1 = createInterface1("可以使用构造器哦");
    4. Interface interface2 = createInterface2();
    5. interface1.fun("interface1");
    6. interface2.fun("interface2");
    7. }
    8. private interface Interface {
    9. void fun(String str);
    10. }
    11. private static Interface createInterface1(String info) {
    12. class InterfaceImpl implements Interface {
    13. private final String otherInfo;
    14. public InterfaceImpl(String otherInfo) {
    15. System.out.println("局部内部类的构造器");
    16. // 构造器,可以构造器传参等
    17. this.otherInfo = otherInfo;
    18. }
    19. @Override
    20. public void fun(String str) {
    21. System.out.println("局部内部类:" + otherInfo + "-" + str);
    22. }
    23. }
    24. return new InterfaceImpl(info);
    25. }
    26. private static Interface createInterface2() {
    27. return new Interface() {
    28. @Override
    29. public void fun(String str) {
    30. System.out.println("匿名内部类:" + str);
    31. }
    32. };
    33. }
    34. }

  • 相关阅读:
    NBextensions/JPT Notebook 载入问题(forbidden)
    C++学习笔记(三十一)
    怎么从零开始运行github / 现成的项目
    kubernetes集群编排(13)
    基于JSP+Servlet的医疗设备管理系统
    Cinema 4D 2024更新, 比旧版速度更快!
    【Vue基础】Vue路由,实现页面跳转
    【从零开始学习 UVM】2.3、UVM 基础功能 —— UVM Object Copy/Clone
    JVMの堆、栈内存存储
    9、SpringBoot_日志使用
  • 原文地址:https://blog.csdn.net/qq_25308331/article/details/138171247