JAVA Class25
Posted Observer
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA Class25相关的知识,希望对你有一定的参考价值。
学习内容:
1.反射
反射目的是在不修改代码的情况下,只需修改外部配置文件,实现调用不同类的不同方法。
(1)类的载入
当我们需要使用一个类时,我们要将这个类载入JVM,这里就要用到类载入的方法:
另外,在我们实例化一个对象是,类会自动载入,另外,实例化一个子类对象会导致父类自动载入
public class Person { public String name; private int age; static {//注意这个静态代码块! System.out.println("静态代码块"); } public Person() { super(); } public Person(String name,int age) { super(); this.name = name; this.age = age; } }
public class TestPerson { @SuppressWarnings({"rawtypes","unchecked"})//忽略多类型警告 public static void main(String[] args) { try { Class c1 = Class.forName("edu.java.reflection.Person");//包名.类名 Class c2 = new Person().getClass(); //上述两种方式都会初始化静态属性,且只会执行一次! Class c3 = Person.class;//不会初始化静态属性 //在一个JVM中,一种类,只会有一个类对象存在。所以以上三种方式取出来的类对象,都是一样的。 //注: 准确的讲是一个ClassLoader下,一种类,只会有一个类对象存在。通常一个JVM下,只会有一个ClassLoader。 System.out.println(c1==c2);//true System.out.println(c1.equals(c2));//true System.out.println(c1==c3);//true System.out.println(c1.equals(c3));//true } }
(2)构造器的获取与利用构造器实例化对象:
public class TestPerson { @SuppressWarnings({"rawtypes","unchecked"}) public static void main(String[] args) { try { Class c1 = Class.forName("edu.java.reflection.Person");//包名.类名 //获取造器数组 Constructor[] con = c1.getConstructors();//获取所有公共的构造器 for(Constructor s:con) { System.out.println(s); } //获取空参构造器 Constructor con = c1.getConstructor(); //空参构造器实例化对象 Object obj = con.newInstance(); Person p = (Person)obj;//newInstance()返回的是Object,向下强转Person*/ //有参构造器 Class[] v = {String.class,int.class}; Constructor con = c1.getConstructor(v); Object obj = con.newInstance("张三",20); Person p = (Person)obj;*/ System.out.println(p); Constructor[] all = c1.getDeclaredConstructors();//获取所有构造器,包括私有的 for(Constructor con:all) { System.out.println(con); } Constructor con = c1.getDeclaredConstructor(String.class);//获取私有的有参构造器 con.setAccessible(true);//取消变量权限检查,可以访问私有化变量 Object obj = con.newInstance("李四"); Person p = (Person)obj; System.out.println(p);*/ //空参构造快速生成对象 Object obj = c1.newInstance(); Person p = (Person)obj; } }
(3)获取字段追
public class TestPerson { @SuppressWarnings({"rawtypes","unchecked"}) public static void main(String[] args) { try { Class c1 = Class.forName("edu.java.reflection.Person");//包名.类名 Field[] f = c1.getFields();//获取所有公共字段 for(Field i:f) { System.out.println(i); } Constructor con = c1.getConstructor(String.class,int.class); Object obj = con.newInstance("张三",20); Person p = (Person)obj; Field f = p.getClass().getField("name");//获取对象的指定字段值 f.set(p, "李四"); System.out.println(p); Field age = p.getClass().getDeclaredField("age");//获取私有变量 age.setAccessible(true); age.set(p, 30); System.out.println(p); } catch(Exception e) { e.printStackTrace(); } } }
(4)通过类获取方法
public class TestPerson { @SuppressWarnings({"rawtypes","unchecked"}) public static void main(String[] args) { try { Class c1 = Class.forName("edu.java.reflection.Person");//包名.类名 Constructor con = c1.getConstructor(String.class,int.class); Object obj = con.newInstance("张三",20); Person p = (Person)obj; Field f = p.getClass().getField("name");//获取对象的指定字段值 f.set(p, "李四"); System.out.println(p); Field age = p.getClass().getDeclaredField("age");//获取私有变量 age.setAccessible(true); age.set(p, 30); System.out.println(p);*/ //获取所有方法 Method[] all = c1.getMethods(); for(Method mm:all) { System.out.println(mm); } Method m1 = c1.getMethod("eat"); m1.invoke(p); Method m2 = c1.getDeclaredMethod("sleep",String.class,int.class,double.class);//获取私有带参方法 m2.setAccessible(true); m2.invoke(p,p.name,30,90); } catch(Exception e) { e.printStackTrace(); } } }
2.泛型擦除
JAVA的泛型是”假泛型“,不进class文件,所以利用反射,我们可以突破泛型限制添加数据
public class TestPerson { @SuppressWarnings({"rawtypes","unchecked"}) public static void main(String[] args) { try { //泛型擦除 ArrayList<String> list = new ArrayList<String>(); list.add("abc"); Class c = list.getClass(); Method method = c.getMethod("add", Object.class); method.invoke(list, 1); System.out.println(list);//数字1被成功添加,JAVA的泛型是”假泛型“,不进class文件 System.out.println(list.get(0)); System.out.println(list.get(1));//但是获取会报类型转换失败错误 } catch(Exception e) { e.printStackTrace(); } } }
3.泛型应用
public class Test { @SuppressWarnings({ "rawtypes", "unchecked" })//忽略多类型警告 public static void main(String[] args) throws Exception { //从spring.txt中获取类名称和方法名称 File sp = new File("e:/java/spring/spring.txt"); Properties sc = new Properties(); sc.load(new FileInputStream(sp)); String classname = (String)sc.get("class"); //String methodname = (String)sc.get("method"); String methodname = sc.getProperty("method"); //根据类名称获取类对象 Class cl = Class.forName(classname); //根据方法名称,获取方法对象 Method m = cl.getMethod(methodname); //获取构造器 Constructor c = cl.getConstructor(); //根据构造器,实例化出对象 Object service = c.newInstance(); //调用对象的指定方法 m.invoke(service); //如果要切换类及方法,只改变外部的txt文件内容即可,代码不用改 } }
以上是关于JAVA Class25的主要内容,如果未能解决你的问题,请参考以下文章
如何使用java将数据从片段传递到android中的另一个片段?
[20-05-18][Thinking in Java 25]Java Inner Class 9 - Anonymous Inner Class 4