获取字节码文件的三种方式
package com.bjpowernode.java.reflect;
import java.util.Date;
/*
反射机制:
先获取字节码文件,怎么获取java.lang.Class实例??
三种方式:
*/
public class ReflectTest01 {
public static void main(String[] args) {
/*
Class.forName();
1.静态方法
2.方法的参数必须是字符串
3.字符串需要的是一个完整的类名
4.完整的类名必须带有包名:java.lang包不能省略
*/
Class c1=null;
Class c2=null;
try {
c1=Class.forName("java.lang.String"); // c1代表的是String.class文件,或者说c1代表的是String类型
c2=Class.forName("java.util.Date"); // c2代表的是Date类型
Class c3=Class.forName("java.lang.Integer");// c3代表的是Integer类型
Class c4=Class.forName("java.lang.System"); // c4代表的是System类型
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// java种任何一个对象都有一个方法:getClass()
String s="abc";
Class x=s.getClass(); // x代表String类型
System.out.println(c1==x);// true 说明c1和x的内存地址一样,说明他们代表的都是String类型
Date date=new Date();
Class y=date.getClass();
System.out.println(y==c2); // true c2和y两个变量保存的内存地址都是一样的
// java语言中任何一种类型,包括基本数据类型,它都有class属性
Class z=String.class; // 代表String类型
Class k=Date.class;
Class f=int.class;
Class e=double.class;
System.out.println(x==z);
}
}
读属性文件的方式
package com.bjpowernode.java.bean;
import java.io.InputStream;
import java.util.Properties;
/*
读属性文件
*/
public class IoPropertiesTest {
public static void main(String[] args) throws Exception{
// 直接以流的形式返回
InputStream reader=Thread.currentThread().getContextClassLoader().getResourceAsStream("classinfo2.properties");
Properties pro=new Properties();
pro.load(reader);
reader.close();
// 通过key获取value
String className=pro.getProperty("className");
System.out.println(className);
}
}
资源绑定器(掌握这种就好啦)
package com.bjpowernode.java.reflect;
import java.util.ResourceBundle;
/*
资源绑定器
java.util包下的资源绑定器,便于获取属性配置文件
使用属性配置文件的时候,属性配置文件必须放在类路径下
*/
public class ResourceBundleTest {
public static void main(String[] args) {
// 资源绑定器,只能绑定xxx.properties 并且这个文件必须在类路径下,问价扩展名必须为properties
// 并且后面的扩展名不用写
ResourceBundle bundle=ResourceBundle.getBundle("classinfo2");
String className=bundle.getString("className");
System.out.println(className);
}
}
类加载器(底层东西 了解)
- 关于JDK中自带的类加载器:
-
- 什么是类加载器??
- 专门负责加载类的命令/工具
- classLoader
-
- JDK中自带了三个类加载器
- 启动类加载器
- 扩展类加载器
- 应用类加载器
-
- 假设有这样一段代码:
- String s=“abc”
- 代码在开始执行前,会将所需要的类全部加载到JVM当中,通过类加载器加载,看到以上代码会找String.class文件,找到就进行加载,那么是怎么加载的??
- 首先通过“启动类加载器”去加载文件
- 如果“启动类加载器”没有加载到,那么就会去执行“扩展类加载器”
- 如果“扩展类加载器”没有加载到,最后会去“应用类加载器”中去加载
这个机制叫做:双亲委派机制
反射一个类中的属性(了解)
package com.bjpowernode.java.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/*
反射Student类当中所有的Field
*/
public class ReflectTest05 {
public static void main(String[] args) throws Exception{
// 获取整个类
Class studentClass =Class.forName("com.bjpowernode.java.bean.Student");
System.out.println(studentClass); // 这是一个完整类名
String simpleName=studentClass.getSimpleName();
System.out.println(simpleName);// 这是一个简单类名
// 获取类中所有的public 修饰的Field
Field[] fields=studentClass.getFields();
System.out.println(fields.length);
// 取出这个Field
Field f=fields[0];
// 取出这个Field的名字
String fieldName=f.getName();
System.out.println(fieldName);
System.out.println("--------------------------------");
// 获取所有的field
Field[] fs=studentClass.getDeclaredFields();
System.out.println(fs.length);
for (Field field:fs){
// 获取属性的修饰符列表
int i=field.getModifiers(); // 返回的是一个int 类型 每一个数字是一个代号
System.out.println(i);
// 可以将这个数字转换为字符串吗??
String modifierString=Modifier.toString(i);
System.out.println(modifierString);
// 获取属性的类型
Class fieldType=field.getType();
String fName=fieldType.getSimpleName();
System.out.println(fName);
// 获取属性的名字
System.out.println(field.getName());
}
}
}
直接进行反编译(了解)
package com.bjpowernode.java.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/*
反编译:反编译一个类的属性Filed
*/
public class ReflectTest06 {
public static void main(String[] args) throws Exception{
// 创建这个是为了拼接字符串
StringBuilder s=new StringBuilder();
Class studentClass=Class.forName("java.lang.Thread");
s.append( Modifier.toString(studentClass.getModifiers()) +" class "+studentClass.getSimpleName()+"{\n");
Field[] fields=studentClass.getDeclaredFields();
for (Field field:fields){
s.append("\t");
s.append(Modifier.toString(field.getModifiers()));
s.append(" ");
s.append(field.getType().getSimpleName());
s.append(" ");
s.append(field.getName());
s.append(";\n");
}
s.append("}");
System.out.println(s);
}
}
通过反射机制反射一个类的属性(重点******)
package com.bjpowernode.java.reflect;
import java.lang.reflect.Field;
/*
必须掌握:
怎么通过反射机制访问一个java对象的属性??
给属性赋值 set
获取属性的值 get
*/
public class ReflectTest07 {
public static void main(String[] args) throws Exception{
// 使用反射机制去获取一个类的属性
Class studentClass=Class.forName("com.bjpowernode.java.bean.Student"); // 通过反射机制拿到class
Object obj=studentClass.newInstance(); // obj就是当前类
// 获取no属性(属性和属性之间依靠名字来区分)
Field noField=studentClass.getDeclaredField("no");
// 给obj对象的no属性赋值
// 还是需要三要素:
// 一:obj对象
// 二:no属性
// 三:赋值
noField.set(obj,1111); // 给obj对象的no赋值1111
// 读取属性的值
System.out.println(noField.get(obj));
// 可以访问私有属性的值吗??
Field nameField=studentClass.getDeclaredField("name");
// 打破封装 缺点:反射机制的特点 可能会给不法分子留下机会
nameField.setAccessible(true);
// 给name赋值
nameField.set(obj,"jack");
// 获取属性值
System.out.println(nameField.get(obj));
}
}
可变长度
package com.bjpowernode.java.reflect;
/*
可变长度参数
int.. args 这就是可变参数
语法是:类型...(注意:一定是3个点)
可变长度参数要求的参数个数是:0到N个
可变长度参数在参数列表中只能有一个,并且要放在最后一个
可变长度可以看作一个数组
*/
public class ArgsTest {
public static void main(String[] args) {
m();
m(10);
m(10,20);
m3("ab","ac","aa","ss");
//直接传一个数组
m3(new String[]{"我","是","中","国","人"});
}
public static void m(int... args){
System.out.println("m方法执行了");
}
public static void m2(int a,String... args){}
public static void m3(String... args){
// args有length属性,说明args是一个数组
// 可以将可变长度当作一个数组来看
for (int i=0;i<args.length;i++){
System.out.println(args[i]);
}
}
}
反编译方法
package com.bjpowernode.java.reflect;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/*
反射Method
*/
public class ReflectTest08 {
public static void main(String[] args) throws Exception{
// 还是得先拿到class
Class userServiceClass=Class.forName("com.bjpowernode.java.service.UserService");
// 获取所有得Method
Method[] methods= userServiceClass.getDeclaredMethods();
System.out.println(methods.length);
// 遍历方法
for (Method method:methods){
// 获取修饰符列表
System.out.println(Modifier.toString(method.getModifiers()));
// 获取方法的返回值类型
System.out.println(method.getReturnType().getSimpleName());
// 获取方法名
System.out.println(method.getName());
// 获取方法的修饰符列表
Class[] parameterTypes= method.getParameterTypes();
for (Class parameterType:parameterTypes){
System.out.println(parameterType.getSimpleName());
}
}
}
}
package com.bjpowernode.java.service;
/*
用户业务类
*/
public class UserService {
// 登录方法
public boolean login(String name,String password){
if ("admin".equals(name) && "123".equals(password))
return true;
return false;
}
// 退出系统方法
public void logout(){
System.out.println("退出系统成功");
}
}
通过反射机制去调用方法(重点********)
package com.bjpowernode.java.reflect;
import java.lang.reflect.Method;
/*
通过反射机制怎么去调方法(重点)
反射机制让代码很具有通用性
*/
public class ReflectTest10 {
public static void main(String[] args) throws Exception{
// 获取一个类
Class userServiceClass =Class.forName("com.bjpowernode.java.service.UserService");
// 获取当前的类的对象
Object obj=userServiceClass.newInstance();
// 获取方法名
Method loginMethod=userServiceClass.getDeclaredMethod("login", String.class, String.class);
// 调用方法 几个要素
// 对象 方法名 实参列表 返回值
// 反射机制中最最最重要的一个方法,必须死记硬背
Object reValue=loginMethod.invoke(obj,"admin","123");
System.out.println(reValue);
}
}
反编译一个类的Constructor构造方法
package com.bjpowernode.java.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
/*
反编译一个类Constructor的构造方法
*/
public class ReflectTest11 {
public static void main(String[] args) throws Exception{
// 进行字符串的拼接
StringBuilder s=new StringBuilder();
Class vipClass=Class.forName("com.bjpowernode.java.bean.Vip");
s.append(Modifier.toString(vipClass.getModifiers()));
s.append("class");
s.append(vipClass.getSimpleName());
s.append("\n");
// 拼接构造方法
Constructor[] constructors=vipClass.getDeclaredConstructors();
for (Constructor constructor:constructors){
s.append("\t");
s.append(Modifier.toString(constructor.getModifiers()));
s.append(" ");
s.append(vipClass.getSimpleName());
s.append("(");
// 拼接参数
Class[] parameterTypes=constructor.getParameterTypes();
for (Class parameterType:parameterTypes){
s.append(parameterType.getSimpleName());
s.append(",");
}
s.deleteCharAt(s.length()-1);
s.append("){}\n");
s.append("{}\n");
}
s.append("}");
System.out.println(s);
}
}
通过反射机制怎么创建对象
package com.bjpowernode.java.reflect;
import java.lang.reflect.Constructor;
/*
通过反射机制怎么new对象
通过反射机制调用构造方法实例化java对象(这个不是重点)
*/
public class ReflectTest12 {
public static void main(String[] args) throws Exception{
// 使用反射机制怎么创建对象
Class c=Class.forName("com.bjpowernode.java.bean.Vip");
// 获取当前对象
Object obj=c.newInstance();
System.out.println(obj);
// 调用有参的构造方法
Constructor con=c.getDeclaredConstructor(int.class,String.class,String.class,boolean.class);
// 调用构造方法new 对象
Object newObj=con.newInstance(110,"jackson","1990-10-11",true);
System.out.println(newObj);
// 调用无参构造方法
Constructor constructor=c.getDeclaredConstructor();
Object obj2=constructor.newInstance();
System.out.println(obj2);
}
}
给你一个类,怎么获取这个类的父类,以及实现了那些接口??(重点**)
package com.bjpowernode.java.reflect;
/*
给你一个类,怎么去获取一个类的父类以及接口??
*/
public class ReflectTest13 {
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 inface:interfaces){
System.out.println(inface.getName());
}
}
}