java快速学习速查(5) 
这个部分包含了Java面向对象部分的全部数据类型,继承,重载,多态,抽象类,封装,接口,枚举,包,反射
 
这里先简单的理解下关系:
封装 让各部门各司其职,不暴露内部细节。 
抽象类/接口 定义岗位职责(做什么)。 
继承 建立上下级关系(技术部→开发组)。 
重写 让不同岗位对同一任务有不同的执行方式。 
多态 让总经理只需喊“开始工作”,不同员工自动做正确的事。 
 
接下来是详解部分:
Java 继承全面解析 继承是面向对象编程的三大特性之一(封装、继承、多态),下面我将系统地讲解 Java 继承的各种功能和使用场景。
一、继承基础 1. 基本语法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class  Animal  {    private  String name;          public  Animal (String name)  {         this .name = name;     }          public  void  eat ()  {         System.out.println(name + "正在吃东西" );     } } class  Dog  extends  Animal  {    private  String breed;          public  Dog (String name, String breed)  {         super (name);           this .breed = breed;     }          public  void  bark ()  {         System.out.println("汪汪叫" );     }               @Override      public  void  eat ()  {         System.out.println(getName() + "("  + breed + ")正在啃骨头" );     }          public  String getBreed ()  {         return  breed;     } } 
 
2. 继承的特点 
子类拥有父类非 private 的属性和方法 
子类可以添加自己的属性和方法 
子类可以重写父类的方法 
Java 是单继承,一个类只能直接继承一个父类 
构造方法不能被继承,但可以通过 super 调用 
 
二、方法重写(Override) 1. 重写规则 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class  Shape  {    public  void  draw ()  {         System.out.println("绘制形状" );     }          public  double  getArea ()  {         return  0.0 ;     } } class  Circle  extends  Shape  {    private  double  radius;          public  Circle (double  radius)  {         this .radius = radius;     }          @Override      public  void  draw ()  {         System.out.println("绘制圆形,半径: "  + radius);     }          @Override      public  double  getArea ()  {         return  Math.PI * radius * radius;     } } 
 
重写规则 :
方法名和参数列表必须相同 
返回类型可以相同或是父类返回类型的子类 
访问修饰符不能比父类更严格 
不能抛出比父类更宽泛的异常 
 
2. @Override 注解 
不是必须的,但建议使用 
帮助编译器检查是否满足重写条件 
提高代码可读性 
 
三、super 关键字 1. 使用场景 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class  Vehicle  {    protected  String brand;          public  Vehicle (String brand)  {         this .brand = brand;     }          public  void  start ()  {         System.out.println("车辆启动" );     } } class  Car  extends  Vehicle  {    private  int  year;          public  Car (String brand, int  year)  {         super (brand);           this .year = year;     }          @Override      public  void  start ()  {         super .start();           System.out.println(year + "年款"  + brand + "汽车启动" );     }          public  void  showInfo ()  {         System.out.println("品牌: "  + super .brand + ", 年份: "  + year);     } } 
 
四、继承中的构造方法 1. 构造方法调用顺序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class  GrandParent  {    public  GrandParent ()  {         System.out.println("GrandParent构造方法" );     } } class  Parent  extends  GrandParent  {    public  Parent ()  {         System.out.println("Parent构造方法" );     } } class  Child  extends  Parent  {    public  Child ()  {         System.out.println("Child构造方法" );     } } public  class  ConstructorTest  {    public  static  void  main (String[] args)  {         new  Child ();     } } 
 
2. super() 使用规则 
必须出现在子类构造方法的第一行 
如果没有显式调用 super(),编译器会自动添加无参 super() 
如果父类没有无参构造方法,子类必须显式调用 super(参数) 
 
五、final 关键字 final可以用于修饰符类,方法和变量。
类:被修饰的类,不能被继承。 
方法:被修饰的方法,不能被重写。 
变量:被修饰符的变量,不能被修改。 
 
1. final 用法 1 2 3 4 5 6 7 8 9 final  class  CannotInherit  {      final  int  MAX_VALUE  =  100 ;            final  void  cannotOverride ()  {           System.out.println("这是最终方法" );     } } 
 
六、Object 类 Object 类是 Java 中所有类的超类,它定义了所有类的默认行为。
1. 常用方法 以下是常用的方法
方法 
描述 
 
 
equals() 
比较对象是否相等 
 
hashCode() 
获取对象的哈希码 
 
toString() 
返回对象的字符串表示 
 
clone() 
克隆对象 
 
finalize() 
垃圾回收前调用 
 
wait() 
线程等待 
 
notify() 
线程通知 
 
notifyAll() 
线程通知所有 
 
 
 
由于toString方法的访问结果是对象的哈希码,所以在实际开发中,通常需要重写toString方法,以便返回有意义的字符串表示。
在重写的时候可以自动拼接,无需手动书写show方法,在idea中键入toString即可
 
equals和 == 的区别: 重写equals前和==的区别和重写equals后和==的区别
重写equals前和==的区别:
==:比较的是两个对象的地址值 
equals:默认比较的也是两个对象的地址值 
 
 
重写equals后和==的区别:
==:比较的是两个对象的地址值 
equals:比较的是两个对象的内容是否相同 
 
 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class  Person  {    private  String name;     private  int  age;          public  Person (String name, int  age)  {         this .name = name;         this .age = age;     }          @Override      public  boolean  equals (Object obj)  {         if  (this  == obj) return  true ;         if  (obj == null  || getClass() != obj.getClass()) return  false ;         Person  person  =  (Person) obj;         return  age == person.age && name.equals(person.name);     }          @Override      public  int  hashCode ()  {         return  Objects.hash(name, age);     }          @Override      public  String toString ()  {         return  "Person{name='"  + name + "', age="  + age + "}" ;     } } 
 
