引入

多态确实提高了扩展性,但是并未达到最好,看一下例子

package com.hz;
public interface Pay {
    void NFC();   // 移动支付
}
package com.hz;
class Alipay implements Pay{

    @Override
    public void NFC() {
        System.out.println("使用支付宝支付");
    }
}

class WeChatPay implements Pay{

    @Override
    public void NFC() {
        System.out.println("使用微信支付");
    }
}

package com.hz;
class Test{
    public static void main(String[] args) {
        // 如果还有其他支持,还要加一堆判断。 多态的无奈

//        String payType = "微信";
        String payType = args[0];

        Pay pay = null;
        if (payType.equals("微信")){
            pay = new WeChatPay();
        }else if(payType.equals("支付宝")){
            pay = new Alipay();
        }

        assert pay != null;
        pay.NFC();
    }
}

如果使用反射

package com.hz;
class Test{
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
		// 配置文件配置要使用的类
        String payClass = "com.hz.WeChatPay";
        Pay pay = (Pay) Class.forName(payClass).newInstance();
        pay.NFC();
    }
}

反射机制

  • Java可以称为 "准动态语言"。即java有一定的动态性,可以利用反射机制获得类似动态语言的特性。

  • 反射机制允许程序在执行期间借助于ReflectionAPI获取任何类的内部信息,并且能够直接操作任意对象的内部属性及方法。

  • 反射机制使得Java编程时更加灵活,从而达到最佳的扩展性。

如何获得Class对象

  • 如果已有具体的类,通过类的class属性获取,最为安全可靠且性能最高的方法

    Class c = Person.class

  • 已知某个类的实例,调用此实例的getClass()方法获取Class对象

    Class c = person.getClass()

  • 已知一个类的全名且在类路径下,可以通过Class类的静态方法forName()获取

    Class c= ClassforName(“com.hz.Person”);

  • 内置基本数据类型可以直接使用 类名.Type

    Person.Type

  • 用ClassLoader

类型的Class对象

  • class:外部类、成员(成员内部类、静态内部类),局部内部类,匿名内部类。
  • interface:接口
  • []:数组
  • enum:枚举
  • annotation:注解
  • primitive type:基本数据类型
  • void
Class c1= Object.class;         //类
Class c2= Runnable.class;       //接口
Class c3= String[].class;       //一维数组
Class c4= int[][].class;        //二维数组
Class c5=Override.class;        //注解
Class c6= ElementType.class;    //枚举
Class c7= Integer.class;        //基本数据类型
Class c8= void.class;           //void
Class c9= Class.class;          //Class

常用方法

[ 示例类]

以下都基于这个类来说明

package com.hz;
import java.lang.reflect.Constructor;

enum Gender{
    Male, Female
}

public class Person {
    public String name;
    int age;
    Gender sex;

    public Person() {
    }
    
    private Person(String name){
    }

