-
2020-12-14 16:27:05
https://blog.csdn.net/wei_zhi/article/details/52730249
更多相关内容 -
Java反射机制详解
2020-09-03 01:54:51主要介绍了Java反射机制,首先简单介绍了反射机制的预备知识,进一步分析了Java反射机制的原理、实现技巧与应用方法,需要的朋友可以参考下 -
java反射机制详解
2017-05-11 20:10:41java反射机制的详细描述 -
Java 反射机制详解及实例
2020-08-31 00:45:14主要介绍了Java 反射机制详解及实例的相关资料,需要的朋友可以参考下 -
JAVA反射机制详解视频
2018-12-30 15:05:21(通过反射获取无参构造方法并使用) (通过反射获取带参构造方法并使用) (通过反射获取私有构造方法并使用) (通过反射获取成员变量并使用) (通过反射获取无参无返回值成员方法并使用) (通过反射获取带参带返回值成员... -
JAVA反射机制详解
2021-04-09 14:59:52(1)Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。 (2)Java属于先编译再...一、什么是java的反射机制:
(1)Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。
(2)Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。
(3)Java的反射机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键
**
二、java的反射机制的原理
(1)首先明确的概念: 一切皆对象----类也是对象.
(2)然后知道类中的内容 :modifier constructor field method.
(3)其次明白加载: 当Animal.class在硬盘中时,是一个文件,当载入到内存中,可以认为是一个对象,是java.lang.class的对象.
**
三、java的反射机制的原理的功能
(1)在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。
(2)Java的反射机制就是增加程序的灵活性,避免将程序写死到代码里。 例如: 实例化一个 person()对象, 不使用反射,需要new person(); 如果想变成实例化其他类,那么必须修改源代码,并重新编译…
-
Java 反射机制详解及实例代码
2020-09-01 15:36:06本文主要介绍Java 反射机制的知识,这里提供示例代码帮助大家学习理解此部分知识,有需要的小伙伴可以参考下 -
java 反射机制详解及实例代码
2020-09-01 07:33:04主要介绍了java 反射机制详解及实例代码的相关资料,需要的朋友可以参考下 -
Java反射机制详解_动力节点Java学院整理
2020-08-30 09:39:11主要为大家详细介绍了Java反射机制的相关资料,主要包括反射的概念、作用 -
java反射机制详解与应用.pdf
2022-07-14 14:30:44java反射机制详解与应用.pdf -
java 反射机制详解
2008-12-17 09:56:54比较详细讲述了java的反射机制,收获颇丰。希望大家能够共同学习,一起进步。 -
java反射机制详解及Method.invoke解释.pdf
2021-11-17 01:19:25java反射机制详解及Method.invoke解释.pdf -
Java 反射机制详解
2021-03-16 12:21:29引言本文主要介绍Java中,有关反射机制、类的加载过程、以及控制反转方面的内容。Java 反射机制Java创建对象的方式有哪些:new、反射、反序列化、克隆class对象获取的方法有哪些:类名.class、getClass、forName、...引言
本文主要介绍Java中,有关反射机制、类的加载过程、以及控制反转方面的内容。
Java 反射机制
Java创建对象的方式有哪些:new、反射、反序列化、克隆
class对象获取的方法有哪些:类名.class、getClass、forName、classLoader.loadClass(‘包类名全路径’)---> 区别在于有没有初始化步骤(statis)
类的加载顺序
Class装载过程:加载、链接(验证、准备、解析)、初始化
Class初始化的详细步骤:
如果这个类还没有被加载和链接,那就先进行加载和链接
如果这个类存在父类,并且父类还没有初始化,那就先初始化直接父类
如果类型存在初始化语句,一次执行初始化语句
Class初始化6大时机:
创建类的实例(new、class.newInstance、constructor.newInstance)
访问类中的某个静态变量,或者对静态变量进行赋值
调用类的静态方法
Class.forName
完成子类的初始化
程序的引导入口
JDBC编程为什么用Class.forName类进行加载驱动?--> 通过classforName 进行初始化statis、注册Driver
Java反射
优点:增加代码的灵活度、可读性更强;
缺点:(在量大的情况下)相比较于直接调用性能会下降、封装性不好(会暴露内部安全)
反射慢的原因:寻找class字节码的过程、判断安全机制
Java反射中,如果需要对私有的属性进行访问,需要设置强制访问(setAccessible)。
class.newInstance()的本质是什么?--> 该方案会首先找指定class中默认的无参数的构造函数(如果该class已经设定了一个新的有参数的抛出异常)
Java控制反转(Spring IOC和DI)
IOC(控制反转),把创建对象的控制权交给程序(容器):构造器、静态工厂、实例方法
DI(依赖注入),对象创建过程中,容器动态构建所需的对象:构造器、setter函数
-
Java 反射机制实例详解
2020-08-29 11:43:40主要介绍了Java 反射机制实例详解的相关资料,这里对java中反射机制进行了详细的分析,需要的朋友可以参考下 -
android系统java反射机制详解
2017-03-26 21:55:27详细解析java的反射机制 -
Java-反射机制详解
2022-04-12 20:56:082 通过反射机制反编译一个类的属性,方法,构造方法。 3 通过反射机制访问一个类的【属性】,调用一个类的【方法】及【构造方法】。 4 注释反射 5 通过I/O流读取users1info文件来获取字符串类名进行反射操作 6 利用...1 定义: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法,这种动态获取、调用对象方法的功能称为java语言的反射机制。
2 作用: 反射机制可以操作字节码文件,也就是说通过反射我们可以获取构造器,对象,属性,方法(原本不知道)
一, 获取class的三种方式
(1) 通过该类的对象去获取到对应的Class对象
Class string_class01 = " ".getClass();
这种方法基本不用,这里显然和反射机制相悖(已有类对象 了还去用反射获取Class类对象干嘛,多此一举)
(2) 通过全限定名来获取Class对象
Class string_class02 = Class.forName("java.lang.String");
(3) 通过类名.class
最好用,也更安全!
Class string_class03 = String.class;
public class test06 { public static void main(String[] args) throws ClassNotFoundException { Class string_class01 = " ".getClass(); Class string_class02 = Class.forName("java.lang.String"); Class string_class03 = String.class; System.out.println(string_class01); System.out.println(string_class02); System.out.println(string_class03); } } //结果 //class java.lang.String //class java.lang.String //class java.lang.String
二,类Field,Method ,Constructor
通过反射机制反编译一个类的属性,方法,构造方法。
public class test05 { public static void main(String[] args) throws Exception { Class user02 = Class.forName("fans.users1"); StringBuilder str = new StringBuilder(); str.append(Modifier.toString(user02.getModifiers())+" class "+user02.getSimpleName()+"{\n"); //通过Field类反射获取类users1属性 Field[] field = user02.getDeclaredFields(); for(Field f:field) { str.append("\t"+Modifier.toString(f.getModifiers()) +" "+f.getType().getSimpleName() +" "+f.getName()+" \n"); } //通过Constructor类反射获取类users1构造方法 Constructor[] con = user02.getConstructors(); str.append("\n"); for(Constructor c :con) { str.append("\t"+Modifier.toString(c.getModifiers())+" " +user02.getSimpleName()+"("); Class[] pp = c.getParameterTypes(); for(Class cc:pp) { str.append(cc.getSimpleName()+","); } if(pp.length>0) { str.deleteCharAt(str.length()-1); } str.append("){}\n"); } //通过Method类反射获取类users1方法 Method[] method = user02.getDeclaredMethods(); str.append("\n"); for(Method m:method) { str.append("\t"+Modifier.toString(m.getModifiers())+" " +m.getReturnType().getSimpleName()+" " +m.getName()); str.append("( "); Class[] p = m.getParameterTypes(); for(Class p01:p) { str.append(p01.getSimpleName()+","); } str.deleteCharAt(str.length()-1); str.append("){}\n"); } str.append("}"); System.out.println(str); } }
通过反射机制访问一个类的【属性】,调用一个类的【方法】及【构造方法】。
public class test06 { public static void main(String[] args) throws Exception { //通过new调用users1的方法 users1 u01= new users1(); if( u01.login("admin", "Admin@123")) System.out.println("登入成功!"); else System.out.println("用户名或密码错误!"); System.out.println("------------------------"); //通过反射调用users1的方法 // 获取类的class Class u02class = users1.class; //创建对象 Object u0201 = u02class.newInstance();//该操作会默认调用无参构造 //获取method Method loginmethod = u02class.getDeclaredMethod("login", String.class,String.class); //获取loginmethod的invoke方法的返回值 Object retValue = loginmethod.invoke(u0201, "admin","Admin@123"); System.out.println(retValue); boolean retlogin = (boolean) retValue; System.out.println(retlogin?"登入成功!":"登入失败!"); Method loninmethod01 = u02class.getDeclaredMethod("login", String.class); boolean retlogin01 = (boolean) loninmethod01.invoke(u0201, "admin"); System.out.println(retlogin01?"登入成功!":"登入失败!"); //调用无参方法 u02class.getDeclaredMethod("logout").invoke(u0201); System.out.println("------------------------"); //通过new调用users1的构造方法 users1 u02 = new users1(); users1 u03 = new users1("张三"); users1 u04 = new users1(true, "李四"); System.out.println("------------------------"); //通过反射调用users1的构造方法 //创建class Class u03class = Class.forName("fans.users1"); Object u0301 = u03class.newInstance(); Constructor cons = u03class.getConstructor(); cons.newInstance(); Constructor cons01 = u03class.getConstructor(String.class); cons01.newInstance("张三"); Constructor cons02 = u03class.getConstructor(boolean.class,String.class); cons02.newInstance(true,"李四"); Constructor cons03 = u03class.getConstructor(int.class,String.class); Object retcons03 = cons03.newInstance(22,"赖滢"); System.out.println(retcons03); System.out.println("------------------------"); //通过new访问users1的属性 users1 u05 = new users1(); u05.name = "张三"; u05.age = 20; u05.sex = true; System.out.println(u05); System.out.println("------------------------"); //通过反射访问users1的属性 Field ff = u03class.getDeclaredField("name"); ff.set(u0301, "张三"); System.out.println(ff.get(u0301)); Field ff01 = u03class.getDeclaredField("ID"); ff01.setAccessible(true);//访问私有属性时需打破封装但会破坏其安全性 ff01.set(u0301, 303); System.out.println(ff01.get(u0301)); //获取父类和父接口 System.out.println("------------------获取父类和父接口---------------------"); Class strclass = String.class; Class strsupclass = strclass.getSuperclass(); System.out.println(strsupclass.getName()); Class[] strinter = strclass.getInterfaces(); for(Class c : strinter) { System.out.println(c.getName()); } } }
上面案例用到users1类
public class users1 { private int ID; protected int age; boolean sex; public String name; public static final double MATH_PI = 3.1415926; public users1() { super(); System.out.println("这是无参构造!"); } public users1(String name) { super(); this.name = name; System.out.println(this.name); } public users1(boolean sex, String name) { super(); this.sex = sex; this.name = name; System.out.println(this.sex+"="+this.name); } public users1(int age, String name) { super(); this.age = age; this.name = name; } @Override public String toString() { return "users1 [ID=" + ID + ", age=" + age + ", sex=" + sex + ", name=" + name + "]"; } /** * * @param name 账户 * @param password 密码 * @return */ public static boolean login(String name,String password) { if("admin".equals(name)&&"Admin@123".equals(password)) return true; return false; } public void logout() { System.out.println("账户已安全退出!"); } public boolean login(String name) { return "admin".equals(name)? true:false; } }
三、反射API
getModifiers()
,获取字段和方法等的修饰符类型,返回值是int类型,什么都不加是0,public 是1,private是2,protected是4,static 是8,final是16,等等,多个修饰符修饰的话,返回的是每个修饰符代表的int值的和、、、、、、、、可自行查API文档
API文档
https://www.runoob.com/manual/jdk1.6/java.base/java/lang/Class.html
四, 注释反射
1 先创建一个名叫ID的注释
若还不会创建和理解的请看Java-注释详解
@Documented @Retention(RUNTIME) @Target({ TYPE, FIELD, METHOD }) public @interface ID { int id() default 205; String name(); mark chengji(); }
2 创建mark(代表成绩且该处用枚举实现)
若不知如何创建或不是很理解就评论 收藏关注后期就出相应教程!
public enum mark { 不及格,及格,良,优; }
3 创建users类并在相应的位置标识注释
@ID(name = "zwy", chengji=mark.不及格) public class users { @ID(name = "zwy", chengji = mark.优) private int ID; protected int age; boolean sex; public String name; public static final double MATH_PI = 3.1415926; }
4 创建被ID注释的类没有有int型的id的异常类
若不知如何创建或不是很理解就评论 收藏关注后期就出相应教程!
public class NotIdException extends RuntimeException{ public NotIdException() { } public NotIdException(String s) { super(s); } }
5 创建测试类test01并实现当被ID注释的类必须有int型的id 属性否则抛出异常!
public class test01 { public static void main(String[] args) throws NoSuchFieldException, SecurityException { Class userclass = users.class; Field ff = userclass.getDeclaredField("ID"); //判断userclass的ID属性是否被注释 System.out.println(ff.isAnnotationPresent(ID.class)); //获取属性的注释属性值 ID id = ff.getAnnotation(ID.class); System.out.println(id.id()); System.out.println(id.name()); System.out.println(id.chengji()); //判断userclass类是否被注释 System.out.println(userclass.isAnnotationPresent(ID.class)); //获取类的注释属性值 ID idclass = (ID) userclass.getAnnotation(ID.class) ; System.out.println(idclass.chengji()); //被ID注释的类必须有int型的id 属性否则抛出异常! boolean isid = false; if(userclass.isAnnotationPresent(ID.class)) { Field[] field = userclass.getDeclaredFields(); for(Field f:field) { if("ID".equals(f.getName())&& "int".equals(f.getType().getSimpleName())) { isid = true; break; } } if(!isid) { throw new NotIdException("被ID注释的类必须有int型的id 属性"); } } } }
五, 可变长度参数
1 长度个数:0~n 2 可变 长度参数必须在参数列表最后一个位置上,而且可变长度参数只能有一个 3 可将可变长度参数看作一个数组
public class test04 { public static void main(String[] args) { m(); m(1,2); m(1,2,3); m2(1,"abc"); m2(1,"abc","dc"); m3(" ","abc","de","f"); String[] strs = {"www",".baidu.","com","//"}; m3(strs); m3(new String[]{"我","是","中","国","人"}); } public static void m(int... args) { System.out.println("m方法执行"); } /* * public static void m1(int... args1 ,String... args2) { }//报错!只要一个且在最后! */ public static void m2(int a,String...args) { System.out.println("m2方法执行"); } public static void m3(String...args) { //args有length说明是一个数组 for(int i=0;i<args.length;i++) { System.out.print(args[i]+" "); } } }
六, 扩展
1 通过I/O流读取users1info文件来获取字符串类名进行反射操作
//通过I/O流读取userinfo文件 FileReader reader = new FileReader("userinfo1"); File f = new File("userinfo1"); //创建属性类对象 Properties p = new Properties(); //加载 p.load(reader); //关闭流 reader.close(); Class s3 = Class.forName(p.getProperty("students")); System.out.println(s3);
2 获取userinfo文件的绝对路径(增强代码的健壮性)
String path = Thread.currentThread().getContextClassLoader().getResource("fans/userinfo2").getPath();
InputStream reader = Thread.currentThread().getContextClassLoader().getResourceAsStream("fans/userinfo2");
3 若获取的绝对路径有中文乱码进行解码
URLDecoder.decode(path,"UTF-8")
String path = Thread.currentThread().getContextClassLoader().getResource("fans/userinfo2").toURI().getPath();
4 使用绝对路径进行获取字符串类名
InputStream reader = Thread.currentThread().getContextClassLoader().getResourceAsStream("fans/userinfo2"); FileReader fr01 = new FileReader(path); Properties p01 = new Properties(); p01.load(reader); reader.close(); Class c01 = Class.forName(p01.getProperty("students")); System.out.println(c01);
5 利用Java自带的资源绑定器获取字符串类名
ResourceBundle b = ResourceBundle.getBundle("fans/userinfo2");资源绑定器 System.out.println(b.getString("students"));
6 在fans包下的txt文件userinfo2
students=fans.students
7 public private protected 的简单区别
//public private protected 的简单区别 1、public:public表明该数据成员、成员函数是对所有用户开放的,所有用户都可以直接进行调用 2、private:private表示私有,私有的意思就是除了class自己之外,任何人都不可以直接使用。 3、protected:protected对于子女、朋友来说,就是public的,可以自由使用,没有任何限制,而对于其他的外部class,protected就变成private。
8 通过反射机制访问一个Java对象的属性,并给属性赋值(set)及获取属性值(get)
public class test03 extends users { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException { students stu01 = new students(); users user01 = new users(); Class usersClass = Class.forName("fans.users"); //通过new,普通访问一个对象的属性 //赋值 stu01.no=111; //获取 System.out.println(stu01.no); //使用反射机制,创建对象 Object obj = usersClass.newInstance();//会自动调用无参构造 //获取no属性 Field nofield = usersClass.getDeclaredField("no"); //给obj对象no属性赋值 nofield.set(obj, 222); System.out.println(nofield.getName()+"="+nofield.get(obj)); //访问私有属性需要打破封装(打破封装会带来安全问题)才能访问赋值获取 Field idfield = usersClass.getDeclaredField("ID"); idfield.setAccessible(true);//打破封装 idfield.set(obj, 306); System.out.println(idfield.getName()+"="+idfield.get(obj)); Field agefisld = usersClass.getDeclaredField("age"); agefisld.set(obj, 18); System.out.println(agefisld.getName()+"="+ agefisld.get(obj)); //正常new的对象不能访问私有属性,要访问须继承对象类并获取set(),get()方法 //user01.ID;//报错访问不了 //去users类下获取获取set(),get()方法,通过调用方法进行赋值和取值 user01.setID(207); System.out.println("user01ID="+ user01.getID()); } }
9 只要类加载静态代码快就会执行(所以若只执行类中的静态代码快可以使用反射机制进 行加载)
public class test02 { public static void main(String[] args) throws ClassNotFoundException, IOException, URISyntaxException { //students s = new students(); Class c = Class.forName("fans.students"); } } class students { int no; private int ID; public students() { System.out.println("这是个无参构造方法!"); } static { System.out.println("这里是静态代码块"); } }
//该通过new对象进行实例化加载会运行整代码块
//运行结果://通过反射进行类加载只会运行静态类加载块
10 获取Class之后,可以调用无参数构造方法来实例化对象
//通过反射获取class ,通过class实例化对象 Class s = Class.forName("fans.students"); Object s1 = s.newInstance();//已过时,该方法会默认调用无参构造方法,所以必须保证无参构造存在。 //通过new实例化对象 students s2 = new students();
11 Java的getCanonicalName和getName ,getSimpleName()
-
Java 反射机制的实例详解
2020-08-29 03:41:31主要介绍了Java 反射机制的实例详解的相关资料,希望通过本文能帮助到大家,让大家理解掌握反射机制,需要的朋友可以参考下