您的位置:首页 > 其它

反射学习笔记(二) - - 暴力反射 - -

2018-03-12 23:18 162 查看
src==> 源文件存放位置
bin==> bean 文件

_____________________________________________________________
=============================================================
++++++++++++++++++++++++  反射  笔记  +++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
_____________________________________________________________
-->
面向对象: 万物皆对象
--> java类 : 类的组成部分
( 1 )每个类都有一个package
( 2 )每个类有一个类名
( 3 )构造方法
( 4 )属性
( 5 )普通方法
.......                    静态方法 未包括
=============================================================
--->     反射的根基 : java 开发者为我们提供了一个类来描述 java  文件 ,这个类为Class
同时,Class 类型对应的对象可以代表某一个某一个类的字节码文件
public class  Class  {
......
}
对象代表字节码文件
字节码文件类型  ===>    . class
==================================
---> 如何获取某一类的字节码文件?   ====>     获取一个类的对象
--------------------------------------------------------
[ 注: 反射不能 new 出来  , 没有 new ]
三种方式获取:
--> 通过类名.class
--> 类名.forName("某个类的全路径")
--> 对象名 .getClass( )                                    [ - 点不能丢 - ]
---------------------------------------------------------
@Test           //获取User的字节码文件
public void ReflectionTest1() throws ClassNotFoundException {
//通过类名获取字节码文件
Class userClass = User.class;                   <----------   第一种
//通过.forName获取字节码文件
Class u = Class.forName("User");                <----------   第二种
//通过.getClass 获取
User user = new User();
Class get =  user.getClass();                   <----------   第三种
//以上三者获取的是同一个字节码文件 , sout 输出  true
// 注意       第三种获取的方式需要实例化对象,通过对象的.getClass方法获取
System.out.println(u==userClass);
System.out.println(u==get);
}
----------------------------------------------------------
所有类的底层都是字节码===> 二进制文件
----------------------------------------------------------
* 通过反射创建对象
* 所谓的反射,将一个类中的  各个成员   映射    成    相对应的   java类型
*    ==================================================================
*     各个成员: 包括 { 包 --> package, 构造器 ---> Contructor ,  属性字段 ---> Field ,  普通方法 ----> Method }
*    ==================================================================
*
*  spring 机制 :
*        <bean id = " xx "  class = " com.xsh.User " ></bean>
*  ====>  通过   Class.forName( " 类的全路径 ")    获取  字节码文件
*         以字节码文件为纽带,创建实例.
*
---------------------------------------------------------
@Test
public void ReflectionTest2() throws Exception {
// 1/获取字节码文件
Class  userClass = Class.forName("User");
//2/需要创建一个对象, ===>  创建对象一定需要调用构造方法  调用类中的无参构造方法来创建构造对象
Constructor[] constructors = userClass.getConstructors();
for (Constructor constructor : constructors ) {             ====>
System.out.println(constructor);                        ===
4000
=> for循环打印所以构造方法
}                                                           ====>
//通过字节码获取无参构造方法
Constructor constructor =userClass.getConstructor();
//通过无参构造方法,创建对象
User u = (User) constructor.newInstance();
System.out.println(u);      ===>   打印出对象: 证明通过映射成功创建对象
//通过字节码获取有参构造方法
Constructor constructor1 = userClass.getConstructor(String.class,int.class);
User uu = (User) constructor1.newInstance("张三",21);        ===> 这里是赋值给通过映射创建的对象
System.out.println(uu);     ===>   打印出对象: 证明通过映射成功创建对象
}
------------------------------------------------------------
反射对象和传统对象效率相比:  反射的效率比传统方式低很多
----> 创建一百个对象速度相比,低至 10~ 20 倍   我自己测是这样的 ,  总结就是低很多...量越大,效率越低
------------------------------------------------------------
==================================================================================================================
public class User {
private String name = "张三李四";           //姓名
int age = 26;           //年龄
protected float weight = 60.5F;         //体重
public float height = 180.5F;       //身高

构造方法略过....
}
==================================================================================================================
1 /  在不给出任何接口的情况下( toString 方法也不给出 )如何获取到User类中私有属性的值  ?   ====>  反射
-------------------------------------------------------------------------
* ==================================================================
* 通过反射获取某一个实体对象的属性字段及其值
*          1/通过反射获取public.protect,默认修饰符修饰的属性字段和值
*          2/通过暴力反射获取 私有属性字段及其值   private 修饰的
* ==================================================================
*  反射里将属性封装成了field类型 :
*          修饰符         数据类型      属性名
*      getFields() ===>  只能获取public修饰的属性
*      getDeclaredFields  ====>   获取除了私有的之外的三种修饰符修饰的字段   jdk 8   获取全部
=================================================================
@Test
public void test() throws Exception {
//创建一个对象
Class c = User.class;
User user = (User) c.getConstructor().newInstance();
//获取user这个对象的属性字段
Field[] fields = c.getDeclaredFields();
for (Field s : fields ) {                           [ 这里仅仅是部分方法 仅供参考 ]
System.out.println(s);
}
//获取指定字段的属性             [ 默认=> 0  public=>1 protected =>4  private =>2 ]
Field field = c.getDeclaredField("weight");
System.out.println(field.getType());        //获取字段类型
System.out.println(field.getModifiers());   //返回修饰符的值
System.out.println(field.getName());    //获取字段名字
System.out.println(field.getDeclaringClass().getTypeName());  //获取属性类路径
}
=================================================================
@Test
public void test() throws Exception {
//创建一个对象
Class c = User.class;
User user = (User) c.getConstructor().newInstance();
//获取user这个对象的属性字段
Field[] fields = c.getDeclaredFields();
for (Field s : fields ) {
//   System.out.println(s);
}
//获取指定字段的属性
Field field = c.getDeclaredField("name");
System.out.println(field.getType());        //获取字段类型
System.out.println(field.getModifiers());   //返回修饰符的值
System.out.println(field.getName());    //获取字段名字
System.out.println(field.getDeclaringClass().getTypeName());  //获取属性类路径
//暴力反射  ==>  获取所有属性的值   如果某个属性被私有化,想要获取就需要通过暴力反射
field.setAccessible(true);
Object o = field.get(user);
System.out.println(o);
//修改某字段值
field.set(user,"牛二刘三");
System.out.println(user);           //修改成功
}
=================================================================
========================================================================================================================
[ 默认=> 0  public=>1 protected =>4  private =>2 ]   为什么没有3?
1Byte  =    8  bit
字节          位               计算机底层 二进制    一个字节 ==>  8 位
计算机传输的时候每次最少是一个八位的字节
1==> 高电压
0==> 低电压          00000000      0
00000010      1*2^0 = 1
00000100      1*2^1 = 2
00001000      1*2^2 = 4
这样的传输效率最高 ===   >   所以没有 3  !
========================================================================================================================
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: