黑马程序员——Java反射机制

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

三种方法获取class类的实例

package com.itheima.zqt;
class X{
};
public class GetClassDemo02{
	public static void main(String args[]){
		Class<?> c1 = null ;		// 指定泛型
		Class<?> c2 = null ;		// 指定泛型
		Class<?> c3 = null ;		// 指定泛型
		try{
			// 以下的操作形式是在开发中最常用的一种形式
			c1 = Class.forName("com.itheima.zqt.X") ;
		}catch(ClassNotFoundException e){
			e.printStackTrace() ;
		}
		c2 = new X().getClass() ;		// 通过Object类中的方法实例化
		c3 = X.class ;	// 通过类.class实例化
		System.out.println("类名称:" + c1.getName())  ;	// 得到类的名称
		System.out.println("类名称:" + c2.getName())  ;	// 得到类的名称
		System.out.println("类名称:" + c3.getName())  ;	// 得到类的名称
	}
};
运行结果:类名称:com.itheima.zqt.X

1.通过无参构造实例化对象 

package com.itheima.zqt ;
class Person{
	private String name ;	// name属性
	private int age ;		// age属性
	public void setName(String name){
		this.name = name ;
	}
	public void setAge(int age){
		this.age = age ;
	}
	public String getName(){
		return this.name ;
	}
	public int getAge(){
		return this.age ;
	}
	public String toString(){	// 覆写toString()方法
		return "姓名:" + this.name + ",年龄:" + this.age  ;
	}
};
public class InstanceDemo01{
	public static void main(String args[]){
		Class<?> c = null ;		// 声明Class对象
		try{
			c = Class.forName("com.itheima.zqt.Person") ;
		}catch(ClassNotFoundException e){
			e.printStackTrace() ;
		}
		Person per = null ;	// 声明Person对象
		try{
			per = (Person)c.newInstance() ;	// 实例化对象
		}catch(Exception e){
			e.printStackTrace() ;
		}
		per.setName("zqt") ;		// 设置姓名
		per.setAge(25) ;				// 设置年龄
		System.out.println(per) ;	// 内容输出,调用toString()
	}
};
如果没有无参构造方法,会报异常,使用反射时尽量保留无参构造方法。

调用有参构造实例化对象

package com.itheima.zqt ;
import java.lang.reflect.Constructor;
class Person{
	private String name ;	// name属性
	private int age ;		// age属性
	public Person(String name,int age){
		this.setName(name) ;
		this.setAge(age);
	}
	public void setName(String name){
		this.name = name ;
	}
	public void setAge(int age){
		this.age = age ;
	}
	public String getName(){
		return this.name ;
	}
	public int getAge(){
		return this.age ;
	}
	public String toString(){	// 覆写toString()方法
		return "姓名:" + this.name + ",年龄:" + this.age  ;
	}
};
public class InstanceDemo02{
	public static void main(String args[]){
		Class<?> c = null ;		// 声明Class对象
		try{
			c = Class.forName("com.itheima.zqt.Person") ;
		}catch(ClassNotFoundException e){
			e.printStackTrace() ;
		}
		Person per = null ;	// 声明Person对象
		Constructor<?> cons[] = null ;
		cons = c.getConstructors() ;
		try{
			per = (Person)cons[0].newInstance("zqt",25) ;	// 实例化对象
		}catch(Exception e){
			e.printStackTrace() ;
		}
		System.out.println(per) ;	// 内容输出,调用toString()
	}
};

取得全部构造方法