七、抽象类与继承 1. 抽象类示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 abstract  class  Animal  {    protected  String name;          public  Animal (String name)  {         this .name = name;     }          public  abstract  void  makeSound () ;          public  void  sleep ()  {         System.out.println(name + "正在睡觉" );     } } class  Cat  extends  Animal  {    public  Cat (String name)  {         super (name);     }          @Override      public  void  makeSound ()  {         System.out.println(name + "说: 喵喵~" );     } } 
 
八、继承与多态 1. 多态示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 class  Employee  {    protected  String name;     protected  double  salary;          public  Employee (String name, double  salary)  {         this .name = name;         this .salary = salary;     }          public  double  calculateBonus ()  {         return  salary * 0.1 ;     } } class  Manager  extends  Employee  {    private  double  bonus;          public  Manager (String name, double  salary, double  bonus)  {         super (name, salary);         this .bonus = bonus;     }          @Override      public  double  calculateBonus ()  {         return  salary * 0.15  + bonus;     }          public  void  manageTeam ()  {         System.out.println(name + "正在管理团队" );     } } public  class  PolymorphismDemo  {    public  static  void  main (String[] args)  {         Employee  emp1  =  new  Employee ("张三" , 5000 );         Employee  emp2  =  new  Manager ("李四" , 8000 , 2000 );                  System.out.println("张三的奖金: "  + emp1.calculateBonus());         System.out.println("李四的奖金: "  + emp2.calculateBonus());                                    if  (emp2 instanceof  Manager) {             Manager  manager  =  (Manager) emp2;             manager.manageTeam();         }     } } 
 
九、继承最佳实践 1. 设计原则 
里氏替换原则 :子类应该能够替换父类而不影响程序正确性 
优先使用组合而非继承 :除非确实是”is-a”关系,否则考虑使用组合 
避免过深的继承层次 :通常不超过3层 
将通用方法放在高层类 :提高代码复用性 
使用抽象类定义接口 :为子类提供通用实现 
 
2. 示例:图形类继承体系 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 abstract  class  Shape  {    protected  String color;          public  Shape (String color)  {         this .color = color;     }          public  abstract  double  getArea () ;     public  abstract  double  getPerimeter () ;          @Override      public  String toString ()  {         return  "Shape[color="  + color + "]" ;     } } class  Circle  extends  Shape  {    private  double  radius;          public  Circle (String color, double  radius)  {         super (color);         this .radius = radius;     }          @Override      public  double  getArea ()  {         return  Math.PI * radius * radius;     }          @Override      public  double  getPerimeter ()  {         return  2  * Math.PI * radius;     }          @Override      public  String toString ()  {         return  "Circle["  + super .toString() + ",radius="  + radius + "]" ;     } } class  Rectangle  extends  Shape  {    private  double  length;     private  double  width;          public  Rectangle (String color, double  length, double  width)  {         super (color);         this .length = length;         this .width = width;     }          @Override      public  double  getArea ()  {         return  length * width;     }          @Override      public  double  getPerimeter ()  {         return  2  * (length + width);     }          @Override      public  String toString ()  {         return  "Rectangle["  + super .toString() +                 ",length="  + length + ",width="  + width + "]" ;     } } public  class  ShapeDemo  {    public  static  void  main (String[] args)  {         Shape[] shapes = {             new  Circle ("Red" , 5.0 ),             new  Rectangle ("Blue" , 4.0 , 6.0 )         };                  for  (Shape shape : shapes) {             System.out.println(shape);             System.out.println("Area: "  + shape.getArea());             System.out.println("Perimeter: "  + shape.getPerimeter());             System.out.println();         }     } } 
 
十、常见面试问题 
继承和接口的区别 ?
继承:is-a关系,单继承,可以包含实现 
接口:can-do关系,多实现,只有抽象方法(Java 8前) 
 
 
什么时候用继承 ?
当两个类之间有明显的is-a关系时 
需要复用父类代码时 
需要实现多态时 
 
 
为什么Java不支持多继承 ?
避免”钻石问题”(菱形继承问题) 
简化语言设计,减少复杂性 
 
 
构造方法能否被重写 ?
不能,构造方法不是成员方法 
子类构造方法必须调用父类构造方法 
 
 
如何防止类被继承 ?
使用final修饰类 
将构造方法设为private,并提供静态工厂方法 
 
 
 
Java 重写(Override)与重载(Overload)全面解析 下面我将系统地讲解 Java 中方法重写和方法重载的核心概念、使用场景和实际应用。
一、方法重写(Override)深度解析 1. 重写基础示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class  Animal  {    public  void  makeSound ()  {         System.out.println("动物发出声音" );     }          protected  String getInfo ()  {         return  "动物基本信息" ;     } } class  Cat  extends  Animal  {         @Override      public  void  makeSound ()  {         System.out.println("喵喵叫" );     }               @Override      public  String getInfo ()  {         return  "猫的信息: "  + super .getInfo();     }                     } public  class  OverrideDemo  {    public  static  void  main (String[] args)  {         Animal  myCat  =  new  Cat ();         myCat.makeSound();           System.out.println(myCat.getInfo());     } } 
 
2. 重写规则详解 
方法签名必须相同 :方法名、参数列表完全一致 
返回类型协变 :Java 5+ 允许子类方法返回父类方法返回类型的子类 
访问修饰符不能更严格 :可以更宽松但不能更严格 
异常限制 :
不能抛出新的检查异常 
不能抛出比父类更宽泛的检查异常 
可以抛出更具体的检查异常或不抛出异常 
可以抛出任何非检查异常 
 
 
不能重写 final/static/private 方法  
 
3. @Override 注解的重要性 1 2 3 4 5 6 7 8 9 10 11 12 13 class  Parent  {    public  void  show (String msg)  {         System.out.println("Parent: "  + msg);     } } class  Child  extends  Parent  {         @Override        public  void  sho (String msg)  {         System.out.println("Child: "  + msg);     } } 
 
