JAVA进阶版:反射机制

1.Class的简单操作

(1)Class类型对象的三种方式

package javase.jingjie.反射机制;
/**
 * 获取Class类型对象的三种方式
 * */
import java.util.*;
public class ReflectTest01 {

	public static void main(String[] args) throws Exception{
		// 第一种方式:
		Class c1=Class.forName("Employee");//c1引用保存内存地址指向堆中的对象,该对象代表的是Employee整个类。
		
		//第二种方式:
		//java中每一个 类型都有class属性
		Class c2=Employee.class;
		
		//第三种方式:
		//java语言中任何一个java对象都有getClass方法
		Employee e=new Employee();
		Class c3=e.getClass();//c3是运行时类(e的运行时类是Employee)
		
		//因为Employee这个类在JVM中只有一个,所以c1,c2,c3的内存地址是相同的,指向堆中的唯一一个对象。
		System.out.println(c1==c2);//true
		System.out.println(c2==c3);//true
		
		//c4,c5,c6都代表Date这个类(三种方式表示Data)
		Class c4=Date.class;
		
		Class c5=Class.forName("java.util.Date");//必须写类全名,类全名带有包名。
		
		Date d=new Date();
		Class c6=d.getClass();
		
		//c7代表int类型
		Class c7=int.class;
	}
}

Employee:

package javase.jingjie.反射机制;

public class Employee {
	// Field
	private String name;
	
	//Constructor
	public Employee() {
		System.out.println("Employee的无参数构造方法执行");
	}
	
	public Employee(String name) {
		this.name=name;
	}
	//方法
	public void work() {
		System.out.println(name+"在工作!");
	}
}

(2) 静态语句块

package javase.jingjie.反射机制;
public class ReflectTest02 {
	public static void main(String[] args) throws Exception{
		//将A.class文件装载到JVM中的过程,会执行静态语句块
		Class.forName("A");
		
		//不会执行静态语句块
		Class c=A.class;
	}
}
class A{
	static {
		System.out.println("A.....");
	}
}

(3) 获取Class类型的对象之后,可以创建该“类”的对象

package javase.jingjie.反射机制;
import java.util.*;
import java.text.*;
/**
 * 获取Class类型的对象之后,可以创建该“类”的对象
 * 
 * newInstance();是表示调用无参构造方法
 * 
 * 结果:Employee的无参数构造方法执行
javase.jingjie.反射机制.Employee@8efb846
2019-10-29,20:56:50:694
 * */
public class ReflectTest03 {
	public static void main(String[] args) throws Exception{		
		Class c=Employee.class;		
		//创建此Class对象所表示的类的一个新实例
		//newInstance()异常
		Object o=c.newInstance();//调用了Employee的无参构造方法
		System.out.println(o);//javase.jingjie.反射机制.Employee@8efb846
		
		//c1是Date类
		Class c1=Date.class;
		Object t=c1.newInstance();//调用Date类的无参构造方法,获取当前时间
		
		if(t instanceof Date) {//如果t是Date类,则执行以下语句
			Date d=(Date)t;//强制转换父类型Object的t
			System.out.println(new SimpleDateFormat("yyyy-MM-dd,HH:mm:ss:SSS").format(d));//2019-10-29,20:56:50:694
		}
	}
}

(4) java中的可变长参数

package javase.jingjie.反射机制;
import java.util.*;
/**
 * 关于java中的可变长参数
 * */
public class ReflectTest04 {
	public static void main(String[] args) throws Exception{
		m1();
		m1(1);
		m1(1,2);
		m1(4,5,6);
		
		m2("美术","音乐","运动","打游戏","上网");
		
		String[] s= {"美术","音乐","运动","打游戏","上网"};
		m2(s);
		//异常上抛
		m3(Date.class,Employee.class);
	}
		// m1方法有一个int类型可变长参数,三个冒号
		public static void m1(int...a) {//m1方法在调用的时候,传递的实参可以是0~N个
			
			System.out.println("Test");
		}
		//如果可以精确匹配的方法,则调用该方法,不会再执行可变长参数的那个方法。
		public static void m1(int i) {
			System.out.println(i);
		}
	
