反射:
反射是一种在程序运行过程中,根据类的名称或者已有对象来获取类的属性,方法,父类等有关信息,以及对象实例的创建和实例类型的判断的一种机制。
反射中常用的类Class,Class类其实表示的是正在运行的Java应用程序中的类和接口。其中Class的forName()方法可以获得Class对象的实例,再通过newInstance()方法即可获得该类的一个新实例。
1.获取一个类Class对象的三种方法: Class类的forName()方法;类的class属性;对象的getClass()方法。以及基本数据类型及其包装类的Class对象;数据类型相同并维度相同时,其对象共享一个Class对象。具体见如下实例:
class.forName();
对象.getClass():
类.class;
public class Test1 {
public static void main(String[] args) throws ClassNotFoundException {
//1.采用目标类的.class属性-->每个类都有包装类(Type属性):
Class c1 = Users.class;
System.out.println(c1);
//2.Object类的getClass()方法:
Users users = new Users();
Class c2 = users.getClass();
//getSimpleClass():只获得类的名称,不包含包名
System.out.println(users);
System.out.println(c2);
//3.Class类的forName()方法:
Class c3 = Class.forName("TestMyself.Users");
System.out.println(c2);
//4.基本数据类型的Class对象,与其包装类的Class对象是Type属性获得
Class i1 = int.class;
Class i2 = Integer.TYPE;
System.out.println(i1==i2);
}
}
2.通过Class对象获得类的:名称;属性;方法;构造方法;
主要方法:
class.getName():获得类名;
class。getDeclaredField():获得属性;
class。getDeclaredConstructor():获得无参构造方法;
class.getDeclaredMethod():获得方法;
1 //通过反射获得类的信息(通过Class对象): 2 //名称;属性;方法;构造; 3 public class Test5 { 4 public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException { 5 Class c1 = Class.forName("TestMyself.Users"); //获得Class对象 6 Class c2 = Class.forName("java.lang.String"); 7 8 //1.获得类名: 9 String name = c1.getName(); 10 String simpleName = c1.getSimpleName(); 11 System.out.println("name:"+name+" simpleName:"+simpleName); 12 System.out.println("================================================="); 13 14 //2.获得属性: 15 Field[] fields = c1.getFields(); //getFields():只能获得public属性 16 for (Field field : fields) { 17 System.out.println(field); 18 } 19 Field[] declaredFields = c1.getDeclaredFields(); //获得全部的属性 20 for (Field declaredField : declaredFields) { 21 System.out.println(declaredField); 22 } 23 System.out.println("============================================================"); 24 25 //3.获得方法: 26 Method[] methods = c1.getMethods(); //getMethods():获得本类和父类的所有public方法 27 for (Method method : methods) { 28 System.out.println("public 方法:"+method); 29 } 30 31 Method[] Methods = c1.getDeclaredMethods();//获得本类的所有方法 32 for (Method declaredMethod : Methods) { 33 System.out.println("本类方法:"+declaredMethod); 34 } 35 //对于要获得重载方法:如果只知道方法名字是找不到具体方法的 36 //("方法名",参数的Class对象) 37 System.out.println("=================================================="); 38 Method getAge = c1.getMethod("getAge", null); 39 Method setName = c1.getMethod("setName", String.class); 40 System.out.println(getAge); 41 System.out.println(setName); 42 43 //4.获得构造器: 44 //获得无参构造 45 System.out.println("====================================================="); 46 Constructor constructor = c1.getConstructor(); 47 48 //获得有参构造:(参数的Class对象) 49 Constructor constructor1 = c1.getConstructor(String.class, int.class, int.class); 50 51 System.out.println("无参构造:"+constructor); 52 System.out.println("有参构造:"+constructor1); 53 54 55 } 56 }
3.通过Class对象来创建对象,并调用执行方法;获得属性并设置属性:
用到的主要方法:
newInstance():使用无参构造创建对象;
getDeclaredConstructor(形参的Class对象。。。)获得有参构造器->construcctor.newInstance(实参。。。):来创建对象;
getDeclaredMethod(“方法名”,形参Class对象。。。):获得一个方法-->method.invoke(对象,实参。。。):执行这个方法;
getDeclaredFiled("属性名"):获得属性;field.setAccessible(true):设置权限来访问私有属性,field.set(对象,实参);
1 public class Test06 { 2 public static void main(String[] args) throws 3 ClassNotFoundException, 4 IllegalAccessException, 5 InstantiationException, 6 NoSuchMethodException, 7 InvocationTargetException, 8 NoSuchFieldException { 9 //1.使用Class对象来获得构造方法,并创建对象 10 Class<?> c = Class.forName("TestMyself.Users"); //创建Class对象 11 12 //用无参构造创建对象 c.newInstance() 13 Users u1 = (Users) c.newInstance(); 14 System.out.println(u1); //重写toString()方法 15 16 //用有参构造创建对象: constructor.newInstance("张三","001","18") 17 Constructor<Users> declaredConstructor = (Constructor<Users>) c.getDeclaredConstructor(String.class, int.class, int.class); 18 Users u2 = declaredConstructor.newInstance("张三", 001, 18); 19 System.out.println(u2); 20 21 //2.通过反射来调用普通方法: 22 Users u3 = (Users) c.newInstance(); //使用无参构造创建一个对象 23 Method getAge = c.getDeclaredMethod("getAge"); //获得方法("方法名",Class对象。。。) 24 Method setAge = c.getDeclaredMethod("setAge", int.class); 25 setAge.invoke(u3,19); 26 getAge.invoke(u3); //invoke(对象,实参)来执行方法 27 System.out.println(u3.getAge()); 28 29 //3.通过反射来获得(私有)属性,并给属性赋值 30 Users u4 = (Users) c.newInstance(); //创建一个对象 31 Field field = c.getDeclaredField("name"); 32 field.setAccessible(true); //设置权限,从而可以访问private属性 33 field.set(u4,"王五"); 34 System.out.println(u4.getName()); 35 } 36 }
注解:
1.常见的三种注解:
2 @SuppressWarnings("all") //取消警告的注解 3 4 public class Test1 extends Thread { 5 6 7 @Override //@Override:方法重写的注解 8 public void run() { 9 System.out.println("@Override"); 10 } 11 12 public static void main(String[] args) { 13 14 15 Test(); 16 new Test1().start(); 17 18 19 } 20 21 @Deprecated //方法过时的注解 22 public static void Test(){ 23 System.out.println("@Deprecated"); 24 25 } 26 }
2.自定义注解:
1 //自定义 2 public class Test2{ 3 4 public static void main(String[] args) { 5 Test(); 6 } 7 8 9 @Myannotation@Deprecated //可以多个在一起定义 10 public static void Test(){ 11 System.out.println("啦啦啦"); 12 } 13 @Myannotation2(name="张三",age={1,2}) 14 public static void Test3(){ 15 System.out.println("this is zhang san!"); 16 } 17 } 18 19 20 @Target(ElementType.METHOD) //参数是唯一的value,可以省略不写 21 @Retention(RetentionPolicy.RUNTIME) 22 @Documented 23 @interface Myannotation{ 24 // String value(); 25 // char[] name(); 26 27 String value() default "张三"; 28 String [] schools() default {"李四","王五","赵6"}; 29 30 } 31 32 33 34 @Target(value={ElementType.METHOD,ElementType.FIELD}) //注解作用范围 35 @Retention(value=RetentionPolicy.RUNTIME) //注解的作用时刻 36 37 @interface Myannotation2{ 38 String name(); //参数 39 int[] age(); 40 }