    public Person(String name, int age, Gender sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Gender getSex() {
        return sex;
    }

    public void setSex(Gender sex) {
        this.sex = sex;
    }

    private void doSth(){
        System.out.println("干活干活");
    }
    
    private List<String>  printCollection(List<Integer> list, Map<Integer, String> map){
        System.out.println(list);
        System.out.println(map);
        List<String> ls = new ArrayList<>();
        ls.add("张三");
        return ls;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                '}';
    }
}

获取类

Class.forName(String classPath) 返回指定类名name对应的Class对象

try {
      Class clz = Class.forName("com.hz.Person");
  } catch (ClassNotFoundException e) {
      e.printStackTrace();
  }

获取构造器

getDeclaredConstructors()     获取所有的构造函数

getDeclaredConstructor(paramTypes)   获取一个所有的构造函数

getConstructors()           获取所有公开的构造函数

getConstructor(paramTypes)       获取单个公开的构造函数

所有构造器

Class clz = Class.forName("com.hz.Person");
Constructor[] constructors = clz.getConstructors();
for (Constructor constructor : constructors) {
    System.out.println(constructor);
}

无参构造器

Class clz = Class.forName("com.hz.Person");
Constructor constructor = clz.getConstructor();
System.out.println(constructor);

有参构造器

Class clz = Class.forName("com.hz.Person");
Constructor constructor = clz.getDeclaredConstructor(
    String.class, 
    int.class, 
    Gender.class);
System.out.println(constructor);

私有构造器

Class clz = Class.forName("com.hz.Person");
Constructor declaredConstructor = clz.getDeclaredConstructor(String.class);
System.out.println(declaredConstructor);

获取修饰符

getModifiers() 获取所有修饰符

返回类型:int

返回值: 修饰符之和,比如:public static void test(){} 返回值是: public + static

修饰符
默认 0
public 1
private 2
protected 4
static 8
final 16
synchronized 32
volatile 64
transient 128
native 256
interface 521
abstract 1024
Class clz = Class.forName("com.hz.Person");
Constructor declaredConstructor = clz.getDeclaredConstructor(String.class);
final int modifiers = declaredConstructor.getModifiers();
System.out.println(modifiers);

// Modifier 类可以判断修饰符, 这里判断是否是私有
System.out.println(Modifier.isPrivate(modifiers));

获取名字

getName()     获取全名 例如:com.hz.Person

getSimpleName()   获取类名 例如:Person

Class clz = Class.forName("com.hz.Person");
System.out.println(clz.getName());
System.out.println(clz.getSimpleName());

获取包

getPackage()

Package aPackage = clz.getPackage();

获取接口

getSuperclass()

System.out.println(clz.getSuperclass());

获取方法

getMethods()   获取所有公开的方法

getDeclaredMethods() 获取所有的方法

getMethod(String name) 获取单个public方法,参数为方法名

getDeclaredMethod(String name)   获取单个任意方法,参数为方法名

Class clz = Class.forName("com.hz.Person");
System.out.println(Arrays.toString(clz.getMethods()));
System.out.println(Arrays.toString(clz.getDeclaredMethods()));
System.out.println(clz.getMethod("getName"));
System.out.println(clz.getDeclaredMethod("doSth"));

获取字段

getFields()    获取所有的public字段

getDeclaredFields()   获取所有的字段

getField(String name)   获取单个public字段,参数为指定字段  

getDeclaredField(String name)   获取单个任意字段,参数为指定字段

Class clz = Class.forName("com.hz.Person");
System.out.println(Arrays.toString(clz.getFields()));
System.out.println(Arrays.toString(clz.getDeclaredFields()));
System.out.println(clz.getField("name"));
System.out.println(clz.getDeclaredField("age"));

实例化对象

newInstance(Object initargs)

Class clz = Class.forName("com.hz.Person");
// 无参构造器
Constructor constructor = clz.getConstructor();
System.out.println(constructor.newInstance());

// 有参构造器
constructor = clz.getConstructor(String.class, int.class, Gender.class);
System.out.println(constructor.newInstance("张三", 16, Gender.Male));

安全检查

  • setAccessible 作用是启用和禁用访问安全检查的开关

  • 提高反射的效率, 如果反射代码频繁被调用,请设置为true

  • 私有成员可以被读写,私有方法可以被调用

setAccessible(true)   禁用检查

setAccessible(false)   启用检查

Class clz = Class.forName("com.hz.Person");
Constructor constructor = clz.getConstructor();
Person person= (Person) constructor.newInstance();

Field age = clz.getDeclaredField("age");
// 默认是false
age.setAccessible(true);
age.setInt(person, 22);
System.out.println(person);

方法调用

method.invoke(Object obj, Object... args)

obj:实例方法,传类对象; 静态方法,传null

args:方法的参数,没有写null或不写

Class clz = Class.forName("com.hz.Person");
Constructor constructor = clz.getConstructor();
Person person= (Person) constructor.newInstance();

Method getName = clz.getMethod("setName", String.class);
getName.invoke(person, "李四");
System.out.println(person);
posted on 2020-09-16 17:47  残月影歌  阅读(125)  评论(0编辑  收藏  举报