欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java之反射第十八天( --反射----类的加载--获取对象属性( 成员变量和方法)-- 构造方法 )

程序员文章站 2023-12-21 13:19:22
...

                                                你想获得什么样的成功 ,你愿意为这份成功付出什么?

    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);
	

上一篇:

下一篇: