反射 枚举和lambda

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 子类对象");
    });

你可能感兴趣的:(反射 枚举和lambda)