package com.itheima.zqt ;
interface China{	// 定义China接口
	public static final String NATIONAL = "China" ;	// 定义全局常量
	public static final String AUTHOR = "zqt" ;	// 定义全局常量
	public void sayChina() ;		// 无参的,没有返回值的方法
	public String sayHello(String name,int age) ;	// 定义有两个参数的方法,并返回内容
}
public class Person implements China{
	private String name ;
	private int age ;
	public Person(){	// 无参构造
	}
	public Person(String name){
		this.name = name ;	// 设置name属性
	}
	public Person(String name,int age){
		this(name) ;
		this.age = age ;
	}
	public void sayChina(){	// 覆写方法
		System.out.println("作者:" + AUTHOR + ",国籍:" + NATIONAL) ;
	}
	public String sayHello(String name,int age){
		return name + ",你好!我今年:" + age + "岁了!" ;
	}
	public void setName(String name){
		this.name = name ;
	}
	public void setAge(int age){
		this.age = age ;
	}
	public String getName(){
		return this.name ;
	}
	public int getAge(){
		return this.age ;
	}
};
public class GetConstructorDemo03{
	public static void main(String args[]){
		Class<?> c1 = null ;		// 声明Class对象
		try{
			c1 = Class.forName("com.itheima.zqt.Person") ;	// 实例化对象
		}catch(ClassNotFoundException e){
			e.printStackTrace() ;
		}
		Constructor<?> con[] = c1.getConstructors() ;	// 取得一个类中的全部构造方法 前面的修饰符必须是public才能取到
              //Constructor<?> con[] = c1.getDeclaredConstructors();   //这个可以不受访问修饰符影响,都能取到
		for(int i=0;i<con.length;i++){
			Class<?> p[] = con[i].getParameterTypes() ;		// 得到构造方法中的全部参数
			System.out.print("构造方法:" ) ;	 // 输出构造,直接打印
			int mo = con[i].getModifiers() ; // 得到所要的访问权限
			System.out.print(Modifier.toString(mo) + " ") ;	// 得到修饰符
			System.out.print(con[i].getName()) ;	// 取得构造方法的名字
			System.out.print("(") ;
			for(int j=0;j<p.length;j++){
				System.out.print(p[j].getName() + " arg" + i) ;
				if(j<p.length-1){
					// 判断此是否是最后一个参数
					System.out.print(",");	// 输出“,”
				}
			}
			System.out.println("){}") ;
		}
	}
};

运行结果:

public com.itheima.zqt.Person()
public com.itheima.zqt.Person(java.lang.String)
public com.itheima.zqt.Person(java.lang.String,int)

取得全部方法

package com.itheima.zqt ;
import java.lang.reflect.Method ;	// 导入构造方法的包
import java.lang.reflect.Modifier ;	// 导入构造方法的包
public class GetMethodDemo{
	public static void main(String args[]){
		Class<?> c1 = null ;		// 声明Class对象
		try{
			c1 = Class.forName("com.itheima.zqt.Person") ;	// 实例化对象
		}catch(ClassNotFoundException e){
			e.printStackTrace() ;
		}
		Method m[] = c1.getMethods() ;	// 取得全部方法
		for(int i=0;i<m.length;i++){
			Class<?> r = m[i].getReturnType() ;	// 得到返回值类型
			Class<?> p[] = m[i].getParameterTypes() ;	// 取得全部参数的类型
			int xx = m[i].getModifiers() ;	// 得到修饰符
			System.out.print(Modifier.toString(xx) + " ") ;	// 输出修饰符
			System.out.print(r + " ") ;
			System.out.print(m[i].getName()) ;
			System.out.print("(") ;
			for(int j=0;j<p.length;j++){
				System.out.print(p[j].getName() + " " + "arg" + j) ;
				if(j<p.length-1){
					System.out.print(",") ;
				}
			}
			Class<?> ex[] = m[i].getExceptionTypes() ;	// 取出异常
			if(ex.length>0){
				System.out.print(") throws ") ;
			}else{
				System.out.print(")") ;
			}
			for(int j=0;j<ex.length;j++){
				System.out.print(ex[j].getName()) ;
				if(j<p.length-1){
					System.out.print(",") ;
				}
			}
			System.out.println() ;
		}
	}
};
运行结果:

public void sayChina()
public class java.lang.String sayHello(java.lang.String arg0,int arg1)
public void setAge(int arg0)
public int getAge()
public class java.lang.String getName()
public void setName(java.lang.String arg0)
public final native void wait(long arg0) throws java.lang.InterruptedException
public final void wait() throws java.lang.InterruptedException
public final void wait(long arg0,int arg1) throws java.lang.InterruptedException,
public boolean equals(java.lang.Object arg0)
public class java.lang.String toString()
public native int hashCode()
public final native class java.lang.Class getClass()
public final native void notify()
public final native void notifyAll()

当使用IDE进行开发的时候.自动弹出提示就是利用这种方式完成的。

取得全部属性

