Java基础十六:枚举,包,反射
一、枚举Enum1. 什么是枚举枚举是一种特殊的类用于定义一组固定的常量。2. 基本用法// 最简单的枚举 public enum Season { SPRING, SUMMER, AUTUMN, WINTER } // 使用枚举 public class TestEnum { public static void main(String[] args) { Season s Season.SPRING; // 常用方法 System.out.println(s.name()); // SPRING System.out.println(s.ordinal()); // 0索引位置 System.out.println(s.toString()); // SPRING // 遍历枚举 for (Season season : Season.values()) { System.out.println(season); } // 根据字符串获取枚举 Season autumn Season.valueOf(AUTUMN); // switch 中使用枚举 switch (s) { case SPRING: System.out.println(春天); break; case SUMMER: System.out.println(夏天); break; default: System.out.println(其他季节); } } }3. 带属性和方法的枚举public enum Grade { // 枚举常量必须首先定义可以带参数 EXCELLENT(优秀, 90, 100) { Override public String getDescription() { return 成绩优异表现突出; } }, GOOD(良好, 80, 89) { Override public String getDescription() { return 成绩良好继续保持; } }, PASS(及格, 60, 79) { Override public String getDescription() { return 成绩及格需要努力; } }, FAIL(不及格, 0, 59) { Override public String getDescription() { return 成绩不及格需要补习; } }; // 成员变量 private String chineseName; private int minScore; private int maxScore; // 构造方法必须是 private private Grade(String chineseName, int minScore, int maxScore) { this.chineseName chineseName; this.minScore minScore; this.maxScore maxScore; } // 普通方法 public String getChineseName() { return chineseName; } public boolean isInRange(int score) { return score minScore score maxScore; } // 抽象方法每个枚举常量必须实现 public abstract String getDescription(); // 静态方法 public static Grade fromScore(int score) { for (Grade grade : Grade.values()) { if (grade.isInRange(score)) { return grade; } } return FAIL; } } // 使用示例 public class TestGrade { public static void main(String[] args) { int score 85; Grade grade Grade.fromScore(score); System.out.println(分数 score); System.out.println(等级 grade); System.out.println(中文名 grade.getChineseName()); System.out.println(描述 grade.getDescription()); // 输出 // 分数85 // 等级GOOD // 中文名良好 // 描述成绩良好继续保持 } }4. 枚举实现接口interface Describable { String describe(); } enum Color implements Describable { RED { Override public String describe() { return 热情奔放的红色; } }, GREEN { Override public String describe() { return 生机勃勃的绿色; } }, BLUE { Override public String describe() { return 宁静深邃的蓝色; } }; // 也可以在枚举级别实现 // Override // public String describe() { // return 这是一个颜色; // } }二、包Package1. 什么是包包用于组织类和接口类似于文件系统中的文件夹避免命名冲突提供访问保护。2. 包的定义和使用// 文件com/example/model/User.java package com.example.model; // 必须在第一行注释除外 import java.util.Date; // 导入单个类 import java.util.*; // 导入包下所有类 import static java.lang.Math.PI; // 静态导入 public class User { private String name; private Date birthday; public double getCircleArea(double radius) { return PI * radius * radius; // 直接使用静态导入的常量 } }3. 包命名规范// 包名全部小写使用域名倒序 // 常见包结构 com.example.project.model // 数据模型 com.example.project.dao // 数据访问层 com.example.project.service // 业务逻辑层 com.example.project.controller // 控制器层 com.example.project.util // 工具类 com.example.project.exception // 异常类 com.example.project.config // 配置类4. 包的访问权限// 文件com/example/Person.java package com.example; public class Person { public String name; // 任何地方都能访问 protected int age; // 子类和同包可以访问 String address; // 默认权限同包可以访问 private String idCard; // 只有本类能访问 } // 文件com/example/Test.java同包 package com.example; public class Test { public static void main(String[] args) { Person p new Person(); p.name 张三; // ✅ public p.age 18; // ✅ protected同包 p.address 北京; // ✅ default同包 // p.idCard xxx; // ❌ private无法访问 } }5. 包和编译运行# 目录结构 # src/ # com/ # example/ # Hello.java # 编译 javac -d . src/com/example/Hello.java # 运行 java com.example.Hello # 打包成jar jar cvf myapp.jar com/三、反射Reflection1. 什么是反射反射允许程序在运行时获取类的完整信息并动态地操作类的属性和方法2. 获取Class对象的三种方式通俗理解把类想象成一个设计图纸比如person类的代码吧Class对象想象成这个图纸的说明书通过说明书可以知道图纸上画了什么有什么属性能做什么事。// 方式1通过类名.class Class? clazz1 String.class; //适用场景 // 示例获取任意已知类的 Class 对象 Class? clazz1 Person.class; Class? clazz2 ArrayList.class; Class? clazz3 int.class; // 基本类型也可以 // 方式2通过对象.getClass() String str hello; Class? clazz2 str.getClass(); //适用场景:手头上有了一个对象想知道它属于哪一类 // 示例多态情况下的实际类型 Animal animal new Dog(); // 声明为 Animal实际是 Dog Class? clazz animal.getClass(); // 返回的是 Dog.class不是 Animal.class // 判断对象的实际类型 if (animal.getClass() Dog.class) { System.out.println(这实际上是一条狗); } // 方式3通过 Class.forName() Class? clazz3 Class.forName(java.lang.String); //适用场景不知道具体类名需要动态配置 public class Demo { public static void main(String[] args) throws Exception { // 1. 类名.class - 静态方式 Class? clazz1 User.class; System.out.println(方式1 clazz1.getName()); // 2. 对象.getClass() - 已有对象 User user new User(张三, 20); Class? clazz2 user.getClass(); System.out.println(方式2 clazz2.getName()); // 3. Class.forName() - 动态加载 String className com.example.User; // 可以从配置文件读取 Class? clazz3 Class.forName(className); System.out.println(方式3 clazz3.getName()); // 三种方式获取的是同一个 Class 对象 System.out.println(clazz1 clazz2); // true System.out.println(clazz1 clazz3); // true } } class User { private String name; private int age; public User(String name, int age) { this.name name; this.age age; } }3.获取类的信息public class ReflectionDemo { public static void main(String[] args) throws Exception { Class? clazz Person.class; // 获取类名 System.out.println(类名 clazz.getName()); System.out.println(简单类名 clazz.getSimpleName()); // 获取包信息 Package pkg clazz.getPackage(); System.out.println(包名 pkg.getName()); // 获取修饰符 int modifiers clazz.getModifiers(); System.out.println(是否是public Modifier.isPublic(modifiers)); // 获取父类 Class? superclass clazz.getSuperclass(); System.out.println(父类 superclass.getName()); // 获取接口 Class?[] interfaces clazz.getInterfaces(); // 获取构造方法 Constructor?[] constructors clazz.getConstructors(); // 获取方法 Method[] methods clazz.getDeclaredMethods(); // 获取字段 Field[] fields clazz.getDeclaredFields(); } }4.动态创建对象// 方式1通过 Class 对象 Class? clazz Person.class; Person person1 (Person) clazz.newInstance(); // 已废弃 // 方式2通过 Constructor推荐 ConstructorPerson constructor Person.class.getConstructor(String.class, int.class); Person person2 constructor.newInstance(张三, 20); // 创建数组 Object array Array.newInstance(String.class, 10); Array.set(array, 0, hello); String value (String) Array.get(array, 0);5.动态调用方法public class MethodInvokeDemo { public static void main(String[] args) throws Exception { Person person new Person(李四, 25); Class? clazz person.getClass(); // 获取并调用公有方法 Method publicMethod clazz.getMethod(getName); String name (String) publicMethod.invoke(person); System.out.println(name); // 获取并调用私有方法 Method privateMethod clazz.getDeclaredMethod(privateMethod, String.class); privateMethod.setAccessible(true); // 突破私有权限 String result (String) privateMethod.invoke(person, 参数); // 调用静态方法 Method staticMethod clazz.getMethod(staticMethod); staticMethod.invoke(null); // 静态方法不需要对象实例 } } 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; } private String privateMethod(String param) { return 私有方法 param; } public static void staticMethod() { System.out.println(静态方法); } }6.动态操作字段Person person new Person(王五, 30); Class? clazz person.getClass(); // 获取私有字段 Field nameField clazz.getDeclaredField(name); nameField.setAccessible(true); // 突破私有权限 // 读取字段值 String name (String) nameField.get(person); System.out.println(原值 name); // 修改字段值 nameField.set(person, 赵六); System.out.println(新值 nameField.get(person));