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