二、方法重载(Overload)深度解析 1. 重载基础示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class  Calculator  {         public  int  add (int  a, int  b)  {         return  a + b;     }               public  int  add (int  a, int  b, int  c)  {         return  a + b + c;     }               public  double  add (double  a, double  b)  {         return  a + b;     }               public  String add (String s, int  n)  {         return  s + n;     }          public  String add (int  n, String s)  {         return  n + s;     }                } public  class  OverloadDemo  {    public  static  void  main (String[] args)  {         Calculator  calc  =  new  Calculator ();         System.out.println(calc.add(5 , 3 ));                 System.out.println(calc.add(5 , 3 , 2 ));              System.out.println(calc.add(2.5 , 3.7 ));             System.out.println(calc.add("ID" , 100 ));            System.out.println(calc.add(100 , "ID" ));        } } 
 
2. 重载规则详解 
必须改变参数列表 :
 
可以改变的内容 :
 
不能仅靠返回类型区分重载  
自动类型转换影响重载解析  
 
3. 重载解析过程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class  OverloadResolution  {    public  void  process (int  i)  {         System.out.println("处理整数: "  + i);     }          public  void  process (double  d)  {         System.out.println("处理浮点数: "  + d);     }          public  void  process (String s)  {         System.out.println("处理字符串: "  + s);     }          public  static  void  main (String[] args)  {         OverloadResolution  resolver  =  new  OverloadResolution ();         resolver.process(10 );              resolver.process(10.0 );            resolver.process("10" );            resolver.process('A' );             resolver.process(10L );         } } 
 
三、重写与重载对比 1. 核心区别对照表 
特性 
方法重写(Override) 
方法重载(Overload) 
 
 
发生位置 
子类与父类之间 
同一个类或父子类之间 
 
方法签名 
必须相同 
必须不同 
 
返回类型 
相同或子类(协变返回) 
可以不同 
 
访问修饰符 
不能比父类更严格 
可以不同 
 
异常抛出 
不能更宽泛 
可以不同 
 
调用机制 
运行时根据对象类型决定 
编译时根据参数类型决定 
 
多态性体现 
子类替换父类行为 
同一方法名处理不同类型参数 
 
 
 
2. 典型场景示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class  OverrideVsOverload  {    static  class  Base  {                  public  void  execute (int  num)  {             System.out.println("Base execute with int: "  + num);         }                           public  void  show ()  {             System.out.println("Base show" );         }     }          static  class  Derived  extends  Base  {                  public  void  execute (String str)  {             System.out.println("Derived execute with String: "  + str);         }                           @Override          public  void  show ()  {             System.out.println("Derived show" );         }     }          public  static  void  main (String[] args)  {         Base  obj  =  new  Derived ();                                    ((Derived)obj).execute("test" );                            obj.show();      } } 
 
四、高级话题与应用场景 1. 构造方法的重载 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class  Person  {    private  String name;     private  int  age;               public  Person ()  {         this ("无名氏" , 18 );      }          public  Person (String name)  {         this (name, 18 );     }          public  Person (String name, int  age)  {         this .name = name;         this .age = age;     }               public  void  introduce ()  {         System.out.println("我是"  + name + ",今年"  + age + "岁" );     }          public  void  introduce (String greeting)  {         System.out.println(greeting + ",我是"  + name);     } } public  class  ConstructorOverload  {    public  static  void  main (String[] args)  {         Person  p1  =  new  Person ();         Person  p2  =  new  Person ("张三" );         Person  p3  =  new  Person ("李四" , 25 );                  p1.introduce();         p2.introduce("你好" );     } } 
 
2. 重写 equals 和 hashCode 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class  Student  {    private  String id;     private  String name;          public  Student (String id, String name)  {         this .id = id;         this .name = name;     }          @Override      public  boolean  equals (Object o)  {                  if  (this  == o) return  true ;                  if  (o == null  || getClass() != o.getClass()) return  false ;                  Student  student  =  (Student) o;                  return  id.equals(student.id) && name.equals(student.name);     }          @Override      public  int  hashCode ()  {         return  Objects.hash(id, name);     }          @Override      public  String toString ()  {         return  "Student{id='"  + id + "', name='"  + name + "'}" ;     } } public  class  ObjectMethodOverride  {    public  static  void  main (String[] args)  {         Student  s1  =  new  Student ("1001" , "张三" );         Student  s2  =  new  Student ("1001" , "张三" );         Student  s3  =  new  Student ("1002" , "李四" );                  System.out.println("s1.equals(s2): "  + s1.equals(s2));          System.out.println("s1.equals(s3): "  + s1.equals(s3));          System.out.println("s1 hashCode: "  + s1.hashCode());         System.out.println("s2 hashCode: "  + s2.hashCode());         System.out.println("s1 toString: "  + s1);     } } 
 
3. 桥接方法与重写 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 interface  Processor <T> {    void  process (T t) ; } class  StringProcessor  implements  Processor <String> {         @Override      public  void  process (String s)  {         System.out.println("处理字符串: "  + s);     } } public  class  BridgeMethod  {    public  static  void  main (String[] args)  {         Processor<String> processor = new  StringProcessor ();         processor.process("测试" );                            for  (Method method : StringProcessor.class.getMethods()) {             if  (method.getName().equals("process" )) {                 System.out.println(method + " is bridge: "  + method.isBridge());             }         }     } } 
 
五、常见问题与最佳实践 1. 常见陷阱 
意外重载而非重写 :
1 2 3 4 5 6 7 8 class  Parent  {    void  doSomething (List<String> list)  {} } class  Child  extends  Parent  {         void  doSomething (ArrayList<String> list)  {} } 
 
 
静态方法”重写” :
1 2 3 4 5 6 7 8 9 10 11 12 class  Parent  {    static  void  staticMethod ()  {         System.out.println("Parent static" );     } } class  Child  extends  Parent  {         static  void  staticMethod ()  {         System.out.println("Child static" );     } } 
 
 
 
