java反射机制
放射机制是一种动态机制,允许我们程序在运行期间确定实例化对象的操作,方法调用的操作和属性赋值对等
*
反射机制可以大大提高代码灵活度,但是也会带俩更多的系统开销和降低运行性能。因此反射只能在关键地方使用而不能过度依赖。
1.获取反射第一步:获取要操作的类的类对象
Class类 称为:类的对象
该类的每一个实例用于表示已经被JVM加载的一个类,并且每个被JVM加载的类都有且只有一个类对象与之关联通过类对象我们可以得知其表示的类的一切信息:类名,有哪些属性,方法,构造器并可以获取他们以便在运行期间调用
获取一个类的类对象有三种方式
1.类名.class
* 例如:String.class
* ArrayList.class
*
2.:Class.forName(String className)
* Class提供了一个静态方法forName,可以根据类的完全限定名(包名.类名)形式
* 获取该类的类对象
*
3.ClassLoader类加载器形式
//获取String的类
// Class cls = String.class;//优点是简单直接,但是缺点是硬编码获取
/*
* 该方法会抛出ClassNotFoundException,当给定的类的完全限定名无效时
* 会抛出该异常
*/
// Class<?> cls = Class.forName("java.lang.String");
System.out.println("请输入一个类名:");
Scanner scan = new Scanner(System.in);
String className = scan.nextLine();
Class<?> cls = Class.forName(className);
//获取类名
String name = cls.getName();
System.out.println(name);
/*
* Method类的每一个实例用于表示某个类中的某个方法
*
* Class提供的方法:
* Method[] getMethods()
* 可以获取Class表示的类的所有公有方法
*/
System.out.println("获取本类中的所有公有方法,包含从超类继承的方法");
Method[]methods = cls.getMethods();
for(Method m:methods){
System.out.println(m.getName());
}
System.out.println("获取本类中的所有方法(不包含继承的方法)");
methods = cls.getDeclaredMethods();
for(Method m:methods){
System.out.println(m.getName());
}
2.使用反射机制实例化对象
2.1 实例化
//硬编码方式实例化
Person p = new Person();
System.out.println(p);
ArrayList a = new ArrayList();
System.out.println(a);
/*
* 使用反射机制:
* 1.加载要实例化对象的类的类对象
* 2.通过类对象的newInstance方法实例
*/
//实例化Person
Class<?>cis = Class.forName("reflect.Person");
//要注意newInstance方法要求Class表示的类必须有无参构造器
Object obj = cis.newInstance();
System.out.println(obj);
2.2 调用有参构造方法
//硬编码方式调用有参构造方法
Student stu = new Student("tom",44);
System.out.println(stu);
/*
* 利用有参构造实例化对象
* 1.加载要实例化的类的类对象
* 2.通过类对象获取指定的构造方法
* 3.利用该构造方法实例化
*/
//1
Class cls1 = Class.forName("reflect.Student");
//2 Student(String name,int age)
Class[]arg = {String.class,int.class};
Constructor c = cls1.getConstructor(arg);
Object o1 = c.newInstance("jock",19);
System.out.println(o1);
3.利用反射调用方法:
1.加载类对象
2.实例化
3.通过类对象获取要调用的方法
4.调用该方法
Person p = new Person();
p.sayHello();
/*
* 利用反射调用方法:
* 1.加载类对象
* 2.实例化
* 3.通过类对象获取要调用的方法
* 4.调用该方法
*/
Scanner scan = new Scanner(System.in);
System.out.println("请输入类名");
String className = scan.nextLine();
System.out.println("请输入方法名");
String methodName = scan.nextLine();
4.调用有参数的方法
Person p = new Person();
p.say("123");
p.say("tom",16);
Class<?>cls = Class.forName("reflect.Person");
Object o =cls.newInstance();
//p.say("123");
Method m = cls.getMethod("say", String.class);
m.invoke(o, "hey!");
//p.say("jok",16)
Method m2 = cls.getMethod("say", String.class,int.class);
m2.invoke(o, "jok",16);
5.使用反射机制调用私有方法
使用反射机制调用私有方法
这样做可能破坏封装性
// Person p = new Perosn();
// p.dosome();//编译不通过
Class<?>cls = Class.forName("reflect.Person");
Object o = cls.newInstance();
//获取dosome方法
Method m = cls.getDeclaredMethod("dosome");
m.setAccessible(true);//强行访问
m.invoke(o);
测试类
package reflect;
/**
* 使用当前类测试反射机制
* @author 毛
*
*/
public class Person {
public void sayHello(){
System.out.println("Person:Hello");
}
public void say(String info){
System.out.println("Person:"+info);
}
public void say(String name,int age){
System.out.println("Paerson:name:"+name+",age:"+age);
}
private void dosome(){
System.out.println("Person中的私有方法dosome");
}
}