		//可变长参数可以等同看作数组
		public static void m2(String...args) {
			
			for(int i=0;i<args.length;i++) {
				System.out.println(args[i]);
			}
		}	
		public static void m3(Class...args) throws Exception{
			for(int i=0;i<args.length;i++) {
				Class c=args[i];
				//异常上抛
				System.out.println(c.newInstance());
			}
		}	
		//可变长参数只能出现一次,并且只能出现在所有参数的最后一位。
		//public static void m4(String...a,int i) {}
		
		public static void m4(int i,String...a) {}
}

2. IO流+Properties

(5) IO流+Properties

package javase.jingjie.反射机制;
/**
 * IO+Properties
 * 
 * r.txt是配置文件(放key和value),说明书,可更改value值,使得java文件得到value值
 * Key和value之间可以使用"空格","等号","冒号",按最前面的作为分隔符。
 * */
import java.io.*;
import java.util.*;
public class ReflectTest05 {

	public static void main(String[] args) throws Exception{
		// 1.创建属性对象
		//和Map一样,只不过key和value只能存储字符串类型
		//key不能重复,如果key重复则value覆盖
		Properties p=new Properties();

		//2.创建输入流
		/*内容:r.txt内容   simth 019 scort 23787894 simth  */
		FileInputStream fis=new FileInputStream("src/javase/jingjie/反射机制/r.txt");
		
		//3.将fis流中的所有数据加载到属性对象中
		p.load(fis);
		
		fis.close();
		
		//通过key获取value
		String v1=p.getProperty("driver");
		String v2=p.getProperty("url");
		String v3=p.getProperty("username");
		String v4=p.getProperty("password");
		String v5=p.getProperty("driver");
		
		System.out.println(v1);
		System.out.println(v2);
		System.out.println(v3);
		System.out.println(v4);
		System.out.println(v5);		
		/**结果:
		 * simth
            019
           scort
         23787894
          simth
*/
	}
}

r.txt

driver=Tom
url=019
username=scort
password=23787894
driver=simth

(6) IO+Properties+反射机制 联合作用创建对象

package javase.jingjie.反射机制;
import java.io.*;
import java.text.*;
import java.util.*;
/**
 * IO+Properties+反射机制 联合作用创建对象
 * */
public class ReflectTest06 {

	public static void main(String[] args) throws Exception{
		// 1.创建属性对象
		Properties p= new Properties();
		
		//创建流,相对路径
		FileReader fr= new FileReader("src/javase/jingjie/反射机制/classInfo.properties");
		
		//3.加载
		p.load(fr);

		//4.关闭流
		fr.close();
		
		//通过key获取value,通过key=className,value=java.util.Date
		//这里可以直接更改value,value就是类,获取不同的类,得到不同的结果
		String className=p.getProperty("className");
		System.out.println(className);//java.util.Date
		
		//通过反射机制创建对象,这里的className指的是java.util.Date
		Class c=Class.forName(className);
		
		//创建对象
		Object o=c.newInstance();//调用Date的无参构造方法
		SimpleDateFormat t=new SimpleDateFormat("yyyy年MM月dd日,HH:mm:ss:SSS");
		System.out.println(t.format(o));//2019年11月03日,15:09:12:996
	}
}

classInfo.properties

className=java.util.Date

3. 获取属性(Field)

(7) 获取属性(Field)的操作

package javase.jingjie.反射机制;
import java.lang.reflect.*;
/**
 * 结果;1
age-------------
2
private-------------
java.lang.String
String----------
id
==============================
1
public-------------
int
int----------
age
==============================
4
protected-------------
java.lang.String
String----------
addr
==============================
0
-------------
boolean
boolean----------
sex
==============================

 * */
public class ReflectTest07 {

