反射、枚举"/>
Java基础——反射、枚举
一.反射
1.使用情景
当你做程序开发时,你会发现定义接口,可以提高程序扩展性,扩展功能类实现接口即可。可是你会发现源码中只有引用型变量不用修改了而已,扩展功能时不能避免的就是建立功能类的对象,对象是必须要建立的。这时就有了反射技术出现解决了这一问题,只要你把功能类类名定义在一个指定配置文件中,你不用修改任何源程序代码的情况下完成功能的扩展。反射的出现大大提高了程序的扩展性
2.解释
反射就是加载类,并解刨出类的各个组成部分
3.描述
3.1 Class类的含义
(1)Class类是对*.class文件共性内容向上抽取后得到的类,是一个描述类的类。就像多个对象都是同一个类构造的一样。
(2)字段(成员变量)、构造函数、成员函数都封装为了对象存储在Class类中,来对字节码文件进行统一的描述
(3)重点:每一个Class对象都单单指一个*.class文件
3.2 使用方法
方法摘要 |
---|
Field | getField(String name) 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。(通过变量名来定位哪一个变量) |
Field[] | getFields() 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。 |
Constructor<T> | getConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。(传入参数列表内参数的类型.class文件,型参)(通过参数列表来定位构造函数) |
Constructor<?>[] | getConstructors() 返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。 |
|
|
|
|
Field | getDeclaredField(String name) 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。(只要声明即可获取,不管权限问题) |
Field[] | getDeclaredFields() 返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。(只要声明即可获取,不管权限问题) |
Method | getDeclaredMethod(String name, Class<?>... parameterTypes) 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。(只要声明即可获取,不管权限问题) |
Method[] | getDeclaredMethods() 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。 |
Constructor<T> | getDeclaredConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。(只要声明即可获取,不管权限问题) |
Constructor<?>[] | getDeclaredConstructors() 返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。(只要声明即可获取,不管权限问题) |
(1)获取该类对象方法
<1>.方法1:
通过Object中的getClass()方法获取本类对象,不过前提是必须要有对象,使用的是非静态方法
Class<?> | getClass() 返回此 Object 的运行时类。 |
<1>.方法2:
通过java任意数据类型都有一个.clsss字节码文件描述这一特性,任意数据类型都有一个静态成员class,例如int.class。来获取本类对象
例如:Class clazz = Person.class; 或者 Class clazz = int.class;
还是必须先要知道类,也就是类名,这个只是通过对象的静态属性
<1>.方法3:
通过该类的静态方法获取本类对象,最常用
static Class<?> | forName(String className) 返回与带有给定字符串名的类或接口相关联的 Class 对象。 |
(2)建立Class对象所表示类的实例
<1>.可以通过Class类的newInstance()方法。只可以通过空参数够赞函数来构造
注1:InstantiationException是实例化失败异常,通常是没有空参数构造函数所致
注2:IllegalAccessException是访问权限不够时会抛出的异常
T | newInstance() 创建此 Class 对象所表示的类的一个新实例。 |
<2>.可以通过Class类中方法获取构造函数对象,来对对象进行构造。并且可以通过制定构造函数对对对象进行初始化
3.2 Constructor类
方法摘要 | |
---|---|
T | newInstance(Object... initargs) 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。(传入实际参数) |
package cn.doing.reflect;import java.lang.reflect.Constructor;
import java.util.HashSet;
import java.util.Set;import org.junit.Test;public class ReflectConstructor {private Class<Person> clazz;//反射public Person(){}@SuppressWarnings("unchecked")@Testpublic void test1() throws Exception {clazz = (Class<Person>) Class.forName("cn.doing.reflect.Person");Constructor<Person> c = clazz.getConstructor();Person p = c.newInstance();System.out.println(p.aa);}//反射public Person(String name){}@SuppressWarnings("unchecked")@Testpublic void test2() throws Exception {clazz = (Class<Person>) Class.forName("cn.doing.reflect.Person");Constructor<Person> con = clazz.getConstructor(String.class);Person p = con.newInstance("黄镇");System.out.println(p.aa);}//反射public Person(String name,int age){}@SuppressWarnings("unchecked")@Testpublic void test3() throws Exception {clazz = (Class<Person>) Class.forName("cn.doing.reflect.Person");Constructor<Person> con = clazz.getConstructor(String.class,int.class);Person p = con.newInstance("于泽",14);System.out.println(p.aa);}//反射private Person(Set s){}@SuppressWarnings("unchecked")@Testpublic void test4() throws Exception {clazz = (Class<Person>) Class.forName("cn.doing.reflect.Person");Constructor<Person> con = clazz.getDeclaredConstructor(Set.class);con.setAccessible(true);Person p = con.newInstance(new HashSet<String>());System.out.println(p.aa);}//通过另一种方法反射public Person(){},通过Class类中提供的newInstance()方法创建空参数的实例@SuppressWarnings("unchecked")@Testpublic void test5() throws Exception {clazz = (Class<Person>) Class.forName("cn.doing.reflect.Person");Person p = clazz.newInstance();System.out.println(p.aa);}
}
3.3 Field类
方法摘要 | |
---|---|
void | setObject obj, Object value) 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。(修改指定对象的这个字段值) |
Object | get(Object obj) 返回指定对象上此 Field 表示的字段的值。 |
Class<?> | getType() 返回一个 Class 对象,它标识了此 Field 对象所表示字段的声明类型。 |
package cn.doing.reflect;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;import org.junit.Test;public class ReflectField {private Person p;//反射空参数构造函数创建对象@Testpublic void newInstanceTest() throws Exception{Class<?> clazz = Class.forName("cn.doing.reflect.Person");Constructor<?> con = clazz.getConstructor();p = (Person) con.newInstance();}//反射类的字段public String aa = "111";@Testpublic void getField1() throws Exception{newInstanceTest();Class<?> clazz = Class.forName("cn.doing.reflect.Person");Field f = clazz.getField("aa");System.out.println(f.get(p));}//反射类的字段private String bb = "aaa";@Testpublic void getField2() throws Exception{newInstanceTest();Class<?> clazz = Class.forName("cn.doing.reflect.Person");Field f = clazz.getDeclaredField("bb");f.setAccessible(true);f.set(p, "xxxxxxxxxxxxx");Object value = f.get(p);Class type = f.getType();if(type.equals(String.class)){String svalue = (String) value;System.out.println(svalue);}}//反射类的字段private static int cc = 111222222;@Testpublic void getField3() throws Exception{//newInstanceTest();Class<?> clazz = Class.forName("cn.doing.reflect.Person");Field f = clazz.getDeclaredField("cc");f.setAccessible(true);Object value = f.get(null);Class type = f.getType();if(type.equals(int.class)){int ivalue = (Integer) value;System.out.println(ivalue);}}
}
3.4 Method类
方法摘要 | |
---|---|
Object | invoke(Object obj, Object... args) 对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。(静态方法传入对象为null即可) |
package cn.doing.reflect;import java.lang.reflect.Constructor;
import java.lang.reflect.Method;import org.junit.Test;public class ReflectMethod {private Person p ;//反射类中的空参数的构造函数建立对象@Testpublic void newInstanceTest() throws Exception{Class<?> clazz = Class.forName("cn.doing.reflect.Person");Constructor<?> con = clazz.getConstructor();p = (Person) con.newInstance();}//反射类中方法public void function(){}@Testpublic void getMethod1() throws Exception{newInstanceTest();Class<?> clazz = Class.forName("cn.doing.reflect.Person");Method m = clazz.getMethod("function",null);m.invoke(p, null);}//反射类中方法public int function(String name){}@Testpublic void getMethod2() throws Exception{newInstanceTest();Class<?> clazz = Class.forName("cn.doing.reflect.Person");Method m = clazz.getMethod("function", String.class);m.invoke(p, "王逊");}//反射类中方法public Class[] function(int i,String[] args){}@SuppressWarnings("rawtypes")@Testpublic void getMethod3() throws Exception{newInstanceTest();Class<?> clazz = Class.forName("cn.doing.reflect.Person");Method m = clazz.getMethod("function", int.class,String[].class);Class[] arr = (Class[]) m.invoke(p, 1,new String[]{});System.out.println(arr);}//反射类中方法public static void funtion(long l){}@Testpublic void getMethod4() throws Exception{//newInstanceTest();Class<?> clazz = Class.forName("cn.doing.reflect.Person");Method m = clazz.getMethod("function", long.class);m.invoke(null,111);}//反射类中方法private boolean funtion1(boolean flag){}@Testpublic void getMethod5() throws Exception{newInstanceTest();Class<?> clazz = Class.forName("cn.doing.reflect.Person");Method m = clazz.getDeclaredMethod("function1", boolean.class);m.setAccessible(true);System.out.println(m.invoke(p, true));}//反射类中主方法public static void main(String[] args) {}@Testpublic void getMethod6() throws Exception{//newInstanceTest();Class<?> clazz = Class.forName("cn.doing.reflect.Person");Method m = clazz.getMethod("main", String[].class);m.invoke(null, (Object)new String[]{"12","123"});}
}
3.5 AccessibleObject类
注1:Field类、Constructor类、Method类的基类,定义共性内容
方法摘要 | |
---|---|
void | setAccessible(boolean flag) 将此对象的 accessible 标志设置为指示的布尔值。(暴力反射,对象在使用时应该取消Java语言访问检查) |
3.6 反射主函数(注意)
当反射主函数时一定要注意在调用invoke(obj,args)时,不能只传入一个new String["1","aabb"],因为Java可变参数的向下兼容特性,导致会把这个数组拆分为两个字符串类型参数
二.枚举
1.适用环境
当需要让方法传入数据不能任意时,可以用自定义类来解决,类不能加你对象并且类中封装了你需要的值。JDK1.5以后可以用枚举类型来解决这一问题
2.知识点
(1)意义:枚举类也是一种特殊形式的Java类 (2)特点:枚举每一个枚举值都代表一个枚举类的实例对象,并且也可以声明属性、方法、构造函数,构造函数必须是私有的。还有枚举类也可以继承实现类和接口 (3)JDK1.5以后swich选择语句可以接收枚举类型 (4)枚举值只有一个的情况下,则可以视为简单的单利设计模式3.Enum类
方法摘要 | ||
---|---|---|
String | name() 返回此枚举常量的名称,在其枚举声明中对其进行声明。 | |
int | ordinal() 返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。 | |
static
| valueOf(Class<T> enumType, String name) 返回带指定名称的指定枚举类型的枚举常量。(将一个字符串转成一个枚举,用法:可以判定这个字符串是否是枚举值,不是的话会抛出异常。很简单的判定字符串的合法性) |
4.代码演示
package cn.doing.enumeration;public enum EnumClass {//枚举A("100-90"){//A B C D都分别代表枚举值并且都是本类对象@Overridepublic String getLocalValue() {// TODO Auto-generated method stubreturn null;}},B("89-80") {//构造对象@Overridepublic String getLocalValue() {//复写抽象方法// TODO Auto-generated method stubreturn null;}},C("79-70") {@Overridepublic String getLocalValue() {// TODO Auto-generated method stubreturn null;}},D("69-60") {@Overridepublic String getLocalValue() {// TODO Auto-generated method stubreturn null;}},E("59-0") {@Overridepublic String getLocalValue() {// TODO Auto-generated method stubreturn null;}};private String value;//枚举字段private EnumClass(String value){//枚举构造函数this.value = value;}public String getValue(){//枚举抽象方法return value;}public abstract String getLocalValue();
}
更多推荐
Java基础——反射、枚举
发布评论