1、反射的定义及作用
1.1、通过Java语言中的反射机制可以操作字节码文件。(可以读和修改字节码文件)
通过反射机制可以操作代码片段。
1.2、反射机制的作用:使程序更加的灵活。
1.3、反射机制的相关类在哪个包下?
java.lang.reflect.*;
1.4、反射机制相关的重要的类有哪些?
java.lang.Class; 代表:整个字节码文件,代表一个类型,代表整个类。
java.lang.reflect.Method; 代表:字节码中的方法字节码,代表类中的方法。
java.lang.reflect.Constructor; 代表:字节码中的构造方法字节码,代表类中的构造方法。
java.lang.reflect.Field; 代表:字节码中的属性字节码,代表类中的成员变量(静态变量和实例变量)
2、获取Class的三种方式
第一种方式:
Class c = Class.forName(“完整类名带包名”);
1、静态方法
2、方法的参数是一个字符串
3、字符串需要是一个完整的类名
4、完整类名前必须带有包名
第二种方式:Class c = 对象.getClass();
第三种方式:Class c = 任何类型.class;(java语言中任何一种类型,包括基本数据类型,它都有.class属性)
3、通过构造方法实例化对象
- 通过newInstance调用无参数构造方法实例化对象 。
3.1.1、语法格式:
// c代表的是日期对象
Class c = Class.forName("java.util.Date");
// 实例化一个日期类型的对象
Object obj = c.newInstance();
3.1.2、注意事项:newInstance()底层调用的是无参数构造方法。如果没有无参数构造方法会出现实例化异常。
3.1.3、如果你只想让一个类的“静态代码块”执行的话,你可以怎么做?
Class.forName(“该类的类名”);
原因:这样类就加载,类加载的时候,静态代码块执行。在这里对该方法的返回值不感兴趣,主要是为了使用“类加载”这个动作。
- 通过反射机制反编译Field;
public static void main(String[] args) {
// 创建字符串,用于追加字符串
StringBuilder stringBuilder = new StringBuilder();
// 获取class
Class studentClass = null;
try {
studentClass = Class.forName("java.lang.Thread");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// 获取类名
String className = Modifier.toString(studentClass.getModifiers()) +" class "+studentClass.getSimpleName();
stringBuilder.append(className+"{\n");
// 获取属性
Field[] fields = studentClass.getDeclaredFields();
for (Field field : fields){
// 制表符
stringBuilder.append("\t");
// 获取访问控制权限列表
int modifiesInt = field.getModifiers();
String modifiesString = Modifier.toString(modifiesInt);
stringBuilder.append(modifiesString);
// 空格
stringBuilder.append(" ");
// 获取属性类型
Class fieldClass = field.getType();
String fieldType = fieldClass.getSimpleName();
stringBuilder.append(fieldType);
// 空格
stringBuilder.append(" ");
// 获取属性名字
String fieldName = field.getName();
stringBuilder.append(fieldName+";");
// 换行
stringBuilder.append("\n");
}
stringBuilder.append("}");
System.out.println(stringBuilder);
}
运行结果:
public class Thread{
private volatile String name;
private int priority;
private Thread threadQ;
private long eetop;
private boolean single_step;
private boolean daemon;
private boolean stillborn;
private Runnable target;
private ThreadGroup group;
private ClassLoader contextClassLoader;
private AccessControlContext inheritedAccessControlContext;
private static int threadInitNumber;
ThreadLocalMap threadLocals;
ThreadLocalMap inheritableThreadLocals;
private long stackSize;
private long nativeParkEventPointer;
private long tid;
private static long threadSeqNumber;
private volatile int threadStatus;
volatile Object parkBlocker;
private volatile Interruptible blocker;
private final Object blockerLock;
public static final int MIN_PRIORITY;
public static final int NORM_PRIORITY;
public static final int MAX_PRIORITY;
private static final StackTraceElement[] EMPTY_STACK_TRACE;
private static final RuntimePermission SUBCLASS_IMPLEMENTATION_PERMISSION;
private volatile UncaughtExceptionHandler uncaughtExceptionHandler;
private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;
long threadLocalRandomSeed;
int threadLocalRandomProbe;
int threadLocalRandomSecondarySeed;
}
- 通过反射机制调用Field;
// 首先第一步:获取class,实例化对象
Class studentClass = Class.forName("com.java.bean.Student");;
Object obj = studentClass.newInstance();
// 获取no属性(通过属性的名称来获取field)
Field noField = studentClass.getDeclaredField("no");
// 给obj对象(Student对象)的no属性赋值
/*
虽然使用了反射机制,但是三要素缺一不可
三要素:
要素1:obj对象
要素2:no属性
要素3:赋值
注意:反射机制让代码复杂了,但是,使程序更加灵活了。
*/
noField.set(obj,200);
// 读属性值
/*
2要素:
obj对象、no属性
*/
System.out.println(noField.get(obj)); // 200
// 尝试访问私有的属性name
Field fieldName = studentClass.getDeclaredField("name");
// 打破封装(反射机制的缺点,打破封装,不安全)
fieldName.setAccessible(true);
// 给name属性赋值
fieldName.set(obj,"jack");
// 获取name属性的值
System.out.println(fieldName.get(obj)); // jack
4、通过反射机制反编译Method
// 获取类
Class studentClass = Class.forName("java.lang.String");
StringBuilder s = new StringBuilder();
// 获取类名
s.append(Modifier.toString(studentClass.getModifiers())+" class "+studentClass.getSimpleName());
s.append("{\n");
// 获取Method
Method[] methods = studentClass.getDeclaredMethods();
for (Method method : methods){
s.append(" \t");
// 获取方法的修饰符列表
s.append(Modifier.toString(method.getModifiers()));
s.append(" ");
// 获取返回值类型
Class classType = method.getReturnType();
String stringType = classType.getSimpleName();
s.append(stringType);
s.append(" ");
// 获取方法名
s.append(method.getName());
s.append("(");
// 获取形参
Class[] parameterTypes = method.getParameterTypes();
// 如果Class[]的长度为0,则说明没有形参
if (0 != parameterTypes.length){
for (Class parameterType : parameterTypes){
String parameterTypeString = parameterType.getSimpleName();
s.append(parameterTypeString);
s.append(",");
}
s.deleteCharAt(s.length()-1);
}
s.append("){}\n");
}
s.append("}");
System.out.println(s);
}
运行结果:
public final class String{
public boolean equals(Object){}
public String toString(){}
public int hashCode(){}
public int compareTo(String){}
public volatile int compareTo(Object){}
public int indexOf(String,int){}
public int indexOf(String){}
public int indexOf(int,int){}
public int indexOf(int){}
static int indexOf(char[],int,int,char[],int,int,int){}
static int indexOf(char[],int,int,String,int){}
public static String valueOf(int){}
public static String valueOf(long){}
public static String valueOf(float){}
public static String valueOf(boolean){}
public static String valueOf(char[]){}
public static String valueOf(char[],int,int){}
public static String valueOf(Object){}
public static String valueOf(char){}
public static String valueOf(double){}
public char charAt(int){}
private static void checkBounds(byte[],int,int){}
public int codePointAt(int){}
public int codePointBefore(int){}
public int codePointCount(int,int){}
public int compareToIgnoreCase(String){}
public String concat(String){}
public boolean contains(CharSequence){}
public boolean contentEquals(CharSequence){}
public boolean contentEquals(StringBuffer){}
public static String copyValueOf(char[]){}
public static String copyValueOf(char[],int,int){}
public boolean endsWith(String){}
public boolean equalsIgnoreCase(String){}
public static transient String format(Locale,String,Object[]){}
public static transient String format(String,Object[]){}
public void getBytes(int,int,byte[],int){}
public byte[] getBytes(Charset){}
public byte[] getBytes(String){}
public byte[] getBytes(){}
public void getChars(int,int,char[],int){}
void getChars(char[],int){}
private int indexOfSupplementary(int,int){}
public native String intern(){}
public boolean isEmpty(){}
public static transient String join(CharSequence,CharSequence[]){}
public static String join(CharSequence,Iterable){}
public int lastIndexOf(int){}
public int lastIndexOf(String){}
static int lastIndexOf(char[],int,int,String,int){}
public int lastIndexOf(String,int){}
public int lastIndexOf(int,int){}
static int lastIndexOf(char[],int,int,char[],int,int,int){}
private int lastIndexOfSupplementary(int,int){}
public int length(){}
public boolean matches(String){}
private boolean nonSyncContentEquals(AbstractStringBuilder){}
public int offsetByCodePoints(int,int){}
public boolean regionMatches(int,String,int,int){}
public boolean regionMatches(boolean,int,String,int,int){}
public String replace(char,char){}
public String replace(CharSequence,CharSequence){}
public String replaceAll(String,String){}
public String replaceFirst(String,String){}
public String[] split(String){}
public String[] split(String,int){}
public boolean startsWith(String,int){}
public boolean startsWith(String){}
public CharSequence subSequence(int,int){}
public String substring(int){}
public String substring(int,int){}
public char[] toCharArray(){}
public String toLowerCase(Locale){}
public String toLowerCase(){}
public String toUpperCase(){}
public String toUpperCase(Locale){}
public String trim(){}
}
5、通过反射机制调用Method;
public static void main(String[] args) throws Exception{
// 不使用反射机制调方法
// 创建对象
Student student = new Student();
// 调方法
/*
要素分析:
要素1:对象
要素2:方法名
要素3:实参列表
要素4:返回值类型
*/
boolean isStudent = student.isStudentName("aaa",100);
System.out.println(isStudent ? "重复":"不重复");
// 通过反射机制调方法
// 获取类
Class studentClass = Class.forName("com.java.bean.Student");
// 创建对象
Object obj = studentClass.newInstance();
// 获取isStudentName方法
Method studentMethod = studentClass.getDeclaredMethod("isStudentName",String.class,int.class);
// 调用方法
/*
要素分析:
要素1:对象 obj
要素2:方法名 isStudentName
要素3:实参列表 "aaa",100
要素4:返回值类型 retValue
*/
// 反射机制中最最最重要的方法之一
Object retValue = studentMethod.invoke(obj,"aaa",100);
System.out.println(retValue);
}
6、通过反射机制反编译构造方法/Constructor
public static void main(String[] args) throws Exception{
// 获取类
Class studentClass = Class.forName("java.lang.String");
StringBuilder s = new StringBuilder();
s.append(Modifier.toString(studentClass.getModifiers())+" class ");
s.append(studentClass.getSimpleName()+" {\n");
// 拼接构造方法
Constructor[] constructors = studentClass.getDeclaredConstructors();
for (Constructor constructor : constructors){
s.append(" "+Modifier.toString(constructor.getModifiers())+"\t");
s.append(studentClass.getSimpleName()+" (");
// 获取实参
Class[] parameterTypes = constructor.getParameterTypes();
if (parameterTypes.length != 0){
for (Class parameterType : parameterTypes){
String parameter = parameterType.getSimpleName();
s.append(parameter);
s.append(",");
}
// 删除最后下标的字符
s.deleteCharAt(s.length()-1);
}
s.append("){}\n");
}
s.append("}");
System.out.println(s);
}
运行结果:
public final class String {
public String (byte[],int,int){}
public String (byte[],Charset){}
public String (byte[],String){}
public String (byte[],int,int,Charset){}
public String (byte[],int,int,String){}
String (char[],boolean){}
public String (StringBuilder){}
public String (StringBuffer){}
public String (byte[]){}
public String (int[],int,int){}
public String (){}
public String (char[]){}
public String (String){}
public String (char[],int,int){}
public String (byte[],int){}
public String (byte[],int,int,int){}
}
7、通过反射机制调用构造方法
public static void main(String[] args) throws Exception{
// 不使用反射机制调用方法
// public Student(int no, String name, boolean sex, int age) {
Student student1 = new Student();
Student student2 = new Student(1,"a",true,20);
System.out.println(student1);
System.out.println(student2);
System.out.println("============================");
// 使用反射机制调用构造方法
// 调用无参数构造方法
Class studentClass = Class.forName("com.java.bean.Student");
Object obj = studentClass.newInstance();
System.out.println(obj);
// 调用无参数构造方法
Constructor con2 = studentClass.getDeclaredConstructor();
Object o2 = con2.newInstance();
System.out.println(o2);
// 调用有参数构造方法
// 第一步:先获取有参数构造方法
Constructor con = studentClass.getDeclaredConstructor(int.class,String.class,boolean.class,int.class);
// 第二步:调用构造方法new对象
Object o = con.newInstance(123,"abc",false,21);
System.out.println(o);
}
8、通过反射机制获取该类的父类跟实现了哪些接口
public static void main(String[] args) throws Exception{
// 拿String举例
Class stringClass = Class.forName("java.lang.String");
// 获取String的父类
Class superClass = stringClass.getSuperclass();
System.out.println(superClass.getName());
// 获取String类实现的所有接口
Class[] interfaces = stringClass.getInterfaces();
for (Class in : interfaces){
System.out.println(in.getName());
}
}
运行结果:
java.lang.Object
java.io.Serializable
java.lang.Comparable
java.lang.CharSequence
4、关于路径的问题
1、用以下的方法首先必须保证该文件在类的根路径下
2、获取路径的两种方式:
- 第一种方式:
/*
解释:
Thread.currentThread() 当前线程对象
getContextClassLoader() 是线程对象的方法,可以获取当前线程的类加载器对象
getResource("") 【获取资源】这是类加载器对象的方法,当前线程的类加载器默认从类的根路径下加载资源。
*/
String path = Thread.currentThread().getContextClassLoader().getResource("在src的根路径下的路径").getPath();
- 第二种方式:直接以流的方式返回
// 直接以流的形式返回。
InputStream reader = Thread.currentThread().getContextClassLoader().getResourceAsStream("在src的根路径下的路径");
3、IO + Properties ,怎么快速绑定属性配置文件?
// 要求:第一这个文件必须在类路径下
// 第二:这个文件必须是.properties结尾。
// 第三:文件的扩展名不用写
ResourceBundle bundle = ResourceBundle.getBundle("在src的根路径下的路径");
String value = bundle.getString(key);
5、结语
您好!正在努力中的人陌生人,加油!!!