package com.itheima.zqt ;
import java.lang.reflect.Field ;	// 导入构造方法的包
import java.lang.reflect.Modifier ;	// 导入构造方法的包
public class GetFieldDemo{
	public static void main(String args[]){
		Class<?> c1 = null ;		// 声明Class对象
		try{
			c1 = Class.forName("com.itheima.zqt.Person") ;	// 实例化对象
		}catch(ClassNotFoundException e){
			e.printStackTrace() ;
		}
		{	// 本类属性
			Field f[] = c1.getDeclaredFields() ;	// 取得本类中的属性
			for(int i=0;i<f.length;i++){
				Class<?> r = f[i].getType() ;	// 得到属性类型
				int mo = f[i].getModifiers() ;	// 得到修饰符的数字
				String priv = Modifier.toString(mo) ; // 还原修饰符
				System.out.print("本类属性:") ;
				System.out.print(priv + " ") ;	
				System.out.print(r.getName() + " ") ;	// 得到属性类型
				System.out.print(f[i].getName()) ;	// 输出属性名称
				System.out.println(" ;") ;
			}
		}
		{	// 公共属性
			Field f[] = c1.getFields() ;	// 取得本类中的公共属性  继承来的
			for(int i=0;i<f.length;i++){
				Class<?> r = f[i].getType() ;	// 得到属性类型
				int mo = f[i].getModifiers() ;	// 得到修饰符的数字
				String priv = Modifier.toString(mo) ; // 还原修饰符
				System.out.print("公共属性:") ;
				System.out.print(priv + " ") ;	
				System.out.print(r.getName() + " ") ;	// 得到属性类型
				System.out.print(f[i].getName()) ;	// 输出属性名称
				System.out.println(" ;") ;
			}
		}
	}
};
运行结果:

本类属性:private java.lang.String name ;
本类属性:private int age ;
公共属性:public static final java.lang.String NATIONAL ;
公共属性:public static final java.lang.String AUTHOR ;
通过反射调用类中的方法

package com.itheima.zqt ;
import java.lang.reflect.Method ;
public class InvokeSayChinaDemo{
	public static void main(String args[]){
		Class<?> c1 = null ;
		try{
			c1 = Class.forName("com.itheima.zqt.Person") ;	// 实例化Class对象
		}catch(Exception e){}
		try{
			Method  met = c1.getMethod("sayChina") ;	// 找到sayChina()方法
			met.invoke(c1.newInstance()) ;	// 调用方法
		}catch(Exception e){
			e.printStackTrace() ;
		}
	}
};
通过反射调用setter 和getter方法
package com.itheima.zqt ;
import java.lang.reflect.Method ;
public class InvokeSetGetDemo{
	public static void main(String args[]){
		Class<?> c1 = null ;
		Object obj = null ;
		try{
			c1 = Class.forName("org.lxh.demo15.Person") ;	// 实例化Class对象
		}catch(Exception e){}
		try{
			obj = c1.newInstance() ;
		}catch(Exception e){}
		setter(obj,"name","zqt",String.class) ;	// 调用setter方法
		setter(obj,"age",25,int.class) ;	// 调用setter方法
		System.out.print("姓名:") ;
		getter(obj,"name") ;
		System.out.print("年龄:") ;
		getter(obj,"age");
	}
	/**
		Object obj:要操作的对象
		String att:要操作的属性
		Object value:要设置的属性内容
		Class<?> type:要设置的属性类型
	*/
	public static void setter(Object obj,String att,Object value,Class<?> type){
		try{
			Method met = obj.getClass().getMethod("set"+initStr(att),type) ;	// 得到setter方法
			met.invoke(obj,value) ;	// 设置setter的内容
		}catch(Exception e){
			e.printStackTrace() ;
		}
	}
	public static void getter(Object obj,String att){
		try{
			Method met = obj.getClass().getMethod("get"+initStr(att)) ;	// 得到setter方法
			System.out.println(met.invoke(obj)) ;	// 调用getter取得内容
		}catch(Exception e){
			e.printStackTrace() ;
		}
	}
	public static String initStr(String old){	// 将单词的首字母大写
		String str = old.substring(0,1).toUpperCase() + old.substring(1) ;
		return str ;
	}
};

通过反射操作属性

