反射是java的动态机制,允许程序在[运行期间]再确定对象实例化,方法调用,属性操作等
反射可以提高代码的灵活度和可扩展性,但是运行效率较慢,开销较大,避免过度使用
类对象:
Class类的实例
JVM加载一个类的字节码文件同时会实例化一个Class的实例用来记录加载的类的信息.
那么这个Class的实例就可以反映出加载的类的相关信息(类名,包信息,构造器,方法,属性等)
从而在程序运行期间供我们了解一个类的内容以便进行操作.
在JVM内部,每个被加载的类都有且只有一个Class的实例.
反射的第一步是获取一个类的类对象(Class的实例)
获取方式一:
获取方式二:
用于获取其表示的类的相关信息
public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
Person person = new Person();
System.out.println(person);
Class cls = Class.forName("reflect.Person");
System.out.println(cls.newInstance());
Scanner scanner = new Scanner(System.in);
System.out.println("请输入类名");
Class clsName = Class.forName(scanner.nextLine());
System.out.println(clsName.newInstance());
}
public class Person {
private String name = "张三";
private int age = 22;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public static void main(String[] args) throws InvocationTargetException,
InstantiationException, IllegalAccessException, NoSuchMethodException,
ClassNotFoundException {
Person person = new Person("李四",22);
System.out.println(person);
Class cls = Class.forName("reflect.Person");
Constructor constructor = cls.getConstructor(String.class,int.class);
System.out.println(constructor.newInstance("王五",36));
Constructor constructor1 = cls.getConstructor();
System.out.println(constructor1.newInstance());
}
Method类是反射对象之一,它的每一个实例用于表示一个方法
通过Method对象我们可以得知该方法的相关信息(方法名,参数列表,返回值,访问修饰符等)
还可以通过Method对象调用该方法
public class Person {
private String name = "张三";
private int age = 22;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public void sayHello(){
System.out.println();
}
public void sayHi(){
System.out.println();
}
public void doSome(){
System.out.println();
}
public void sleep(){
System.out.println();
}
public void watchTV(){
System.out.println();
}
public void study(){
System.out.println();
}
public void playGame(){
System.out.println();
}
public void sing(){
System.out.println();
}
public void say(String info){
System.out.println(name+":"+info);
}
public void say(String info,int count){
for (int i=0;i<count;i++){
System.out.println(name+":"+info);
}
}
private void hehe(){
System.out.println("我是Person的私有方法hehe!!");
}
}
public static void main(String[] args) throws ClassNotFoundException {
Scanner scanner = new Scanner(System.in);
Class cls = Class.forName(scanner.nextLine());
Method[] methods = cls.getMethods();
System.out.println("一共:" +methods.length+ "个方法");
for(Method method : methods){
System.out.println(method.getName());
}
}
public static void main(String[] args) throws ClassNotFoundException {
Class cls = Class.forName("reflect.Person");
Method[] methods = cls.getDeclaredMethods();
for(Method method : methods){
System.out.println(method.getName());
}
}
public static void main(String[] args) throws NoSuchMethodException,
ClassNotFoundException {
Class cls = Class.forName("reflect.Person");
Method method = cls.getDeclaredMethod("say", String.class, int.class);
System.out.println("方法名" +method.getName());
System.out.println("参数个数" +method.getParameterCount());
switch (method.getModifiers()){
case Modifier.PUBLIC:
System.out.println("是一个公开方法");
break;
case Modifier.PRIVATE:
System.out.println("是一个私有方法");
break;
case Modifier.PROTECTED:
System.out.println("是一个受保护方法");
}
}
public static void main(String[] args) throws NoSuchMethodException,
ClassNotFoundException, InstantiationException, IllegalAccessException,
InvocationTargetException {
Class cls = Class.forName("reflect.Person");
Object obj = cls.newInstance();
Method method = cls.getDeclaredMethod("doSome");
method.invoke(obj);
}
public static void main(String[] args) throws Exception {
Class cls = Class.forName("reflect.Person");
Object obj = cls.newInstance();
Method method = cls.getDeclaredMethod("say",String.class);
method.invoke(obj, "hello");
Method method1 = cls.getDeclaredMethod("say",String.class,int.class);
method1.invoke(obj, "大家好",5);
}
public static void main(String[] args) throws Exception {
Class cls = Class.forName("reflect.Person");
Method method = cls.getDeclaredMethod("hehe");
method.setAccessible(true);
method.invoke(cls.newInstance());
method.setAccessible(false);
}
public class Teacher {
public String name;
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
'}';
}
}
public static void main(String[] args) throws ClassNotFoundException,
InstantiationException, IllegalAccessException, NoSuchFieldException {
Class cls = Class.forName("reflect.Teacher");
Object object = cls.newInstance();
cls.getDeclaredField("name").set(object, "Bloom");
System.out.println(object);
}
public class ReflectDemo {
public static void main(String[] args) throws URISyntaxException {
File baseDir = new File(
//获取当前类的类加载器中的当前目录的资源路径,并将其转换为URI
ReflectDemo.class.getClassLoader().getResource(".").toURI()
);
System.out.println(baseDir);
File dir = new File(
//获取当前类的类加载器中的当前目录的资源路径,并将其转换为URI
ReflectDemo.class.getResource(".").toURI()
);
System.out.println(dir);
}
}
用于指定当前注解可以被应用的位置
例如
@Target(ElementType.TYPE)
@Target({ElementType.TYPE, ElementType.CONSTRUCTOR})
注解的保留级别
package reflect.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoRunClass {
}
import reflect.annotations.AutoRunClass;
@AutoRunClass
public class Person {
private String name = "张三";
private int age = 22;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public static void main(String[] args) throws ClassNotFoundException {
Class cls = Class.forName("reflect.Person");
boolean mark = cls.isAnnotationPresent(AutoRunClass.class);
if(mark){
System.out.println("被标注");
}else{
System.out.println("没有被标注");
}
}
注解可以定义参数,格式为:
例如:
注解的传参机制
例如:
public @interface AutoRunMethod {
int age()
}
当注解仅有一个参数,且参数名不为value时,正常使用注解传参语法:参数名=参数值
举例:
在Person类的方法sayHello上使用该注解,并指定参数:
@AutoRunMethod(age=3) 此时必须写"作参数名=参数值"
public void sayHello(){
System.out.println(name+":hello!");
}
@AutoRunMethod(3) 编译不通过,因为参数没有指定参数名
public void sayHello(){
System.out.println(name+":hello!");
}
如果注解仅有一个参数时,参数名使用value,则使用注解可以忽略参数名:
public @interface AutoRunMethod {
int value()
}
使用时:
@AutoRunMethod(3) 可以
public void sayHello(){
System.out.println(name+":hello!");
}
注解可以声明多个参数
例如:
public @interface AutoRunMethod {
int age() default 1;
String name();
}
当注解有多个参数时,使用该注解时每个参数都需要使用:参数名=参数值
例如:
@AutoRunMethod(age=2,name="张三")
public void sayHello(){
System.out.println(name+":hello!");
}
实际使用中多个参数传参顺序可以与注解定义时参数顺序不一致
@AutoRunMethod(age=2,name="张三")
public void sayHello(){
System.out.println(name+":hello!");
}
或
@AutoRunMethod(name="张三",age=2)
public void sayHello(){
System.out.println(name+":hello!");
}
当注解有多个参数时,就算其中一个注解取名为value,实际使用时参数名也不可以忽略!
例如:
public @interface AutoRunMethod {
int value();
String name();
}
使用时:
@AutoRunMethod(name="张三",value=2) 可以
@AutoRunMethod(value=2,name="张三") 可以
@AutoRunMethod(name="张三",2) 不可以
@AutoRunMethod(2,name="张三") 不可以
参数指定默认值,仍然在使用时可以忽略
public @interface AutoRunMethod {
int value() default 1;
String name();
}
@AutoRunMethod(name="张三") 可以
public static void main(String[] args) throws Exception {
Class cls = Class.forName("reflect.Person");
Method method = cls.getDeclaredMethod("sayHello");
boolean mark = method.isAnnotationPresent(AutoRunMethod.class);
if(mark){
System.out.println("被标注了");
}else{
System.out.println("没有被标注");
}
}
package reflect.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoRunMethod {
int value() default 1;
}
package reflect;
import reflect.annotations.AutoRunClass;
import reflect.annotations.AutoRunMethod;
@AutoRunClass
public class Person {
private String name = "张三";
private int age = 22;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@AutoRunMethod
public void sayHello(){
System.out.println(name+":hello!");
}
public void sayHi(){
System.out.println();
}
@AutoRunMethod
public void doSome(){
System.out.println("doSome方法");
}
@AutoRunMethod
public void sleep(){
System.out.println("睡觉中");
}
public void watchTV(){
System.out.println();
}
public void study(){
System.out.println();
}
@AutoRunMethod
public void playGame(){
System.out.println("玩游戏");
}
public void sing(){
System.out.println();
}
public void say(String info){
System.out.println(name+":"+info);
}
public void say(String info,int count){
for (int i=0;i<count;i++){
System.out.println(name+":"+info);
}
}
private void hehe(){
System.out.println("我是Person的私有方法hehe!!");
}
}
public static void main(String[] args) throws ClassNotFoundException,
NoSuchMethodException {
Class cls = Class.forName("reflect.Person");
Method method = cls.getDeclaredMethod("sayHello");
if(method.isAnnotationPresent(AutoRunMethod.class)){
AutoRunMethod autoRunMethod = method.getAnnotation(AutoRunMethod.class);
int value = autoRunMethod.value();
System.out.println(value);
}
}
package reflect.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoRunMethod {
int value() default 1;
}
package reflect;
import reflect.annotations.AutoRunClass;
import reflect.annotations.AutoRunMethod;
@AutoRunClass
public class Person {
private String name = "张三";
private int age = 22;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@AutoRunMethod
public void sayHello(){
System.out.println(name+":hello!");
}
}