Java之反射第十八天( --反射----类的加载--获取对象属性( 成员变量和方法)-- 构造方法 )
你想获得什么样的成功 ,你愿意为这份成功付出什么?
https://blog.csdn.net/BuddyUU/article/details/52458241 反射精讲!
1. 类的加载
https://blog.csdn.net/zcxwww/article/details/51330327 ----网址内有具体的解析类加载1. 加载过程: 将.class文件加载到内存里面;
把编译完成的class文件,加载到方法区;
在堆区创建一个表示class文件的对象; ( 反射主要就是使用这一方面 );
2. 链接
2. 验证: 查看一下你这个类的内部结构, ( 成员变量和成员方法);
3.准备 : 为静态成员开辟内存空间并且进行赋初始值;
4.解析: 将虚拟机常量池中的符号引用替换成直接引用的过程; 例如c=1 将c的位置变为1;
3.初始化: 在初始化阶段, 则是根据程序员通过程序的主管计划初始化类变量和其他资源;
java虚拟机规范了4种情况必须立即对垒进行初始化( 加载 验证 准备 必须在此之前进行完成 )
1. 当使用new 关键字实例化对象是,当读取或者设置一个类的静态字段( 被final修饰的除外),以及调用
一个类的静态方法是( 比如构造方法就是静态方法,)如果类未初始化,则需要先进性初始化;
2. 通过反射机制对类进行调用时,如果类没有初始花化,则先需要初始化;
3.当初始化一个类是, 如果其父类没有进行初始化, 县初始化父类;
4.用户指定的执行主类( 含有main 方法的那个类 ),在虚拟机启动的时候,会先被初始化;
除了上面这4种方式,所有引用类的方式都不会触发初始化,称为被动引用。如:通过子类引用父类的静态字段,不会导致子类 初始化;通过数组定义来引用类,不会触发此类的初始化;引用类的静态常量不会触发定义常量的类的初始化,因为常量在编 译阶段已经被放到常量池中了。
以上: 类的加载并且使用的整个过程, java的类只有在需要的时候才会被加载进来,为内存节约了很大的空间;
2. 类使用什么进行加载?
类使用类加载器进行加载( 共三种)
1. 根加载器; 加载java的核心类库,系统的库;
2. 扩展加载器: ext结尾的都是扩展加载器进行加载的;
3 . 系统加载器: 加载我们放进去的第三方类库;
3.反射:
反射可以把一个正在运行的类( 已经加载到内存中的类)
通过class文件的对象直接获取, 该文件中的成员变量和方法( 可以是私有权限,包括private修饰的);
4. 如何获取class文件对象, class类 共三种方式;
1. 对象获取: object.getClass();
2. 类名进行获取 ; 类名.class
3. Class的静态方法获取; Class.forName( com.lan.Person); 括号里面是包加类名;
1.获取Class对象的三种方法展示;
/*
* Class文件对象的获取;
*/
public class 自我练习使用 {
public static void main(String[] args) throws ClassNotFoundException {
// 第一种获取方式
Person p1 = new Person();
Class<? extends Person> class1 = p1.getClass();
System.out.println(class1);
//打印结果 class com.lanou3greflect.Person
// 第二中获取方式;
Class<?> c2 = Person.class;
System.out.println(c2);
// 第三种方式 静态获取;
Class<?> c3 = Class.forName("com.lanou3greflect.Person");
System.out.println(c3);
}
}
2.获取构造方法 getConstructor( type.class, type.class ); 利用构造方法创建对象newInstance();
public static void main(String[] args) throws ClassNotFoundException, Exception, Exception {
// funclass类的获取();
// 第一步: 先使用静态获取类;获取类中的构造方法,找到person类;
Class<?> c1 = Class.forName("com.lanou3greflect.Person");
// 第二步: 获取类中的构造方法; 获取到的是所有的构造方法;是个数组;
Constructor<?>[] cons = c1.getConstructors();
System.out.println(Arrays.toString(cons));
// 获取类中无参构造方法
Constructor<?> con1 = c1.getConstructor();
System.out.println(con1);
// 获取有参构造方法
Constructor<?> con2 = c1.getConstructor(String.class, int.class);
System.out.println(con2);
//通过有参构造方法进行创建对象; instance 实例的
Object newInstance = con2.newInstance("张建海",26);
System.out.println(newInstance);
}
3. 利用 Class文件对象直接进行对象的创建
// 利用class文件对象,快速创建对象; 要求( 1.构造方法必须public 修饰, 2. 类是public修饰) 3.必须提供无参构造方法
Class<?> class1 = Class.forName("com.lanou3greflect.Person");
Object newInstance = class1.newInstance();
System.out.println(newInstance);
4. 获取私有化的构造方法;
// fun2获取构造方法创建对象();
// fun3快速创建对象();
// 获取私有化构造方法 也就是private修饰的;
// 第一步 创建class对象
Class<?> forName = Class.forName("com.lanou3greflect.Person");
// 第一步: 使用获取私有方法的构造方法;
Constructor<?> constructor = forName.getDeclaredConstructor(int.class, String.class);
// 第三步 : 打开构造方法的访问权限;
constructor.setAccessible(true);
// 第四步进行赋值
Object person = constructor.newInstance(18, "胡小青");
System.out.println(person);
5. 获取成员变量getFiled() ,getDeclaredFiled(),
// 获取成员方法
// 1.获取Class.forName;
Class<?> class1 = Class.forName("com.lanou3greflect.Person");
// 获取所有的成员变量,是个数组;只能获取公开的;
Field[] fields = class1.getFields();
for (Field field : fields) {
System.out.println(field);
}
// 获取单个成员变量 NoSuchFieldException在获取私有的时候和没有这个成员变量的时候,
//Field field = class1.getField("age");
//System.out.println(field);
//获取单个私有的成员变量
Field declaredField = class1.getDeclaredField("age");
//开放访问权限
declaredField.setAccessible(true);
System.out.println(declaredField);
6.获取成员方法getMethod()
// fun5获取成员变量();
// 第一步: 获取Class.forName
Class<?> c = Class.forName("com.lanou3greflect.Person");
// 获取 : 成员方法 获取所有的方法,包括继承过来的方法
Method[] methods = c.getMethods();
for (Method method : methods) {
System.out.println(method);
}
// 第二步 :获取单个成员方法; 有参数就填class文件;
Method method = c.getMethod("eat");
System.out.println(method);
// invoke
// 参数1表示用哪个对象, 参数2: 方法传入;
Object object = c.newInstance();
// 该方法的返回值就是调用这个方法的返回值;
Object invoke = method.invoke(object);
System.out.println(invoke + "---我是返回值");
// 调用待返回值得成员方法;和参数名
Method method2 = c.getMethod("speak", String.class);
//给object的对象的方法进行赋值;
Object invoke2 = method2.invoke(object, "中国话");
//invoke2是返回值;
System.out.println(invoke2 + "喂喂喂");
// 调用私有方法;
Method declaredMethod3 = c.getDeclaredMethod("playGame", String.class);
declaredMethod3.setAccessible(true);
Object invoke3 = declaredMethod3.invoke(object, "lol");
// 没有返回值,返回值是Null
System.out.println(invoke3);