package com.itheima.zqt ;
import java.lang.reflect.Field ;
public class InvokeFieldDemo{
	public static void main(String args[]) throws Exception{
		Class<?> c1 = null ;
		Object obj = null ;
		c1 = Class.forName("com.itheima.zqt.Person") ;	// 实例化Class对象
		obj = c1.newInstance() ;
		Field nameField = null ;
		Field ageField = null ;
		nameField = c1.getDeclaredField("name") ;	// 取得name属性
		ageField = c1.getDeclaredField("age") ;	// 取得name属性
		nameField.setAccessible(true) ;	// 此属性对外部可见
		ageField.setAccessible(true) ;	// 此属性对外部可见
		nameField.set(obj,"zqt") ;	// 设置name属性内容
		ageField.set(obj,30) ;			// 设置age属性内容
		System.out.println("姓名:" + nameField.get(obj)) ;
		System.out.println("年龄:" + ageField.get(obj)) ;
	}
};
以上操作属性的方法比之前使用setter和getter方法操作属性简单,但是这种方式是属于扩大类属性的访问权限后直接操作属性。不建议使用

通过反射操作数组

package org.lxh.demo15.invokedemo ;
import java.lang.reflect.Array ;
public class ClassArrayDemo{
	public static void main(String args[]) throws Exception{
		int temp[] = {1,2,3} ;// 声明一整型数组
		Class<?> c = temp.getClass().getComponentType() ;	// 取得数组的Class对象
		System.out.println("类型:" + c.getName()) ;	// 取得数组类型名称
		System.out.println("长度:" + Array.getLength(temp)) ;
		System.out.println("第一个内容:" + Array.get(temp,0)) ;
		Array.set(temp,0,6) ;
		System.out.println("第一个内容:" + Array.get(temp,0)) ;
	}
};
运行结果:

类型:int
长度:3
第一个内容:1
第一个内容:6
通过Array类根据已有数组类型开辟新的数组对象

package com.itheima.zqt ;
import java.lang.reflect.Array ;
public class ChangeArrayDemo{
	public static void main(String args[]) throws Exception{
		int temp[] = {1,2,3} ;// 声明一整型数组
		int newTemp[] = (int []) arrayInc(temp,5) ;	// 重新开辟空间5
		print(newTemp) ;
		System.out.println("\n-------------------------") ;
		String t[] = {"zqt","itheima","itcast"} ;
		String nt[] = (String [])arrayInc(t,8) ;
		print(nt) ;
	}
	public static Object arrayInc(Object obj,int len){
		Class<?> c = obj.getClass() ;
		Class<?> arr = c.getComponentType() ;	// 得到数组的
		Object newO = Array.newInstance(arr,len) ;	// 开辟新的大小
		int co = Array.getLength(obj) ;
		System.arraycopy(obj,0,newO,0,co) ;	// 拷贝内容
		return newO ;
	}
	public static void print(Object obj){	// 数组输出
		Class<?> c = obj.getClass() ;
		if(!c.isArray()){	// 判断是否是数组
			return;
		}
		Class<?> arr = c.getComponentType() ;
		System.out.println(arr.getName()+"数组的长度是:" + Array.getLength(obj)) ;	 // 输出数组信息
		for(int i=0;i<Array.getLength(obj);i++){
			System.out.print(Array.get(obj,i) + "、") ;	// 通过Array输出
		}
	}
};
运行结果:

int数组的长度是:5
1、2、3、0、0、
-------------------------
java.lang.String数组的长度是:8
zqt、itheima、itcast、null、null、null、null、null、

动态代理

前面博文中设计模式代理设计属于静态代理,因为每个代理类只能为一个接口服务,必然会产生过多的代理,最好能有一个代理类完成全部的代理功能。

首先定义个InvocationHandler接口的子类完成具体的功能

package com.itheima.zqt;
import java.lang.reflect.InvocationHandler ;
import java.lang.reflect.Proxy ;
import java.lang.reflect.Method ;
interface Subject{
	public String say(String name,int age) ;	// 定义抽象方法say
}
class RealSubject implements Subject{	// 实现接口
	public String say(String name,int age){
		return "姓名:" + name + ",年龄:" + age ;
	}
};
class MyInvocationHandler implements InvocationHandler{
	private Object obj ;
	public Object bind(Object obj){
		this.obj = obj ;	// 真实主题类
		return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this) ;
	}
	public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
		Object temp = method.invoke(this.obj,args) ;	// 调用方法
		return temp ;
	}
};
public class DynaProxyDemo{
	public static void main(String args[]){
		Subject sub = (Subject)new MyInvocationHandler().bind(new RealSubject()) ;
		String info = sub.say("zqt",25) ;
		System.out.println(info) ;
	}
};
类的生命周期

JVM通过装载,链接,初始化三个步骤