	public static void main(String[] args) throws Exception{
		// 获取整个类
		Class c=User.class;
		
		//获取所有的public修饰的属性 getFields()
		Field [] fs=c.getFields();
		System.out.println(fs.length);//1
		System.out.println(fs[0].getName()+"-------------");//age--------------
		
		//获取所有的属性getDeclaredFields()
		Field[] fs1=c.getDeclaredFields();

		for(Field field:fs1) {
			
			//修饰符输出,i的数字与修饰符对应
			int i=field.getModifiers();
			System.out.println(i);//2 
			//将int类型转换成字符串,Modifier是个类
			String strModifier=Modifier.toString(i);
			System.out.println(strModifier+"-------------");//private------------
			
			//获取数据类型getType()
			Class type=field.getType();
			System.out.println(type.getName());//java.lang.String
			//简单格式
			System.out.println(type.getSimpleName()+"----------");//String----------
			
			//获取属性名字 getName()
			System.out.println(field.getName());//id
			System.out.println("==============================");
		}
	}
}

User.java

package javase.jingjie.反射机制;
public class User {
	//Field
	private String id;
	public int age;
	protected String addr;
	boolean sex;
}

(8) 追加操作,修饰符+数据类型+属性名

package javase.jingjie.反射机制;
/**
 * 写出User类
 * 结果:public class User {
	private String id;
	public int age;
	protected String addr;
	 boolean sex;
}
 * */
import java.lang.reflect.*;
public class ReflectTest08 {
	public static void main(String[] args) throws Exception{
		// 获取整个类,可以将“User”类换成其他类,如java.util.Date;(写全类名)
		//Class c=java.util.Date.class;
		Class c=User.class;
		
		//完整写出User的文本
		StringBuffer sb= new StringBuffer();
		
		//获取所有属性
		Field[] fs=c.getDeclaredFields();
		//追加,修饰符+数据类型+属性名
		sb.append(Modifier.toString(c.getModifiers())+" class "+c.getSimpleName()+" {\n");//\n是空格
		for(Field field:fs) {
			sb.append("\t");
			sb.append(Modifier.toString(field.getModifiers())+" ");
			sb.append(field.getType().getSimpleName()+" ");
			sb.append(field.getName()+";\n");
		}
		sb.append("}");
		System.out.println(sb);
	}
}	

(9) 获取某个指定的属性

package javase.jingjie.反射机制;
/**
 * 获取某个指定的属性。
 * java.lang.reflect.Field
 * */
import java.lang.reflect.*;
public class ReflectTest09 {
	public static void main(String[] args) throws Exception{
		// 以前的方式:
		/*
		User u= new User();
		u.age=12;//set
		System.out.println(u.age);//12  get
		*/
		
		//获取类
		Class c=User.class;
		
		//获取id属性
		Field idf=c.getDeclaredField("id");
		
		//获取到某一个特定的属性可以用来?set,get
		Object o=c.newInstance();//该语句创建对象
		
		//打破私有封装(带private)
		idf.setAccessible(true);
		
		//给o对象的id属性赋值“110”
		idf.set(o, "110");//set
		
		//get
		System.out.println(idf.get(o));//110
	}
}

4. 获取方法(Method)

(10) 获取方法的操作

package javase.jingjie.反射机制;
import java.lang.reflect.*;
/**
 * java.lang.reflect.Method;
 * */
public class ReflectTest10 {
	public static void main(String[] args) {
		// 获取类,可以写任何一个类
		Class c=CustomerService.class;		
		//获取所有的方法
		Method[] ms=c.getDeclaredMethods();
		for(Method m:ms) {			
			//修饰符			System.out.println(Modifier.toString(m.getModifiers()));		
			//方法的返回值类型getReturnType(),与属性的方法getType()不同
			Class returnType=m.getReturnType();
			System.out.println(returnType.getSimpleName());			
			//方法名
			System.out.println(m.getName());			
			//方法的形式参数列表
			Class[] parameterTypes=m.getParameterTypes();
			for(Class parameterType:parameterTypes) {
				System.out.println(parameterType.getSimpleName());
			}
		}
		
        //反编译,和前面类似
		StringBuffer sb=new StringBuffer();
		//修饰符 class 类名
		sb.append(Modifier.toString(c.getModifiers())+" class "+c.getSimpleName()+"{\n");
		
		//方法
		for(Method m:ms) {
			sb.append("\t");
			sb.append(Modifier.toString(m.getModifiers())+" ");
			sb.append(m.getReturnType().getSimpleName()+" ");
			sb.append(m.getName()+" ");
			
			//形参
			Class[] parameterTypes=m.getParameterTypes();
			for(int i=0;i<parameterTypes.length;i++) {
				Class parameterType=parameterTypes[i];
				if(i==parameterTypes.length-1) {
					sb.append(parameterType.getSimpleName());
				}else {
					sb.append(parameterType.getSimpleName()+" ");
				}
			}
			sb.append("() {}\n");
		}
		sb.append("}");
		System.out.println(sb);
	}
}