2. 最佳实践 
总是使用 @Override 注解 :避免意外重载而非重写 
保持重写方法行为一致 :遵守里氏替换原则 
谨慎重载可变参数方法 :容易导致混淆 
避免过度重载 :考虑使用不同方法名提高可读性 
文档化重写方法 :说明与父类方法的差异 
 
面向对象编程 面向对象思想  java是一种面向对象的程序设计语言,我们在面向对象的思想的指引下编写程序。
面向过程(pop) 
这是一种以过程为中心的编程思想。把事情拆成几个步骤然后按照一定的顺序执行。(强调过程) 
 
面向对象(oop) 
面向对象就是把现实世界的事物抽象成对象,这些对象都是唯一的并且都拥有自己的属性和行为。我们就可以通过调用这些对象的方法,属性去调用对象(强调对象) 
 
区别: 
面向过程:强调的是功能行为 
面向对象:强调具备功能的对象 
 
面向对象的三大特征: 
类和对象是面向对象的核心概念。具体使用方式见:[类和对象详解](http://xhayane.top/2025/03/31/java%E5%BF%AB%E9%80%9F%E5%AD%A6%E4%B9%A0%E9%80%9F%E6%9F%A5%EF%BC%881%EF%BC%89/) 
什么是类  类是对一类事物的描述,是抽象的、概念上的定义。例如:猫,狗,人,手机,电脑,电视,书,学生,老师,等等。
什么是对象  对象是实际存在的该类事物的每个个体,因而也称为实例(instance)。例如:张三,李四,王五,小明,小红,小绿,等等。
类和对象的关系  类是对象的模板,对象是类的实例。 -类是对一类事物的描述,是抽象的、概念上的定义 -对象是一类实例化的存在,是具体的、可以操作的。
其余内容请跳转[类和对象详解](http://xhayane.top/2025/03/31/java%E5%BF%AB%E9%80%9F%E5%AD%A6%E4%B9%A0%E9%80%9F%E6%9F%A5%EF%BC%881%EF%BC%89/)**java对象和类的全面解析** 
Java 面向对象核心特性全面解析(多态、抽象类、封装和接口这四大面向对象特性) 下面我将依次详细讲解Java面向对象编程的四大核心特性:多态、抽象类、封装和接口 。
问到三大特性就把接口去掉就行
一、多态(Polymorphism) 1. 多态基础 多态(对象的多种状态)同一个行为具有不同的表现形态的能力,对象多种表现形态的能力
多态的前提: 1.要有继承关系1 2 3 4 public  interface  MyInterFace  {         String USERNAME="admin123" ; } 
 2.子类要重写父类的方法 3.父类引用指向子类对象
多态的好处,体现再可以使程序编写的更加简单,并且有良好的扩展性。 
多态的理解 老板不需要知道每个人具体怎么工作,他只需要发同一个指令,不同员工会自动做自己该做的事。这就是多态! 
继承 + 方法重写(最常见) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class 员工 {     public  void  工作() {         System.out.println("处理行政事务" );     } } class 程序员 extends 员工 {     @Override      public  void  工作() {           System.out.println("写代码" );     } } class 销售 extends 员工 {     @Override      public  void  工作() {         System.out.println("拜访客户" );     } } 员工 员工1  = new  程序员(); 员工 员工2  = new  销售(); 员工1. 工作();  员工2. 工作();  
关键点:   
编译时(写代码时):员工1.工作() 看起来调用的是父类方法。   
运行时(实际执行时):JVM 会根据对象的实际类型(程序员 或 销售)调用对应的方法。   
 
接口实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 interface 可演讲 {     void  演讲(); } class 程序员 implements 可演讲 {     public  void  演讲() {         System.out.println("讲技术方案" );     } } class 销售 implements 可演讲 {     public  void  演讲() {         System.out.println("讲产品优势" );     } } 可演讲 人1  = new  程序员(); 可演讲 人2  = new  销售(); 人1. 演讲();  人2. 演讲();  
多态的操作应用 引用类型转换  多态的转型分为向上转型和向下转型两种:
向上转型 
父类引用指向子类实例,这种转换其实就是上面的多态写法,创建一个子类的对象,我们把它当作父类 来看待,我们创建一个学生,把他当作人来看待,这种肯定使可以的。 
 
注意事项 
向上转向是安全的,对象的范围有小变大的,弊端是子类特有的方法无法调用,类似于我们基本数据类 型中的自动转换。
向下转型父类类型向子类类型向下转换的过程,这个过程是强制的。(类似强制类型转换) 
类型转换异常 1 2 3 4 5 6 Animal  a  = new  Cat ();                 Cat c=(Cat)a;         Dog d=(Dog)a;         d.eat();         d.kanMen(); 
 
如上所示: 这段代码可以通过编译,但是运行的时间,却报错了 ClassCastException ,类型转换异常,这是因为 明明创建了Cat类型对象,运行时,当然不能转换为Dog对象,这两个类型并没有任何继承关系,不符 合类型转换的定义。为了避免 ClassCastException 的发生,java提供了instanceof关键字,给引用变 量做类型校验1 2 变量名 instanceof   数据类型 如果变量属于该数据类型,返回true,如果变量不属于该数据类型,返回false 
 
1 2 3 4 5 6 7 8 9 10 11 Animal  a  = new  Cat ();               if (a instanceof   Cat){             Cat c=(Cat)a;             c.eat();             c.zhuaLaoShu();        }else  if (a instanceof   Dog){             Dog d=(Dog)a;             d.eat();             d.kanMen();        } 
 
== 实战部分在最后 ==1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 class  Animal  {    public  void  makeSound ()  {         System.out.println("动物发出声音" );     } } class  Dog  extends  Animal  {    @Override      public  void  makeSound ()  {         System.out.println("汪汪叫" );     }          public  void  fetch ()  {         System.out.println("叼回飞盘" );     } } class  Cat  extends  Animal  {    @Override      public  void  makeSound ()  {         System.out.println("喵喵叫" );     }          public  void  scratch ()  {         System.out.println("挠沙发" );     } } public  class  PolymorphismDemo  {    public  static  void  main (String[] args)  {                  Animal  myPet1  =  new  Dog ();         Animal  myPet2  =  new  Cat ();                  myPet1.makeSound();           myPet2.makeSound();                                      if  (myPet1 instanceof  Dog) {             ((Dog)myPet1).fetch();           }     }               public  static  void  animalSound (Animal animal)  {         animal.makeSound();       } } 
 
 
 
2. 多态实现形式 
方法重写(Override) :子类重写父类方法 
方法重载(Overload) :同名不同参 
接口实现 :不同类实现同一接口 
抽象类和抽象方法 :提供统一接口,具体实现由子类完成 
 
3. 多态的优势 
可替换性 :子类对象可以替换父类对象 
可扩展性 :新增子类不影响已有代码 
灵活性 :同一方法不同表现 
简化性 :统一接口处理不同对象 
 
二、抽象类(Abstract Class) 1. 抽象类基础 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 abstract  class  Shape  {    protected  String color;          public  Shape (String color)  {         this .color = color;     }               public  abstract  double  getArea () ;               public  String getColor ()  {         return  color;     }               public  static  void  printShapeInfo (Shape shape)  {         System.out.println("颜色: "  + shape.color);         System.out.println("面积: "  + shape.getArea());     } } class  Circle  extends  Shape  {    private  double  radius;          public  Circle (String color, double  radius)  {         super (color);         this .radius = radius;     }          @Override      public  double  getArea ()  {         return  Math.PI * radius * radius;     } } class  Rectangle  extends  Shape  {    private  double  length;     private  double  width;          public  Rectangle (String color, double  length, double  width)  {         super (color);         this .length = length;         this .width = width;     }          @Override      public  double  getArea ()  {         return  length * width;     } } public  class  AbstractClassDemo  {    public  static  void  main (String[] args)  {         Shape  circle  =  new  Circle ("红色" , 5.0 );         Shape  rectangle  =  new  Rectangle ("蓝色" , 4.0 , 6.0 );                  Shape.printShapeInfo(circle);         Shape.printShapeInfo(rectangle);                       } } 
 
2. 抽象类特点 
不能被实例化 :只能被继承 
可以包含抽象方法 :没有实现的方法,必须被子类实现 
可以包含具体方法 :有实现的方法,子类可以直接使用或重写 
可以包含成员变量 :可以是各种访问修饰符 
构造方法 :虽然不能实例化,但可以有构造方法供子类调用 
 
3. 抽象类应用场景 
定义通用接口 :为相关类提供统一的操作规范 
部分实现 :提供部分通用实现,子类完成剩余部分 
模板方法模式 :定义算法骨架,具体步骤由子类实现 
 
三、封装(Encapsulation) 1. 封装基础实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 class  BankAccount  {         private  String accountNumber;     private  double  balance;     private  String owner;               public  BankAccount (String accountNumber, String owner, double  initialBalance)  {         this .accountNumber = accountNumber;         this .owner = owner;         this .balance = initialBalance;     }               public  void  deposit (double  amount)  {         if  (amount > 0 ) {             balance += amount;             System.out.println("存款成功,当前余额: "  + balance);         } else  {             System.out.println("存款金额必须大于0" );         }     }          public  void  withdraw (double  amount)  {         if  (amount > 0  && amount <= balance) {             balance -= amount;             System.out.println("取款成功,当前余额: "  + balance);         } else  {             System.out.println("取款失败,金额无效或余额不足" );         }     }               public  double  getBalance ()  {         return  balance;     }          public  String getAccountNumber ()  {         return  accountNumber;     }          public  String getOwner ()  {         return  owner;     }               public  void  setOwner (String owner)  {         if  (owner != null  && !owner.trim().isEmpty()) {             this .owner = owner;         }     }           } public  class  EncapsulationDemo  {    public  static  void  main (String[] args)  {         BankAccount  account  =  new  BankAccount ("123456789" , "张三" , 1000 );                  account.deposit(500 );           account.withdraw(200 );          account.withdraw(2000 );                   System.out.println("账户余额: "  + account.getBalance());              } } 
 
2. 封装原则 
最小访问原则 :使用最严格的访问修饰符 
数据隐藏 :字段通常设为private 
受控访问 :通过public方法暴露必要操作 
不变性保护 :对不应修改的字段不提供setter 
 
3. 封装优势 
安全性 :防止外部直接访问内部数据 
灵活性 :可以修改内部实现而不影响外部代码 
可维护性 :易于修改和扩展 
数据验证 :可以在方法中添加业务规则验证 
 
四、接口(Interface) 1. 接口基础 先补充个东西:大小写切换快捷键为Ctrl+Shift+CapsLk
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 interface  Switchable  {         int  MAX_BRIGHTNESS  =  100 ;               void  turnOn () ;     void  turnOff () ;               default  void  adjustBrightness (int  level)  {         System.out.println("调整亮度至: "  + Math.min(level, MAX_BRIGHTNESS));     }               static  void  printMaxBrightness ()  {         System.out.println("最大亮度: "  + MAX_BRIGHTNESS);     } } interface  SmartDevice  extends  Switchable  {    void  connectToWifi (String ssid) ;     void  runApp (String appName) ; } class  LightBulb  implements  Switchable  {    @Override      public  void  turnOn ()  {         System.out.println("灯泡亮起" );     }          @Override      public  void  turnOff ()  {         System.out.println("灯泡熄灭" );     } } class  SmartTV  implements  SmartDevice  {    @Override      public  void  turnOn ()  {         System.out.println("智能电视开机" );     }          @Override      public  void  turnOff ()  {         System.out.println("智能电视关机" );     }          @Override      public  void  connectToWifi (String ssid)  {         System.out.println("连接到WiFi: "  + ssid);     }          @Override      public  void  runApp (String appName)  {         System.out.println("运行应用: "  + appName);     }               @Override      public  void  adjustBrightness (int  level)  {         System.out.println("智能电视亮度调节至: "  + level);     } } public  class  InterfaceDemo  {    public  static  void  main (String[] args)  {         Switchable  bulb  =  new  LightBulb ();         bulb.turnOn();         bulb.adjustBrightness(80 );           bulb.turnOff();                  SmartTV  tv  =  new  SmartTV ();         tv.turnOn();         tv.connectToWifi("HomeWiFi" );         tv.runApp("Netflix" );         tv.adjustBrightness(60 );             tv.turnOff();                  Switchable.printMaxBrightness();       } } 
 
2. 接口特性 
多继承 :一个类可以实现多个接口 
默认方法 :Java 8+ 允许接口包含具体实现的方法 
静态方法 :Java 8+ 允许接口包含静态方法 
私有方法 :Java 9+ 允许接口包含私有方法 
常量定义 :接口中定义的变量默认是public static final 
 
3. 接口与抽象类对比 
特性 
接口(Interface) 
抽象类(Abstract Class) 
 
 
实例化 
不能 
不能 
 
方法实现 
Java 8+ 可以有默认方法 
可以有具体方法 
 
字段 
只能是常量(public static final) 
可以是普通成员变量 
 
构造方法 
没有 
有 
 
多继承 
一个类可实现多个接口 
一个类只能继承一个抽象类 
 
访问修饰符 
方法默认public 
方法可以有各种访问修饰符 
 
设计目的 
定义行为规范 
提供通用实现和规范 
 
 
 
五、四大特性综合应用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 abstract  class  Vehicle  {    private  String model;            protected  Vehicle (String model)  {         this .model = model;     }               public  String getModel ()  {         return  model;     }               public  abstract  void  start () ;     public  abstract  void  stop () ;               public  void  displayInfo ()  {         System.out.println("车型: "  + model);     } } interface  Electric  {    void  charge () ;     int  getBatteryLevel () ; } class  ElectricCar  extends  Vehicle  implements  Electric  {    private  int  batteryLevel;          public  ElectricCar (String model)  {         super (model);         this .batteryLevel = 100 ;     }          @Override      public  void  start ()  {         System.out.println(getModel() + "电动车静音启动" );     }          @Override      public  void  stop ()  {         System.out.println(getModel() + "电动车再生制动停止" );     }          @Override      public  void  charge ()  {         batteryLevel = 100 ;         System.out.println(getModel() + "已充满电" );     }          @Override      public  int  getBatteryLevel ()  {         return  batteryLevel;     }               public  void  autoPilot ()  {         System.out.println(getModel() + "自动驾驶模式激活" );     } } public  class  OOPIntegration  {    public  static  void  main (String[] args)  {         Vehicle[] vehicles = {             new  ElectricCar ("Tesla Model S" ),                      };                  for  (Vehicle vehicle : vehicles) {             vehicle.displayInfo();             vehicle.start();                          if  (vehicle instanceof  Electric) {                 Electric  electric  =  (Electric) vehicle;                 System.out.println("电量: "  + electric.getBatteryLevel() + "%" );                 electric.charge();             }                          if  (vehicle instanceof  ElectricCar) {                 ((ElectricCar)vehicle).autoPilot();             }                          vehicle.stop();             System.out.println();         }     } } 
 
六、设计原则与最佳实践 1. SOLID原则 
单一职责原则(SRP) :一个类只负责一个功能领域 
开闭原则(OCP) :对扩展开放,对修改关闭 
里氏替换原则(LSP) :子类必须能替换父类 
接口隔离原则(ISP) :客户端不应依赖它不需要的接口 
依赖倒置原则(DIP) :依赖抽象而非具体实现
 
迪米特法则 :一个对象应当对其他对象有最少的了解
 
合成复用原则 :优先使用组合而非继承 
 
2. 面向对象设计技巧 
优先使用组合而非继承 :除非明确is-a关系 
面向接口编程 :提高灵活性和可扩展性 
合理使用访问控制 :遵循最小权限原则 
避免过度设计 :根据实际需求设计类结构 
保持类和方法小巧 :单一职责,高内聚低耦合 
 
Java 枚举、包与反射全面解析 下面我将系统地讲解 Java 中枚举、包和反射的核心概念与使用场景。
一、枚举(Enum) 1. 枚举基础 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 public  enum  Day  {    MONDAY,      TUESDAY,      WEDNESDAY,      THURSDAY,      FRIDAY,      SATURDAY,      SUNDAY } public  enum  Planet  {    MERCURY(3.303e+23 , 2.4397e6 ),     VENUS(4.869e+24 , 6.0518e6 ),     EARTH(5.976e+24 , 6.37814e6 );          private  final  double  mass;        private  final  double  radius;           Planet(double  mass, double  radius) {         this .mass = mass;         this .radius = radius;     }          public  double  surfaceGravity ()  {         return  6.67300E-11  * mass / (radius * radius);     }          public  double  surfaceWeight (double  otherMass)  {         return  otherMass * surfaceGravity();     } } public  class  EnumDemo  {    public  static  void  main (String[] args)  {                  Day  today  =  Day.WEDNESDAY;         System.out.println("Today is: "  + today);                           System.out.println("All days:" );         for  (Day day : Day.values()) {             System.out.println(day);         }                           double  earthWeight  =  70 ;          double  mass  =  earthWeight / Planet.EARTH.surfaceGravity();         for  (Planet p : Planet.values()) {             System.out.printf("Your weight on %s is %f%n" ,                 p, p.surfaceWeight(mass));         }                           switch  (today) {             case  MONDAY:                 System.out.println("星期一综合症" );                 break ;             case  FRIDAY:                 System.out.println("感谢上帝,今天是星期五" );                 break ;             default :                 System.out.println("普通工作日" );         }     } } 
 
2. 枚举高级特性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 public  enum  Operation  {    PLUS("+" ) {         public  double  apply (double  x, double  y)  { return  x + y; }     },     MINUS("-" ) {         public  double  apply (double  x, double  y)  { return  x - y; }     },     TIMES("*" ) {         public  double  apply (double  x, double  y)  { return  x * y; }     },     DIVIDE("/" ) {         public  double  apply (double  x, double  y)  { return  x / y; }     };          private  final  String symbol;          Operation(String symbol) {         this .symbol = symbol;     }          @Override      public  String toString ()  {         return  symbol;     }          public  abstract  double  apply (double  x, double  y) ;               public  static  Operation fromSymbol (String symbol)  {         for  (Operation op : Operation.values()) {             if  (op.symbol.equals(symbol)) {                 return  op;             }         }         throw  new  IllegalArgumentException ("未知运算符: "  + symbol);     } } public  class  AdvancedEnum  {    public  static  void  main (String[] args)  {         double  x  =  10.5 ;         double  y  =  2.5 ;                  for  (Operation op : Operation.values()) {             System.out.printf("%f %s %f = %f%n" ,                  x, op, y, op.apply(x, y));         }                  Operation  op  =  Operation.fromSymbol("*" );         System.out.println("10 * 5 = "  + op.apply(10 , 5 ));     } } 
 
3. 枚举最佳实践 
单例模式实现 :枚举是实现单例的最佳方式 
策略模式 :利用枚举的抽象方法实现策略模式 
状态机 :适合用枚举实现有限状态机 
替代常量 :比常量类更类型安全 
 
二、包(Package) 1. 包基础使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 package  com.example.utils;public  class  MathUtils  {    public  static  int  add (int  a, int  b)  {         return  a + b;     }          public  static  int  factorial (int  n)  {         if  (n <= 1 ) return  1 ;         return  n * factorial(n - 1 );     } } package  com.example;import  com.example.utils.MathUtils;import  static  com.example.utils.MathUtils.add; public  class  Main  {    public  static  void  main (String[] args)  {                  System.out.println(com.example.utils.MathUtils.factorial(5 ));                           System.out.println(MathUtils.add(3 , 4 ));                           System.out.println(add(5 , 6 ));     } } 
 
2. 包的组织原则 
功能相关性 :相同功能的类放在同一包中 
层次结构 :按功能模块分层,如com.公司名.项目名.模块名 
访问控制 :利用包级私有(package-private)保护实现细节 
避免循环依赖 :包之间不应有循环依赖关系 
 
3. JDK常用包 
包名 
描述 
 
 
java.lang 
核心类(自动导入) 
 
java.util 
工具类和集合框架 
 
java.io 
输入输出相关 
 
java.net 
网络编程 
 
java.sql 
数据库操作 
 
java.time 
日期时间API 
 
 
 
三、反射(Reflection) 1. 反射基础 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 import  java.lang.reflect.*;public  class  ReflectionBasics  {    public  static  void  main (String[] args)  throws  Exception {                  Class<?> stringClass1 = String.class;         Class<?> stringClass2 = "Hello" .getClass();         Class<?> stringClass3 = Class.forName("java.lang.String" );                  System.out.println(stringClass1 == stringClass2);          System.out.println(stringClass2 == stringClass3);                            System.out.println("类名: "  + stringClass1.getName());         System.out.println("简单类名: "  + stringClass1.getSimpleName());         System.out.println("是否是接口: "  + stringClass1.isInterface());                           int  modifiers  =  stringClass1.getModifiers();         System.out.println("修饰符: "  + Modifier.toString(modifiers));                           Class<?> superClass = stringClass1.getSuperclass();         System.out.println("父类: "  + superClass.getName());                           Class<?>[] interfaces = stringClass1.getInterfaces();         System.out.println("实现的接口:" );         for  (Class<?> iface : interfaces) {             System.out.println("  "  + iface.getName());         }     } } 
 
2. 反射操作类成员 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 import  java.lang.reflect.*;import  java.util.*;class  Person  {    private  String name;     private  int  age;          public  Person ()  {}          public  Person (String name, int  age)  {         this .name = name;         this .age = age;     }          public  String getName ()  {         return  name;     }          public  int  getAge ()  {         return  age;     }          private  void  privateMethod ()  {         System.out.println("私有方法被调用" );     } } public  class  ReflectionMembers  {    public  static  void  main (String[] args)  throws  Exception {         Class<?> personClass = Person.class;                           System.out.println("构造方法:" );         Constructor<?>[] constructors = personClass.getConstructors();         for  (Constructor<?> c : constructors) {             System.out.println("  "  + c);         }                           Constructor<?> constructor = personClass.getConstructor(String.class, int .class);         Object  person  =  constructor.newInstance("张三" , 25 );         System.out.println(((Person)person).getName());                           System.out.println("\n字段:" );         Field[] fields = personClass.getDeclaredFields();         for  (Field field : fields) {             System.out.println("  "  + field);         }                           Field  nameField  =  personClass.getDeclaredField("name" );         nameField.setAccessible(true );          nameField.set(person, "李四" );         System.out.println("修改后name: "  + nameField.get(person));                           System.out.println("\n方法:" );         Method[] methods = personClass.getDeclaredMethods();         for  (Method method : methods) {             System.out.println("  "  + method);         }                           Method  getNameMethod  =  personClass.getMethod("getName" );         System.out.println("调用getName: "  + getNameMethod.invoke(person));                           Method  privateMethod  =  personClass.getDeclaredMethod("privateMethod" );         privateMethod.setAccessible(true );         privateMethod.invoke(person);     } } 
 
3. 反射应用场景 
动态代理 :AOP实现的基础 
注解处理 :框架中处理自定义注解 
类浏览器/IDE :获取类结构信息 
序列化/反序列化 :JSON/XML库的实现 
插件架构 :动态加载类 
测试工具 :Mock框架的实现 
 
4. 反射性能与安全 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 public  class  ReflectionPerformance  {    private  static  final  int  ITERATIONS  =  1000000 ;          public  static  void  main (String[] args)  throws  Exception {                  long  start  =  System.nanoTime();         Person  person  =  new  Person ();         for  (int  i  =  0 ; i < ITERATIONS; i++) {             person.getName();         }         long  directTime  =  System.nanoTime() - start;                           Method  getNameMethod  =  Person.class.getMethod("getName" );         start = System.nanoTime();         for  (int  i  =  0 ; i < ITERATIONS; i++) {             getNameMethod.invoke(person);         }         long  reflectionTime  =  System.nanoTime() - start;                           getNameMethod.setAccessible(true );         start = System.nanoTime();         for  (int  i  =  0 ; i < ITERATIONS; i++) {             getNameMethod.invoke(person);         }         long  reflectionAccessibleTime  =  System.nanoTime() - start;                  System.out.printf("直接调用耗时: %,d ns%n" , directTime);         System.out.printf("反射调用耗时: %,d ns%n" , reflectionTime);         System.out.printf("反射(setAccessible)调用耗时: %,d ns%n" , reflectionAccessibleTime);                           SecurityManager  sm  =  System.getSecurityManager();         if  (sm != null ) {             sm.checkPermission(new  ReflectPermission ("suppressAccessChecks" ));         }     } } 
 
性能提示 :
反射操作比直接调用慢 
通过setAccessible(true)可以提升性能 
缓存Method/Field/Constructor对象避免重复查找 
 
安全考虑 :
反射可以绕过访问控制检查 
安全管理器可以限制反射操作 
生产环境应谨慎使用反射 
 
四、综合应用示例 1. 注解处理器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 import  java.lang.annotation.*;import  java.lang.reflect.*;@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @interface  Test {    int  priority ()  default  5 ; } class  TestRunner  {    public  static  void  runTests (Class<?> testClass)  throws  Exception {         Object  testInstance  =  testClass.getDeclaredConstructor().newInstance();                           Method[] methods = testClass.getDeclaredMethods();         Arrays.sort(methods, (m1, m2) -> {             Test  t1  =  m1.getAnnotation(Test.class);             Test  t2  =  m2.getAnnotation(Test.class);             int  p1  =  t1 != null  ? t1.priority() : 0 ;             int  p2  =  t2 != null  ? t2.priority() : 0 ;             return  Integer.compare(p2, p1);          });                           for  (Method method : methods) {             if  (method.getAnnotation(Test.class) != null ) {                 System.out.println("Running test: "  + method.getName());                 method.invoke(testInstance);             }         }     } } class  MyTests  {    @Test(priority = 1)      public  void  testFeatureA ()  {         System.out.println("Testing important feature A" );     }          @Test(priority = 3)      public  void  testFeatureB ()  {         System.out.println("Testing feature B" );     }          @Test       public  void  testFeatureC ()  {         System.out.println("Testing feature C" );     }          public  void  helperMethod ()  {              } } public  class  AnnotationProcessor  {    public  static  void  main (String[] args)  throws  Exception {         TestRunner.runTests(MyTests.class);     } } 
 
2. 简单DI容器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 import  java.lang.annotation.*;import  java.lang.reflect.*;import  java.util.*;@Retention(RetentionPolicy.RUNTIME) @interface  Inject {}class  SimpleDIContainer  {    private  Map<Class<?>, Object> instances = new  HashMap <>();          public  void  register (Class<?> clazz)  throws  Exception {         Constructor<?>[] constructors = clazz.getConstructors();         if  (constructors.length != 1 ) {             throw  new  RuntimeException ("类必须有且只有一个公共构造方法" );         }                  Constructor<?> constructor = constructors[0 ];         Object[] params = Arrays.stream(constructor.getParameterTypes())             .map(paramType -> {                 if  (!instances.containsKey(paramType)) {                     throw  new  RuntimeException ("未注册的依赖类型: "  + paramType);                 }                 return  instances.get(paramType);             })             .toArray();                  Object  instance  =  constructor.newInstance(params);         instances.put(clazz, instance);     }          public  <T> T getInstance (Class<T> clazz)  {         return  clazz.cast(instances.get(clazz));     }          public  void  injectFields (Object obj)  throws  Exception {         for  (Field field : obj.getClass().getDeclaredFields()) {             if  (field.isAnnotationPresent(Inject.class)) {                 field.setAccessible(true );                 Class<?> fieldType = field.getType();                 if  (!instances.containsKey(fieldType)) {                     throw  new  RuntimeException ("未注册的依赖类型: "  + fieldType);                 }                 field.set(obj, instances.get(fieldType));             }         }     } } class  ServiceA  {    public  void  execute ()  {         System.out.println("ServiceA executed" );     } } class  ServiceB  {    @Inject      private  ServiceA serviceA;          public  void  doWork ()  {         System.out.println("ServiceB starting work" );         serviceA.execute();         System.out.println("ServiceB finished work" );     } } public  class  DIContainerDemo  {    public  static  void  main (String[] args)  throws  Exception {         SimpleDIContainer  container  =  new  SimpleDIContainer ();                           container.register(ServiceA.class);         container.register(ServiceB.class);                           ServiceB  serviceB  =  container.getInstance(ServiceB.class);         serviceB.doWork();     } } 
 
五、关键知识点总结 
枚举 :
类型安全的常量集合 
可以包含字段、方法和构造方法 
适合实现单例、策略模式等 
 
 
包 :
组织类和接口的命名空间 
控制访问权限(包级私有) 
避免命名冲突 
 
 
反射 :
运行时检查和操作类、方法、字段 
强大的但应谨慎使用 
性能开销较大,适合框架开发