Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。. 这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。. 反射被视为动态语言的关键
反射的使用 反射第一步:获取要操作的类的类对象
类对象:Class类
JVM(java虚拟机)每当加载一个类时(读取要操作的类的字节码文件),就会实例化一个Class的实例来表示刚加载的这个类。在JVM内部每个被加载的类都有且只有一个Class的实例与之对应。通过这个Class实例我们可以在程序运行期间了解其表示的类的一切信息(类名,有哪些方法,那些属性,那些构造器等)并在运行期间进行操作
获取类对象的方式有三种:
1:类名.class
Class cls = String.class;
Class cls = int.class;(基本类型只有这一种方式获取类对象)
2:Class.forName(String className)
参数为要操作的类的完全限定名:包名.类名
Class cls = Class.forName("java.lang.String");
3:ClassLoader类加载形式获取类对象
*/
String name = cls.getName();//获取类名(完全限定名)
System.out.println(name);
name = cls.getSimpleName();//仅获取类名
System.out.println(name);
//列如:
Scanner scanner=new Scanner(System.in);
System.out.println("请输入一个类名:");
String className=scanner.nextLine();
Class cls=Class.forName(className);
String name = cls.getName();//获取类名(完全限定名)
System.out.println(name);
name = cls.getSimpleName();//仅获取类名
System.out.println(name);
Method[] methods=cls.getMethods();
for (Method method:methods){
System.out.println(method.getName());
}
使用反射机制实例化对象
1.加载类对象 调用的包名.类名
Class cls=Class.forName("reflect.Person");
//2.Class提供了一个方法:newInstance()方法,可以调用其表示的类的公开的无参构造进行实例化
Object o=cls.newInstance();
//列如:
Scanner scanner=new Scanner(System.in);
while (true){
System.out.println("请输入一个类名:");
String className=scanner.nextLine();
Class cls=Class.forName(className);
Object o=cls.newInstance();
System.out.println(o);
}
获取类的公开方法:
Method[] methods=cls.getMethods();
for (Method method:methods){
System.out.println(method.getName());
}
获取构造器:
Class cls=Class.forName("reflect.Person");
//Constructor类的每一个实例用于表示一个构造方法
// Constructor c=cls.getConstructor();//不传参获取的就是无参构造器
Constructor c=cls.getConstructor(String.class);//Person(String name)
Object o=c.newInstance("王五");//new Person("王五")
System.out.println(o);
Constructor cs=cls.getConstructor(String.class,int.class);
Object oc=cs.newInstance("132131w",126);
System.out.println(oc);
调用方法:
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(className);
//2.实例化
Object obj=cls.newInstance();//使用默认构造器实例化对象,Person p=new Person
//根据类对象获取要操作的方法对象
Method method=cls.getMethod(methodName);
//调用方法
method.invoke(obj);//p.sayGoodBye
//调用一个参数的方法
Class cls=Class.forName("reflect.Person");
Object obj=cls.newInstance();
Method method=cls.getMethod("say",String.class);
method.invoke(obj,"大家好~~~");
//调用两个的参数方法
Method method1=cls.getMethod("say", String.class, int.class);
method1.invoke(obj,"今天周末",2);
调用私有方法(一般不要使用):
Class cls=Class.forName("reflect.Person");
Object obj=cls.newInstance();
Method method=cls.getDeclaredMethod("dosome");
if (method.getModifiers()== Modifier.PRIVATE){//判断该方法是否为private方法
method.setAccessible(true);//强行打开访问
}
method.invoke(obj);//p.dosome()
在反射机制中判定是否有被某个注解标注的类
public static void main(String[] args) throws URISyntaxException, ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {
File dir=new File(
ReflectDemo7.class.getResource(".").toURI()
);
File[] subs=dir.listFiles(f->f.getName().endsWith(".class"));
for (File file:subs) {
String fileName=file.getName();
String className=fileName.substring(0,fileName.indexOf("."));
Class cls=Class.forName("reflect."+className);
//判断当前类是否被注解@AutoRunClass标注过
// boolean tf=cls.isAnnotationPresent(AutoRunClass.class);
// System.out.println(className+"是否被标注"+tf);
if (cls.isAnnotationPresent(AutoRunClass.class)){
Object o=cls.newInstance();
Method[] methods=cls.getDeclaredMethods();
for (Method method:methods) {
if (method.isAnnotationPresent(AutoRun.class)){
AutoRun ar=method.getAnnotation(AutoRun.class);
int value=ar.value();
System.out.println("@AutoRun("+value+")");
System.out.println("自动调用"+cls.getName()+"的方法"+method.getName()+"()");
method.setAccessible(true);
method.invoke(o);
}
}
}
}
}
调用含有s的无参方法
public class Text {
public static void main(String[] args) throws URISyntaxException {
File file=new File(Text.class.getResource(".").toURI());
System.out.println(file.getAbsolutePath());
File[] subs=file.listFiles(f->f.getName().endsWith(".class"));
for (File sub:subs) {
String fielName=sub.getName();
String className=fielName.substring(0,fielName.indexOf("."));
System.out.println("类名"+className);
try {
Class cls = Class.forName("reflect."+className);
Object obj=cls.newInstance();
Method[] methods=cls.getDeclaredMethods();
for (Method method:methods) {
if (method.getModifiers()== Modifier.PUBLIC
&& method.getParameterCount()==0){
System.out.println("自动执行"+cls.getName()+"的方法"+method.getName()+"()");
method.invoke(obj);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
调用别的类的main方法:
//定位包: map包
File dir=new File(
Text2.class.getClassLoader().getResource("./map").toURI()
);
System.out.println(dir.getAbsolutePath());
File[] subs=dir.listFiles(f->f.getName().endsWith(".class"));
for (File sub:subs) {
String fileName=sub.getName();
String className=fileName.substring(0,fileName.indexOf("."));
try {
Class cls = Class.forName("map."+className);
System.out.println("准备执行"+cls.getName()+"的main方法");
Method method=cls.getMethod("main",String[].class);
method.invoke(null,(Object)new String[]{});
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
System.out.println("没有main方法");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
调用在同一包含有s的无参方法:
//定位包: map包
File dir=new File(
Text2.class.getClassLoader().getResource("./map").toURI()
);
System.out.println(dir.getAbsolutePath());
File[] subs=dir.listFiles(f->f.getName().endsWith(".class"));
for (File sub:subs) {
String fileName=sub.getName();
String className=fileName.substring(0,fileName.indexOf("."));
try {
Class cls = Class.forName("map."+className);
System.out.println("准备执行"+cls.getName()+"的main方法");
Method method=cls.getMethod("main",String[].class);
method.invoke(null,(Object)new String[]{});
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
System.out.println("没有main方法");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
注解:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface AutoRunClass {
int value() default 1;
}



