反射机制简笔

反射(Reflect)

1.反射:把Java类中的各种成分映射成单独的Java对象进行操作。

2.类的对象:基于某个类new出来的对象,也称为实例对象。

3.类对象:类加载的产物,封装了一个类的所有信息(类名,父类,接口,属性,方法,构造方法)。

获取类的类对象

前两种方式依赖性太强,推荐使用第三种方式,耦合性低,比较灵活。

通过对象获取
Wife wife = new Wife("艾米莉亚"16);
Class<?> class1 = wife.getClass();
类名.class
//class是每个类都有的属性
Class<?> class2 = Student.class;
Class.forName()
//会抛异常
Class<?> class3 = Class.forName("必须是类的带包全名");

获取构造方法

获取所有构造方法
Constructor<?>[] constructors = class1.getConstructors();
for (Constructor<?> constructor : constructors) {
    System.out.println(constructor);
}
获取带参构造方法
Constructor<?> constructor = class1.getConstructor(String.class, int.class, String.class);
Student s1=(Student) constructor.newInstance("艾米莉亚",18,"女神");
获取无参构造方法
Constructor constructor2=class1.getConstructor();
Student s2=(Student) constructor2.newInstance();
//简写
Student s1 = (Student)class1.newInstance()

获取方法

获取所有方法
//getMethods()获取公开的所有方法,包括继承的公开方法;没有私有、默认,保护的方法
Method[] methods = class1.getMethods();
//getDeclaredMethods() 获取类中所有的方法,包含私有、默认、保护的方法。不包括继承的。
Method[] methods =class1.getDeclaredMethods();
获取单个方法
Student s1 = (Student) class1.newInstance();
//获取无参方法
Method methodShow=class1.getMethod("show");
methodShow.invoke(s1);//调用
//获取带参方法
Method methodShow2 = class1.getMethod("show", String.class);
methodShow2.invoke(s1,"上海");
//获取静态方法
Method staticMethod=class1.getMethod("staticMethod");
staticMethod.invoke(null);
//获取私有方法
Method privateMethod=class1.getDeclaredMethod("privateMethod");
//设置访问权限失效
privateMethod.setAccessible(true);
privateMethod.invoke(s1);

给属性赋值

Class<?> class1 = Class.forName("com.qf.gp2002_2.Person");
Object person = class1.newInstance();
反射赋值,不符合封装
Field name = class1.getDeclaredField("name");
Field age = class1.getDeclaredField("age");
Field gender = class1.getDeclaredField("gender");
获取set方法,麻烦,不知道方法形参属性
Method setName = class1.getMethod("setName", String.class);
Method setAge = class1.getMethod("setAge", int.class);
Method setGender = class1.getMethod("setGender", String.class);
内省(透视类的内部)

https://blog.csdn.net/qq_41033290/article/details/85834927

属性:如果类中包含了getXxx、setXxx、isXxx开头的方法,表示类中有xxx属性

//获取所有属性
//        BeanInfo beanInfo = Introspector.getBeanInfo(class1);
//        PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
//        for (PropertyDescriptor pd : pds) {
//            System.out.println(pd.getName());
//        }

//给属性赋值
        //name属性
        PropertyDescriptor pdName=new PropertyDescriptor("name", class1);
        System.out.println(pdName.getPropertyType());//获取属性类型
        Method writeMethod = pdName.getWriteMethod(); //setName()方法
        writeMethod.invoke(person,"铸玺");

        PropertyDescriptor pdAge=new PropertyDescriptor("age", class1);
        System.out.println(pdAge.getPropertyType());
        Method writeMethod1 = pdAge.getWriteMethod();
        writeMethod1.invoke(person,20);

        PropertyDescriptor pdGender=new PropertyDescriptor("gender",class1);
        System.out.println(pdGender.getPropertyType());
        Method writeMethod2 = pdGender.getWriteMethod();
        writeMethod2.invoke(person,"男");

        System.out.println("-----------------------");
//获取属性
        Method readMethod = pdName.getReadMethod();//getName
        System.out.println(readMethod.invoke(person));
        Method readMethod1 = pdAge.getReadMethod();//getAge
        System.out.println(readMethod1.invoke(person));
        Method readMethod2 = pdGender.getReadMethod();//getGender
        System.out.println(readMethod2.invoke(person));

单例模式

1.要求整个程序只有一个对象。

2.步骤:

(1)私有化构造方法

(2)在类内部创建一个对象

(3)通过公开的方法返回这个对象

饿汉式

类一加载,对象就初始化。
缺点:生命周期太长,浪费空间。优点:线程安全。

public class SingleTon {
    //1私有化构造方法
    private SingleTon(){}
    //2创建对象
    private static final SingleTon instance=new SingleTon();
    //3通过公开的方法,返回这个对象
    public static SingleTon getInstance(){
        return instance;
    }
}

懒汉式

好处:生命周期短,节省空间

缺点:线程不安全,必须使用同步解决

public class SingleTon2 {
    //(1)私有化构造方法
    private static boolean flag=false;
    private SingleTon2(){
        if(flag){
            throw new RuntimeException("不能反射破解");
        }
    }
    //(2)在类内部创建一个对象
    private static volatile SingleTon2 instance;
    //(3)通过公开的方法,返回这个对象
    public static  SingleTon2 getInstance(){
        //判断锁是否可用效率低
        if(instance==null) {//目的:提高效率, double check双重检查
            synchronized (SingleTon2.class) {
                if (instance == null) {
                    //(1)new  (2)dup  (3)invokespecial  (4)astore
                    // 1 2 3 4
                    // 1 2 4 3  多线程问题?
                    instance = new SingleTon2();
                    flag=true;
                }
            }
        }
        return instance;
    }
}

静态内部类写法

优点:1 安全 2 生命周期短,节省空间

public class SingleTon3 {
    //1私有化构造方法
    private SingleTon3(){}
    //2在静态内部类中创建对象
    private static class Holder{
        private static final SingleTon3 instance=new SingleTon3();
    }
    //3通过公开方法返回这个对象
    public static SingleTon3 getInstance(){
        return Holder.instance;
    }
}

枚举

1.枚举类:规定了取值范围的数据类型。

2.注意事项:

(1)枚举常量之间用逗号隔开,最后分号可写也可不写,如果后面有代码,必须加分号

(2)枚举包含私有构造方法,属性和普通方法,必须写在常量后面。

public enum Gender {

    MALE,FEMALE;

    private Gender(){

    }
    public String value;

    public void show(){
        System.out.println(value);
    }

}

注解

注解中:

(1)只能包含公开属性:1.基本类型,2.String类型,3.Class类型,4.枚举类型,5.注解类型,6.以及上述类型的一维数组。

(2)定义属性时,可以给默认值

(3)如果注解中使用value属性名,使用可以不用写value

public @interface MyAnnotation {
    int value;
}
通过反射获取方法注解属性
@MyAnnotation(100)
public class Test{
  public void show(){
      Class<?> class1 = Class.forName("Test的带包全名");
      class1.getMethod("show");
      Annotation[] annotations = show.getAnnotations();
      for (Annotation annotation : annotations) {
          System.out.println(annotation.toString());
      }
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值