CustomerService

package javase.jingjie.反射机制;
public class CustomerService {
	//登录
	public boolean login(String name,String pwd) {	
		if("admin".equals(name)&&"123".equals(pwd)) {
			return true;
		}
		return false;
	}
	//退出
	public void logout() {
		System.out.println("系统已安全退出!");
	}
}

(11) 获取某个特定的方法,通过反射机制执行

package javase.jingjie.反射机制;
/**
 * 获取某个特定的方法,通过反射机制执行
 * */
import java.lang.reflect.*;
public class ReflectTest11 {
	public static void main(String[] args) throws Exception{
		// 获取CustomerService类,可以更改类
		Class c=CustomerService.class;
		
		//获取某个特定的方法。通过:方法名+形参列表
		Method m=c.getDeclaredMethod("login", String.class,String.class);
		
		//通过反射机制执行login方法
		Object o=c.newInstance();//创建对象
		
		//调用o对象的m方法,传递"admin","123"参数,方法执行的结果是retValue
		Object retValue=m.invoke(o, "admin","123");
		System.out.println(retValue);//true
	}
}

5. 获取构造方法

(12) 获取构造方法

package javase.jingjie.反射机制;
import java.lang.reflect.*;
/**
 * 获取构造方法
 * */
public class ReflectTest12 {

	public static void main(String[] args) {
		// 获取类
		Class c=java.lang.String.class;
		
		//获取所有的构造
		Constructor [] cs=c.getDeclaredConstructors();
		
		for(Constructor con:cs) {
			//获取修饰符
			System.out.println(Modifier.toString(con.getModifiers()));
			
			//获取构造方法名
			System.out.println(c.getName());
			
			//构造方法的形式参数列表
			Class [] parameterTypes=con.getParameterTypes();
			for(Class parameterType:parameterTypes) {
				System.out.println(parameterType.getSimpleName());
			}
		}
		//反编译,参考前面
	}
}

(13) 获取特定的构造方法

package javase.jingjie.反射机制;
/**
 * 获取特定的构造方法
 * */
import java.lang.reflect.*;
public class ReflectTest13 {

	public static void main(String[] args)throws Exception {
		// 获取类
		Class c=Customer02.class;
		
		//获取特定的构造方法
		Constructor con=c.getDeclaredConstructor(String.class,int.class);
		
		//创建对象,这里的newInstance()是 con,不是c里面调用的无参构造
		Object o=con.newInstance("李四",23);
		System.out.println(o);
	}

}
class Customer02{
	String name;
	int age;
	 public Customer02(String name,int age) {
		 this.name=name;
		 this.age=age;
	 }
		 public String toString() {
			 return "Customer["+name+","+age+"]";
		 }
}

(14) 关于类获取父类和父接口

package javase.jingjie.反射机制;
/**
 * 关于类获取父类和父接口
 * */
public class ReflectTest14 {
	public static void main(String[] args) {
		// 通过反射机制获取String类的父类和父接口
		Class c=java.lang.String.class;
		
		//获取父类
		Class superClass=c.getSuperclass();
		System.out.println(superClass.getName());
		
		System.out.println("------------------");
		
		//获取父接口,一个类可以实现多个接口
		Class[] ins=c.getInterfaces();
		for(Class in:ins) {
			System.out.println(in.getName());
		}
	}
}
发布了71 篇原创文章 · 获赞 10 · 访问量 3410

猜你喜欢

转载自blog.csdn.net/JH39456194/article/details/104083402