反射是java的动态机制,可以允许我们在程序[运行期间]再确定实例化,调用某个方法,操作某个属性。反射机制大大的提高了代码的灵活度,但是会有更高的系统开销和较慢的运行效率。 因此反射机制不能被过度的使用.
类对象 Class的实例
JVM在加载一个类的class文件时,就会同时创建一个Class的实例,使用该实例记录加载的 类的一切信息(类名,有哪些属性,哪些方法,哪些构造器等)。并且每个被JVM加载的类都有 且只有一个Class的实例与之对应。 反射的第一步就是获取要操作的类的类对象,以便程序在运行期间得知要操作的类的一切信息 然后对其进行响应的操作。
获取一个类的类对象的常见方式:
1:类名.class
例如:
Class cls = String.class;
Class cls = int.class;
注意:基本类型获取类对象只有这一种方式。
2:Class.forName(String className)
例如:
Class cls = Class.forName("java.lang.String");
这里传入的类名必须是类的完全限定名,即:包名.类名
3:还可以通过类加载器形式完成
Scanner scanner = new Scanner(System.in);
System.out.println("请输入类名:");
String className = scanner.nextLine();
/*
java.util.ArrayList
java.util.HashMap
java.io.ObjectInputStream
java.lang.String
*/
Class cls = Class.forName(className);
//获取当前类对象所表示的类的完全限定名
String name = cls.getName();
System.out.println(name);
//仅获取类名(不包含包名)
name = cls.getSimpleName();
System.out.println(name);
Package getPackage() 获取当前类对象所表示的类的包,返回的Package实例表示该包信息
Package pack = cls.getPackage();
String packName = pack.getName();
System.out.println("包名"+packName);
Method[] getMethods() 获取当前类对象所表示的类中定义的所有公开方法,包含从超类继承下来的方法 java.lang.reflect.Method类,方法对象 该类的每一个实例用于表示某个类中定义的一个方法,通过它可以获取其表示的方法中的 相关信息(方法名,参数个数,参数类型,返回值类型等等,并且还可以调用这个方法)
Method[] methods = cls.getMethods();
for(Method method : methods){
System.out.println(method.getName()+"()");
}
2.使用反射机制实例化对象
类对象直接提供了可以通过公开的无参构造器实例化的功能
Class.newInstance()
package reflect;
/**
* 使用当前类测试反射机制
*/
public class Person {
private String name = "张三";
private int age = 18;
public Person(){}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void sayHello(){
System.out.println(name+":hello!");
}
public void sayHi(){
System.out.println(name+":Hi!");
}
public void watchTV(){
System.out.println(name+":看电视");
}
public void sing(){
System.out.println(name+":唱歌");
}
public void doSomeThing(String something){
System.out.println(name+"正在做"+something);
}
public void doSomeThing(String something,int count){
for(int i=0;i<count;i++) {
System.out.println(name + "正在做" + something + i + "次");
}
}
private void dosome(){
System.out.println("我是Person的私有方法dosome()!!!!!!");
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package reflect;
import java.util.Scanner;
/**
* 使用反射机制实例化对象
*/
public class ReflectDemo2 {
public static void main(String[] args) throws Exception {
Object p = new Person();
System.out.println(p);
//1获取要实例化的类的类对象
// Class cls = Class.forName("reflect.Person");
Scanner scanner = new Scanner(System.in);
System.out.println("请输入要实例化的类名:");
String className = scanner.nextLine();
Class cls = Class.forName(className);
//2类对象直接提供了可以通过公开的无参构造器实例化的功能
Object obj = cls.newInstance();
System.out.println(obj);
}
}
3.使用有参构造器进行实例化
import java.lang.reflect.Constructor;
public class ReflectDemo3 {
public static void main(String[] args) throws Exception {
Person p = new Person("李四",22);
System.out.println(p);
Class cls = Class.forName("reflect.Person");
//获取Person的构造器Person(String,int)
// cls.getConstructor();//不穿任何参数时获取的仍然是无参构造器
Constructor c = cls.getConstructor(String.class,int.class);
//new Person("王五",55);
Object obj = c.newInstance("王五",55);//实例化时要传入构造器要求的实际参数
System.out.println(obj);
}
}

4. 使用反射机制调用方法
public class ReflectDemo4 {
public static void main(String[] args) throws Exception {
Person p = new Person();
p.sayHello();
Scanner scanner = new Scanner(System.in);
System.out.println("请输入类名:");
String className = scanner.nextLine();
System.out.println("请输入方法名:");
String methodName = scanner.nextLine();
//1实例化
// Class cls = Class.forName("reflect.Person");
Class cls = Class.forName(className);
//Object obj = new Person();
Object obj = cls.newInstance();
//2调用方法
//2.1通过类对象获取要调用的方法
// Method method = cls.getMethod("sayHello");//获取的是无参的sayHello方法
Method method = cls.getMethod(methodName);
//2.2通过获取的方法对象来调用该方法
// obj.sayHello() 因为obj指向的是及一个Person对象,因此反射机制可以调用到它的sayHello()
method.invoke(obj);
}
}
5. 调用有参方法


6.调用私有方法
getMethod(),getMethods()
它们都是获取Class所表示的类的所有公开方法,包含从超类继承的
getDeclaredMethod(),getDeclaredMethods()
这两个方法获取的都是Class所表示的类中当前类自身定义的方法。包含私有方法
package reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectDemo6 {
public static void main(String[] args) throws Exception {
// Person p = new Person();
// p.dosome();
Class cls = Class.forName("reflect.Person");
Object obj = cls.newInstance();
/*
getMethod(),getMethods()
它们都是获取Class所表示的类的所有公开方法,包含从超类继承的
getDeclaredMethod(),getDeclaredMethods()
这两个方法获取的都是Class所表示的类中当前类自身定义的方法。包含私有方法
*/
// Method[] methods = cls.getDeclaredMethods();
// for(Method method : methods){
// System.out.println(method.getName());
// }
Method method = cls.getDeclaredMethod("dosome");
method.setAccessible(true);//强行打开dosome方法的访问权限
method.invoke(obj);//p.dosome()
}
}
8.面试ti
main方法上的参数String[] args的作用是
在命令行上使用java命令指定当前类时,可以传递参数进来,此时会被main上的String[] args接收
例如:
java ReflectDemo7 arg1 arg2 arg3 main方法执行后,args数组就有三个元素,对应的就是"arg1","arg2","arg3"
9.自动调用与当前类ReflectDemo7所在同一个包中,自动调用本类自己定义的无参的公开方法
public class ReflectDemo7 {
public static void main(String[] args) throws Exception {
/*
两个开发中常用的相对路径
*/
//1这里的当前目录表示的是当前ReflectDemo7这个类所在最外层包的上一级目录
// File dir = new File(
// ReflectDemo7.class.getClassLoader().getResource(".").toURI()
// );
//2这里的当前目录就是当前类所在的目录
File dir = new File(
ReflectDemo7.class.getResource(".").toURI()
);
System.out.println(dir.getName());
//通过当前类ReflectDemo7的类对象获取所在的包名
String packageName = ReflectDemo7.class.getPackage().getName();
System.out.println("ReflectDemo7类的包名是:"+packageName);
//获取ReflectDemo7.class文件所在的目录中所有.class文件
File[] subs = dir.listFiles(f->f.getName().endsWith(".class"));
for(File sub : subs){
//获取字节码文件的文件名
String fileName = sub.getName();
System.out.println(fileName);
/*
由于java命名要求,文件名必须与类名一致,所以我们可以通过文件名得知该字节码
文件中保存的类的类名
*/
String className = fileName.substring(0,fileName.indexOf("."));
// System.out.println("类名:"+className);
//加载该类的类对象
Class cls = Class.forName(packageName+"."+className);
Object obj = cls.newInstance();
// System.out.println("加载的类为:"+cls.getName());
//通过类对象获取本类定义的所有方法
Method[] methods = cls.getDeclaredMethods();
//遍历每个方法,检查哪个方法是无参的
for(Method method : methods){
if(
method.getParameterCount()==0
&&
method.getModifiers() == Modifier.PUBLIC
){
System.out.println("自动调用"+className+"的方法:"+method.getName());
method.invoke(obj);
}
}
}
}
}
10.自动调用reflect.Person类中所有无参且方法名中含有say的方法
/**
* 自动调用reflect.Person类中所有无参且方法名中含有say的方法
*
* 提示:
* Method类上定义了一个方法:int parameterCount(),该方法可以返回当前Method对象表示的
* 方法的参数个数。
*/
public class Test2 {
public static void main(String[] args) throws Exception {
Class cls = Class.forName("reflect.Person");
Object obj = cls.newInstance();
//获取所有方法
Method[] methods = cls.getMethods();
for (Method method : methods){
if(method.getName().contains("say")
&&
method.getParameterCount()==0
){
System.out.println("自动调用方法:"+method.getName());
method.invoke(obj);
}
}
}
}
/**
* 使用反射机制实例化10个Person对象
* Person对象中的name顺序为:test1--test10
* age顺序为:21-30
* 并存入一个集合
*/
public class Test1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
List<Person> list =new ArrayList<>();
Class cls = Class.forName("reflect.Person");
Constructor c =cls.getConstructor(String.class,int.class);
for (int i = 0; i < 10; i++) {
String a ="test"+(i+1);
int b =21+i;
Object obj =c.newInstance(a,b);
System.out.println(obj);
list.add((Person) obj);
}
System.out.println(list);
}
}
1198

被折叠的 条评论
为什么被折叠?