装载:通过类加载器把.class二进制文件装入JVM方法区,并且在堆创建java.lang.Class对象,同一个类只会被JVM加载一次,链接是把二进制数据组装成可运行的状态

链接:分为校验,准备,解析。校验此二进制文件是否适合当前jvm(版本),准备就是为静态成员分配内存空间和设置默认值,解析为转换常量池的代码为直接引用的过程。完成后,类就可以初始化,初始化后类的对象就可以正常使用,对象不再使用之后,被垃圾回收,释放空间,当没有任何引用只想Class对象时将会被卸载。

反射在工厂设计模式上的应用

工厂类每增加一个子类都需要修改工厂类,如果使用反射,工厂类可以不用做任何修改

package com.itheima.zqt ;
interface Fruit{
	public void eat() ;	// 吃水果
}
class Apple implements Fruit{
	public void eat(){			// 覆写eat()方法
		System.out.println("** 吃苹果");
	}
};
class Orange implements Fruit{
	public void eat(){
		System.out.println("** 吃橘子") ;
	}
};
class Factory{
	public static Fruit getInstance(String className){
		Fruit fruit = null ;
		try{
			fruit = (Fruit)Class.forName(className).newInstance() ;
		}catch(Exception e){
			e.printStackTrace() ;
		}
		return fruit ;
	}
};
public class FactoryDemo01{
	public static void main(String args[]){
		Fruit f = Factory.getInstance("com.itheima.zqt.Apple") ;
		if(f!=null){
			f.eat() ;
		}
	}
};
结合属性文件的工厂模式

以上操作虽然可行,但是操作时需要传入完整的包.类名称,可以使用属性文件的方式

fruit.properties

apple = com.itheima.zqt.Apple
orange = com.itheima.zqt.Orange

package com.itheima.zqt ;
import java.util.Properties ;
import java.io.File ;
import java.io.FileOutputStream ;
import java.io.FileInputStream ;
interface Fruit{
	public void eat() ;	// 吃水果
}
class Apple implements Fruit{
	public void eat(){			// 覆写eat()方法
		System.out.println("** 吃苹果");
	}
};
class Orange implements Fruit{
	public void eat(){
		System.out.println("** 吃橘子") ;
	}
};
class Init{
	public static Properties getPro(){
		Properties pro = new Properties() ;
		File f = new File("D:\\work\\javasebase\\fruit.properties") ;	// 找到属性文件
		try{
			if(f.exists()){	// 文件存在
				pro.load(new FileInputStream(f)) ;	// 读取属性
			}else{
				pro.setProperty("apple","com.itheima.zqt.Apple") ;
				pro.setProperty("orange","com.itheima.zqt.Orange") ;
				pro.store(new FileOutputStream(f),"FRUIT CLASS") ;
			}
		}catch(Exception e){}
		return pro ;
	}
};
class Factory{
	public static Fruit getInstance(String className){
		Fruit fruit = null ;
		try{
			fruit = (Fruit)Class.forName(className).newInstance() ;
		}catch(Exception e){
			e.printStackTrace() ;
		}
		return fruit ;
	}
};
public class FactoryDemo02{
	public static void main(String args[]){
		Properties pro = Init.getPro() ;
		Fruit f = Factory.getInstance(pro.getProperty("apple")) ;
		if(f!=null){
			f.eat() ;
		}
	}
};



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
黑马程序员的tb_brand是指在JavaWeb基础教程中创建的一个表。这个表是用来存储品牌信息的,具体的表结构和数据类型需要和JavaBean类中的成员变量保持一致。\[1\]在这个教程中,使用了Maven来构建项目,并且使用了MyBatis作为持久层框架,通过配置pom.xml文件来引入相关依赖。\[2\] Maven是一个用于管理和构建Java项目的工具,它提供了一套标准化的项目结构、构建流程和依赖管理机制。\[3\] #### 引用[.reference_title] - *1* [【JAVAWEB开发】黑马程序员java web案例资料(含Element的删除与修改)](https://blog.csdn.net/aasd23/article/details/126940147)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [黑马程序员-MyBatis 框架-最全入门笔记、阿伟看了都得说真大、真细、真全!!!](https://blog.csdn.net/qq_57383364/article/details/128103058)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [JavaWeb——黑马程序员课程笔记](https://blog.csdn.net/King_ZACC/article/details/128573804)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值