java学习_反射
来源:互联网 发布:单片机芯片 编辑:程序博客网 时间:2024/05/17 06:23
1、Class类(反射的基石)
1.1、 Java中的类是描述一类事物的共性,表示该类事物具有什么属性,属性的值是什么则有这个类的实例化对象来表示,不同的实例化对象属性值不同。
Java程序中的各个Java类属于同一类事物,描述该类事物的Java类名就是Class,Class类描述类的名字、类的访问属性、类所属的包名、字段名称的列表、方法名称的列表等。Class的实例对象代表的是类的字节码。
注意:与小写class关键字不同
1.2、 得到类的Class对象(字节码)的三种方式 (三种方式得到的字节码是一样的)
1)Object类的getClass()方法 格式为 对象.getClass
例如 Person p1=new Person();
Class cls1=p1.getClass();
弊端:必须要创建该类对象,才可以调用getClass方法
2)数据类型的静态属性class 格式为 类名.class
例如 Class cls1=String.class
弊端:必须先明确该类
3) Class类中的静态方法 public static Class forName(String className)
例如Class.forName("java.util.Date");
这种方式是用一个字符串,而不是一个具体的类名,可以把这样的字符串配置到配置文件中,扩展性好,开发中常用。
代码示例:
package com.itheima_01;/* * Class类: * 成员变量Field * 构造方法Constructor * 成员方法Method * * 获取class文件对象的方式: * A:Object类的getClass()方法 * B:数据类型的静态属性class * C:Class类中的静态方法 * public static Class forName(String className) */public class ReflectDemo {public static void main(String[] args) throws ClassNotFoundException {// 方式1Person p = new Person();Class c = p.getClass();Person p2 = new Person();Class c2 = p2.getClass();System.out.println(p == p2);// falseSystem.out.println(c == c2);// true// 方式2Class c3 = Person.class;// int.class;// String.class;System.out.println(c == c3);// 方式3// ClassNotFoundExceptionClass c4 = Class.forName("cn.itheima_01.Person");System.out.println(c == c4);}}
package com.itheima_01;public class Person {private String name;int age;public String address;public Person() {}private Person(String name) {this.name = name;}Person(String name, int age) {this.name = name;this.age = age;}public Person(String name, int age, String address) {this.name = name;this.age = age;this.address = address;}public void show() {System.out.println("show");}public void method(String s) {System.out.println("method " + s);}public String getString(String s, int i) {return s + "---" + i;}private void function() {System.out.println("function");}@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + ", address=" + address+ "]";}}
1.3、 9个预定义的Class:
八个基本类型(boolean、byte、char、short、int、long、float 和 double)和 void。
public boolean isPrimitive()用于判定指定的 Class 对象是否表示一个基本类型。
Integer.TYPE是Integer类的一个常量,Integer.TYPE==int.class。基本数据类型的字节码都可以用与之对应的包装类中的TYPE常量表示。
只要是在源程序中出现的类型,都有各自的Class实例对象,例如,int[],void。
数组类型的Class实例对象,可以用Class.isArray()方法判断是否为数组类型。
2、反射
反射就是把Java类中的各种成分映射成相应的java类。(反射会导致程序性能下降)
例如,一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示,就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类。表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,它们是Field(成员变量)、Method(成员方法)、Contructor(构造方法)、Package(包)等等。
一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象后,得到这些实例对象后有什么用呢?怎么用呢?这正是学习和应用反射的要点。
2.1、Constructor类
Constructor类代表某个类中的一个构造方法
获取构造方法:
public Constructor[] getConstructors():所有公共构造方法
public Constructor[] getDeclaredConstructors():所有构造方法
public Constructor<T> getConstructor(Class<?>... parameterTypes) 获取单个构造方法
参数表示的是:你要获取的构造方法的构造参数个数及数据类型的class字节码文件对象
示例:
得到某个类中所有公共的构造函数:
Constructor [] cons= Class.forName("java.lang.String").getConstructors();
得到某一个构造函数
Constructor con = Class.forName(“java.lang.String”).getConstructor(StringBuffer.class);
代码示例
package com.itheima_02;import java.lang.reflect.Constructor;import com.itheima_01.Person;/* * 通过反射获取构造方法并使用。 */public class ReflectDemo {public static void main(String[] args) throws Exception {// 获取字节码文件对象Class c = Class.forName("<span style="font-family:SimSun;">com.itheima_01.Person</span>");// 获取构造方法// public Constructor[] getConstructors():所有公共构造方法// public Constructor[] getDeclaredConstructors():所有构造方法// Constructor[] cons = c.getDeclaredConstructors();// for (Constructor con : cons) {// System.out.println(con);// }// 获取单个构造方法// public Constructor<T> getConstructor(Class<?>... parameterTypes)// 参数表示的是:你要获取的构造方法的构造参数个数及数据类型的class字节码文件对象Constructor con = c.getConstructor();// 返回的是构造方法对象// Person p = new Person();// System.out.println(p);// public T newInstance(Object... initargs)// 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。Object obj = con.newInstance();System.out.println(obj);// Person p = (Person)obj;// p.show();}}
package com.itheima_02;import java.lang.reflect.Constructor;/* * 通过反射去获取带带参构造方法并使用: * public Person(String name, int age, String address) * * Person p = new Person("long",27,"上海"); * System.out.println(p); */public class ReflectDemo2 {public static void main(String[] args) throws Exception {// 获取字节码文件对象Class c = Class.forName("com.itheima_01.Person");// 获取带参构造方法对象// public Constructor<T> getConstructor(Class<?>... parameterTypes)Constructor con = c.getConstructor(String.class, int.class,String.class);// 通过带参构造方法对象创建对象// public T newInstance(Object... initargs)Object obj = con.newInstance("long", 27, "上海");System.out.println(obj);}}
package com.itheima_02;import java.lang.reflect.Constructor;/* * 通过反射获取私有构造方法并使用 * private Person(String name){} * * Person p = new Person("long"); * System.out.println(p); */public class ReflectDemo3 {public static void main(String[] args) throws Exception {// 获取字节码文件对象Class c = Class.forName("com.itheima_01.Person");// 获取私有构造方法对象// NoSuchMethodException:每个这个方法异常// 原因是一开始我们使用的方法只能获取公共的,下面这种方式就可以了。Constructor con = c.getDeclaredConstructor(String.class);// 用该私有构造方法创建对象// IllegalAccessException:非法的访问异常。// 暴力访问con.setAccessible(true);// 值为true则指示反射的对象在使用时应该取消Java语言访问检查。Object obj = con.newInstance("long");System.out.println(obj);}}
2.2、Field类
Field类代表某个类中的一个成员变量
得到的Field对象是对应到类上面的成员变量
Field getField(String s);//只能获取公有和父类中公有
Field getDeclaredField(String s);//获取该类中任意成员变量,包括私有
set(Object obj, Object value);//将指定对象变量上此Field对象表示的字段设置为指定的新值。
如果是私有的,就用setAccesiable(true);暴力访问
Object get(Object obj);//返回指定对象上Field表示的字段的值。
package com.itheima_03;import java.lang.reflect.Constructor;import java.lang.reflect.Field;/* * 通过发生获取成员变量并使用 */public class ReflectDemo {public static void main(String[] args) throws Exception {// 获取字节码文件对象Class c = Class.forName("com.itheima_01.Person");// 获取所有的成员变量// Field[] fields = c.getFields();// Field[] fields = c.getDeclaredFields();// for (Field field : fields) {// System.out.println(field);// }/* * Person p = new Person(); p.address = "上海"; System.out.println(p); */// 通过无参构造方法创建对象Constructor con = c.getConstructor();Object obj = con.newInstance();System.out.println(obj);// 获取单个的成员变量// 获取address并对其赋值Field addressField = c.getField("address");// public void set(Object obj,Object value)// 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。addressField.set(obj, "上海"); // 给obj对象的addressField字段设置值为"上海"System.out.println(obj);// 获取name并对其赋值// NoSuchFieldExceptionField nameField = c.getDeclaredField("name");// IllegalAccessExceptionnameField.setAccessible(true);nameField.set(obj, "long");System.out.println(obj);// 获取age并对其赋值Field ageField = c.getDeclaredField("age");ageField.setAccessible(true);ageField.set(obj, 27);System.out.println(obj);}}
练习:把字母b改成a,实现该功能代码如下
public static void changeStringValue(Object obj) throws Exception {Field[] fields = obj.getClass().getDeclaredFields();for (Field field : fields) {if (field.getType() == String.class) {field.setAccessible(true);String oldvalue = (String) field.get(obj);String newvalue=oldvalue.replace('b', 'a');field.set(obj, newvalue);}}}
2.3、Method类
Method类代表某个类中的一个成员方法
大家应通过思考和推理的方式来学习反射中的API,例如,Class.getMethod方法用于得到一个方法,该方法要接受什么参数呢?显然要一个方法名,而一个同名的方法有多个重载形式,用什么方式可以区分清楚想得到重载方法系列中的哪个方法呢?根据参数的个数和类型,例如,Class.getMethod(name,Class... args)中的args参数就代表所要获取的那个方法的各个参数的类型的列表。
再强调一遍参数类型用什么来表示啊?用Class对象!
class TestArrayArguments { public static void main(String [] args) { for(String arg:args) { System.out.println("----------" + arg + "----------"); } }}2.4、数组的反射
class ReflecTest2 {public static void main(String[] args) throws Exception {// 应该先直接用ArrayList和HashSet,然后才引入从配置文件读,这样便于学员学习。Properties props = new Properties();// 先演示相对路径的问题// InputStream ips = new FileInputStream("config.properties");/* * 一个类加载器能加载.class文件,那它当然也能加载classpath环境下的其他文件,既然它有如此能力,它没有理由不 * 顺带提供这样一个方法。它也只能加载classpath环境下的那些文件。注意:直接使用类加载器时,不能以/打头。 */// InputStream ips =// ReflectTest2.class.getClassLoader().getResourceAsStream("cn/itcast/javaenhance/config. //properties");// Class提供了一个便利方法,用加载当前类的那个类加载器去加载相同包目录下的文件// InputStream ips =// ReflectTest2.class.getResourceAsStream("config.properties");InputStream ips = ReflectTest2.class.getResourceAsStream("/cn/itcast/javaenhance/config.properties");props.load(ips);ips.close();String className = props.getProperty("className");Class clazz = Class.forName(className);Collection collection = (Collection) clazz.newInstance();// Collection collection = new ArrayList();ReflectPoint pt1 = new ReflectPoint(3, 3);ReflectPoint pt2 = new ReflectPoint(5, 5);ReflectPoint pt3 = new ReflectPoint(3, 3);collection.add(pt1);collection.add(pt2);collection.add(pt3);collection.add(pt1);System.out.println(collection.size());}}
- java学习_反射
- JAVA学习31_ java反射机制
- java高级技术学习_反射
- Java Reflection 反射机制_学习
- Java基础知识_反射
- java技术_反射
- Java入门_反射
- Java笔记 _反射
- JAVA反射_代理
- JAVA反射_注解
- 黑马程序员--Java学习日记5_反射
- [知了堂学习笔记]_浅谈Java反射
- 黑马程序员学习_反射
- Java核心技术(第8版)学习笔记_继承(2)_反射
- java基础27_反射
- java基础加强_反射
- java初级笔记_反射
- Java学习之类加载全过程_JVM内存分析_反射机制核心原理_常量池理解
- 根据客户区大小反推窗口大小
- CentOS源码安装gftp缺失stropts.h
- Ubuntu中文路径改英文路径
- javascript基础资料
- [优化篇]Ubuntu使用corosync+pacemaker+drbd实现MySQL的HA(1)
- java学习_反射
- 泛型委托
- C++中typename和class的区别
- CentOS7下升级glib
- [实验]10.9号实验内容(网络14)
- FBO
- Android GridView的简单使用
- javascript实现下拉列表和复选框的选中
- Ubuntu samba服务器建立并与windows文件共享