反射 枚举和lambda

    技术2022-07-11  137

    1 反射(reflect) 是 在运行状态中, 对于任意一个类, 都能够知道这个类的所有属性和方法. 对于任意 一个对象,都能够调用它的任意方法和属性. 既然能拿到那么,我们就可以修改部分类型信息. 这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制.

    2 使用场景: 可以获取到某个类对象, 以及遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用Java的 反射机制通过反射获取到某些 私有的成员或方法. (1) Class类 代表类的实体,在运行的Java应用程序中表示类和接口 . (2) Field类 代表类的成员变量/类的属性 . (3) Method类 代表类的方法 (4) Constructor类 代表类的构造方法

    3-1 获得 Class对象 的三种方式.

    (1) 使用 Class.forName(“类的全路径名”), 是静态方法. 前提是 已明确类的全路径名.

    Class catClass = Class.forName("java15_0418.Cat");

    (2) 使用 类名.class 方法. 仅适合在编译前就已经明确要操作的类.

    Class catClass2 = Cat.class; System.out.println(catClass == catClass2);

    (3) 使用 类对象.getClass() 方法.

    Cat cat = new Cat("小黑"); Class catClass3 = cat.getClass();

    结论: 得到的类对象在内存中只有一份, 不管通过哪种方式获取到的类对象, 本质上都是同一个对象.所以三个都相等.

    3-2 通过Class对象 可以创建实例. 3-3 通过反射 获取/修改属性 (也可以修改 private 的属性).

    package java15_0418; class Cat { private String name; public Cat(String name) { this.name = name; } public void eat(String food) { System.out.println(this.name + " 正在吃 " + food); } } Class catClass = Class.forName("java15_0418.Cat"); // 通过 getDeclaredField 能得到局部内容. 通过 Field 对象来表示 Field filed = catClass.getDeclaredField("name"); // 这个代码加上之后, 才能访问 private 的成员 filed.setAccessible(true); Cat cat = new Cat(); filed.set(cat, "小喵喵"); //这个代码相当于cat.name="小喵喵" String name = (String) filed.get(cat); //这个代码相当于cat.name System.out.println(name);

    3-4 通过反射 获取到类中的方法.

    Class catClass = Class.forName("java15_0418.Cat"); // 方法是可以重载的. 就可以通过后续的变长参数列表来指定, 要获取哪个版本的 eat. // 下面这个代码的意思是获取到 只有一个 参数 且类型为 String 的 eat 方法 Method method = catClass.getMethod("eat", String.class); Cat cat1 = new Cat(); method.invoke(cat1, "猫粮");

    3-5 获取构造方法, 借助构造方法来实例化对象.

    Class catClass5 = Class.forName("java15_0418.Cat"); // 获取到 Cat 类中, 只有一个参数且类型为 String 的构造方法 Constructor constructor = catClass5.getConstructor(String.class); Cat cat5 = (Cat) constructor.newInstance("小黑"); cat5.eat("鱼");

    4 反射优点和缺点. 优点: (1) 对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法. (2) 增加程序的灵活性和扩展性,降低耦合性,提高自适应能力. (3) 反射已经运用在了很多流行框架如:Struts、Hibernate、Spring 等等. 缺点: (1) 我们认为反射是一个“自省”的过程,所以在性能上面有性能的问题, 一般不建议用在小型程序上,可用到框架当中. (2) 反射技术绕过了源代码的技术,因而会带来维护问题. 反射代码比相应的直接代码更复杂 .

    5 枚举: 是将一组常量组织起来.

    public enum Sex { MALE, FEMALE, OTHER, } public class TestEnum { public static void main(String[] args) { // 通过刚才定义常量来表示性别, 代码可读性是提高了, 但是对于下面的场景 // 编译器并没有明确的约束. 按理説这个代码是无意义的, 但是编译仍然能正常编译. Sex sex=Sex.valueOf("MALE"); if(sex==Sex.MALE){ System.out.println("得到一个MALE类型的枚举常量"); } } }

    6 优点: (1) 枚举常量更简单安全 . (2) 枚举具有内置方法 ,代码更优雅 缺点:不可继承,无法扩展. 7 (1) 枚举本身就是一个类,其构造方法默认为私有的,且都是默认继承与 java.lang.Enum. (2) 枚举可以避免反射和序列化问题 .

    8 Lambda表达式的 优点很明显,在代码层次上来说使代码变得非常简洁. 缺点 也明显, 使代码变得不易读,也不易进行调试.

    用 普通方法创建线程 Thread t = new Thread(new Runnable() { @Override public void run() { System.out.println("使用匿名类创建 Runnable 子类对象"); } }); 用 lambda表达式创建线程: Thread t = new Thread(() -> { System.out.println("使用匿名类创建 Thread 子类对象"); });
    Processed: 0.013, SQL: 10