Java类文件编译后,会在类中添加一个静态属性,这个属性就是Class类的实例,用于描述类型信息。描述类信息的架构图如:
Class对象提供了一组方法,让我们可以方便获取类的属性,方法,构造方法等信息,并且用Field,Method,Constructor类来描述,可以用这些类来分析类型信息和运行类型信息来进行一些动态操作,例如反射,动态代理,依赖注入/控制反转等
Class类
Classl类的对象用来表示运行时的类或接口信息,可以通过Class对象获取类名,父类信息,还可以通过Class类获取该类的属性,方法,构造方法等
1. 通过.class属性
2. 通过getClass()方法
3. 通过forName()方法
package xls;
public class ClassTest {
public void print(String str){
System.out.println("Hello "+str);
}
}
package xls
public class ClassTestMain {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
//通过.class属性
Class<ClassTest> clazz1 = ClassTest.class
System.out.println("通过.class属性: "+clazz1.getCanonicalName())
//通过getClass()方法
ClassTest classTest = new ClassTest()
Class<? extends ClassTest> clazz2 = classTest.getClass()
System.out.println("通过getClass()方法: "+clazz2.getCanonicalName())
//通过forName(className)方法 className为完整名字
Class<?> clazz3 = Class.forName("xls.ClassTest")
System.out.println("通过forName()方法: "+clazz3.getCanonicalName())
//用三种方法获取的Class对象实例化ClassTest
ClassTest classTest1 = clazz1.newInstance()
classTest1.print("classTest1")
ClassTest classTest2 = clazz2.newInstance()
classTest2.print("classTest2")
ClassTest classTest3 = (ClassTest) clazz3.newInstance()
classTest3.print("classTest3")
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
运行结果:
获取Constructor对象
有四种方式获取构造方法的Constructor对象
1. getConstructor(Class,parameterTypes…)用于获取指定参数类型的Constructor对象
但是不能获取私有的构造方法的对象
2. getDeclaredConstructor(Class,paramerterTypes..) 用于获取指定参数类型的Constructor对象
但是能获取公有和私有的构造方法的Constructor对象
3. getConstructors()用于获取所有公有构造方法描述对象,若没有共有构造函数时返回长度为0的数组
4. getDeclaredConstructors()用于获取所有公有和被保护的构造方法描述对象
package xls;
import java.lang.reflect.Constructor;
public class ConstructorTest {
/** * 构造函数发生重载时,下方的无参构造方法被注释掉的话,则变成没有无参构造方法, * 当使用Constructor constructor1 = clazz1.getConstructor();就会报错 * 因为这种情况并没有无参构造方法 * 但是当没有写构造方法时,则会有一个默认的无参构造方法使用 * Constructor constructor1 = clazz1.getConstructor();则没有问题 */
public ConstructorTest(){}
public ConstructorTest(String name){}
public ConstructorTest(String name,int age){}
protected ConstructorTest(int age){}
private ConstructorTest(double salary){}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
package xls
import java.lang.reflect.Constructor
public class ConstructorTestMain {
public static void main(String[] args) throws NoSuchMethodException, SecurityException {
Class clazz1 = ConstructorTest.class
//获取无参构造方法,要注意有没有无参构造方法
Constructor constructor1 = clazz1.getConstructor()
System.out.println(constructor1.toString())
//获取指定参数类型的Constructor对象
Constructor constructor2= clazz1.getConstructor(String.class)
System.out.println(constructor2.toString())
Constructor constructor3= clazz1.getConstructor(String.class,int.class)
System.out.println(constructor3.toString())
//下方的代码会报错,因为getConstructor()不能获取私有属性的
//Constructor constructor4= clazz1.getConstructor(int.class)
//System.out.println(constructor4.toString())
//Constructor constructor5= clazz1.getConstructor(double.class)
//System.out.println(constructor5.toString())
System.out.println("<===============2===============>")
//获取指定类型的被保护的构造方法的对象
Constructor constructor6 = clazz1.getDeclaredConstructor(int.class)
System.out.println(constructor6.toString())
Constructor constructor7 = clazz1.getDeclaredConstructor(double.class)
System.out.println(constructor7.toString())
System.out.println("<===============3===============>")
Constructor[] constructor8 = clazz1.getConstructors()
for(Constructor c :constructor8){
System.out.println(c.toString())
}
System.out.println("<===============4===============>")
Constructor[] constructor9 = clazz1.getDeclaredConstructors()
for(Constructor c :constructor9){
System.out.println(c.toString())
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
运行结果:
获取Method对象
Method的对象用于描述类的单个方法(不包构造方法),可以通过它来获取方法的访问权限,参数类型,返回值的类型等信息,还可以根据Method的对象来动态执行。
package xls;
public class MethodTest {
public void hello(){}
private void student(String name){}
public void teacher(String name){
System.out.println("Hello "+name);
}
public final void school(){}
}
package xls;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class MethodMain {
public static void main(String[] args) throws ClassNotFoundException,
NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
/** * 获取Method的四种方法与获取Constructor的四种方法相似,用法相似 * 1.getMthod(String name,Class...parameterTypes)用于获取指定名称和参数类型的公有方法的描述对象, * ,不能用来获取私有和被保护的对象 * 2.getDeclaredMethod(String name,Class...parameterTypes)作用和第一个相同, * 但可以获取来获取非公有的方法描述对象 */
Class<?> clazz = Class.forName("xls.MethodTest");
Method method1 = clazz.getMethod("hello", null);
Method method3 = clazz.getMethod("teacher", String.class);
Method method4 = clazz.getMethod("school", null);
System.out.println("<===================1===================>");
System.out.println(method1.toString());
System.out.println(method3.toString());
System.out.println(method4.toString());
Method method5 = clazz.getDeclaredMethod("hello", null);
Method method6 = clazz.getDeclaredMethod("teacher", String.class);
Method method7 = clazz.getDeclaredMethod("student", String.class);
Method method8 = clazz.getDeclaredMethod("school", null);
System.out.println("<===================2===================>");
System.out.println(method5.toString());
System.out.println(method6.toString());
System.out.println(method7.toString());
System.out.println(method8.toString());
/** * 3.getMethods()获取公有的方法描述对象列表,还包括继承父类或接口的方法描述对象, * 4.getDeclaredMethods()获取公有和非公有的所有方法描述对象列表,但只能获取 * 自己定义的方法描述对象 */
Method[] method9 = clazz.getMethods();
System.out.println("<===================3===================>");
for(Method m : method9){
System.out.println(m.toString());
}
Method[] method10 = clazz.getDeclaredMethods();
System.out.println("<===================4===================>");
for(Method m : method10){
System.out.println(m.toString());
}
/** * 获取Method的对象,可以获取它的方法名,返回类型,执行方法 */
System.out.println("<======================================>");
System.out.println(method3.getName());
System.out.println(method3.getReturnType());
MethodTest metodTest = (MethodTest) clazz.newInstance();
method3.invoke(metodTest, "wto");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
运行结果:
获取Field对象
package xls;
public class FieldTest {
public String name = "luxi";
public int num =1202020;
private int age;
private double salary;
public String sit;
}
package xls;
import java.lang.reflect.Field;
public class FieldTestMain {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException,
SecurityException, InstantiationException, IllegalAccessException {
/** * Class提供4种方式来获取Field对象 * 这四种方式前面提到获取Constructor和Method的4种方式类似 * 1.getField(String name) 获取指定的公有的属性,name为属性名 * 2.getDeclaredField(String name) 获取指定的属性包括非公有属性,但必须定义在类内部 */
System.out.println("========================1===================");
Class clazz = Class.forName("xls.FieldTest");
Field field1 = clazz.getField("name");
System.out.println(field1.getType());
FieldTest obj = (FieldTest) clazz.newInstance();
System.out.println(field1.get(obj));
field1.set(obj, "lcy");
System.out.println(field1.get(obj));
System.out.println("========================2===================");
Field field2 = clazz.getDeclaredField("age");
System.out.println(field2.getType());
FieldTest obj1 = (FieldTest) clazz.newInstance();
field2.setAccessible(true);
System.out.println(field2.get(obj));
field2.set(obj1, 3);
System.out.println(field2.get(obj1));
/** * 3.getField()获取所有公有属性的对象 * 4.getDeclaredFields()获取所有的属性对象,包括非公有属性 */
System.out.println("========================3===================");
Field[] field3 = clazz.getFields();
for(Field f : field3){
System.out.println(f.toString());
}
System.out.println("========================4===================");
Field[] field4 = clazz.getDeclaredFields();
for(Field f : field4){
System.out.println(f.toString());
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
运行结果
用反射机制编写通用的Excel导入导出
反射机制
反射机制是指在运行状态中,对任意的一个类,都能知道这个类的所有属性和方法;对任意的一个对象,都能调用它的任意一个方法,修改它的任意属性,这种动态获取的信息以及动态调用对象成员的功能就是java的反射机制。
编写通用的Excel导入导出
假设当一个图书关系管理系统项目中,需要导出图书,成员等信息时,我们不可能为每一个需要导出的对象都写一个导出导入Excel的代码,这会有很多重复性的代码,也没有必要,因此可以写一个通用的Excel导入导出。我的思路是将要导出的数据封装在每一个对象当中,因而我们就可以对对象进行操作,利用反射的机制在代码运行时动态的对这些对象进行操作。
package xls;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;
public class Xls {
/** * @param arrayList 把要导出的数据封装到一个个对象中,把对象存储到ArrayList中 * @param path 文件的路径 * @param list 第一行为数据的名称 */
public static void out(ArrayList<?> arrayList,String path,ArrayList<String> list) throws
IllegalArgumentException, IllegalAccessException, IOException, WriteException{
WritableWorkbook book = Workbook.createWorkbook(new File(path));
WritableSheet sheet = book.createSheet("sheet1", 0);
for(int i=0;i<list.size();i++){
Label label = new Label(i,0,(String) list.get(i));
sheet.addCell(label);
}
for(int j = 1;j<=arrayList.size();j++){
Class<? extends Object> clazz = arrayList.get(j-1).getClass();
Field[] fields = clazz.getDeclaredFields();
int i=0;
for(Field ff : fields){
ff.setAccessible(true);
/** * ff.getType()获取属性类型 * ff.getName()获取属性名 * ff.get()获取属性值 * System.out.println(ff.getType()+" "+ff.getName()+" "+ff.get(list.get(j))); */
Label label = new Label(i++,j, String.valueOf(ff.get(arrayList.get(j-1))));
sheet.addCell(label);
}
}
book.write();
book.close();
}
/** * @param clazz Class的对象 * @param path 文件路径 * @return ArrayList */
public static ArrayList<?> in(Class<?> clazz,String path) throws BiffException, IOException, NoSuchMethodException,
SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException{
ArrayList<Object> list = new ArrayList<Object>();
Workbook book = Workbook.getWorkbook(new File(path));
Sheet sheet = book.getSheet(0);
Field[] fields = clazz.getDeclaredFields();
int row = sheet.getRows();
for(int j=1;j<row;j++){
int i = 0;
Object obj = clazz.newInstance();
for(Field ff : fields){
String methodName = "set"+ff.getName().substring(0, 1).toUpperCase()+ff.getName().substring(1);
String value;
Cell cell = sheet.getCell(i++,j);
value = cell.getContents();
Method method = obj.getClass().getMethod(methodName,ff.getType());
if(ff.getType().toString().equals("class java.lang.String")){
method.invoke(obj, value);
}else if(ff.getType().toString().equals("int")||ff.getType().toString().equals("Integer")){
method.invoke(obj, Integer.valueOf(value));
}
}
list.add(obj);
}
book.close();
return list;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
package xls;
public class Student {
private String name;
private int num;
private String className;
private String age;
private String major;
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getMajor() {
return major;
}
public void setMajor(String major) {
this.major = major;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String toString() {
return "姓名:" + name + " 学号:" + num + " 班级:"
+ className + " 年龄:" + age + " 专业:" + major;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
package xls;
public class Teacher {
private String name;
private String sex;
private String phone;
private int salary;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "姓名:"+name+" "+sex+" 手机:"+phone+" 工资:"+salary;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
测试类
package xls
import java.io.IOException
import java.lang.reflect.InvocationTargetException
import java.util.ArrayList
import jxl.read.biff.BiffException
import jxl.write.WriteException
public class XlsTest {
@SuppressWarnings("unchecked")
public static void main(String[] args) throws IllegalArgumentException,
IllegalAccessException, WriteException, IOException, BiffException,
NoSuchMethodException, SecurityException, InvocationTargetException,
InstantiationException {
//把数据导入excel中
ArrayList<Teacher> arrayList = new ArrayList<Teacher>()
Teacher teacher = new Teacher()
teacher.setName("张海")
teacher.setSex("男")
teacher.setPhone("13058993353")
teacher.setSalary(7000)
arrayList.add(teacher)
Teacher teacher1 = new Teacher()
teacher1.setName("张萍")
teacher1.setSex("女")
teacher1.setPhone("15013983453")
teacher1.setSalary(7340)
arrayList.add(teacher1)
Teacher teacher2 = new Teacher()
teacher2.setName("李依芬")
teacher2.setSex("女")
teacher2.setPhone("13550934483")
teacher2.setSalary(8000)
arrayList.add(teacher2)
ArrayList<String> list = new ArrayList<String>()
list.add("姓名")
list.add("性别")
list.add("手机")
list.add("工资")
Xls.out(arrayList,"f:/teacher.xls",list)
//把f:/teacher2.xls的数据导进来
ArrayList<Teacher> arrayList2 = new ArrayList<Teacher>()
arrayList2 = ((ArrayList<Teacher>) Xls.in(Teacher.class,"f:/teacher2.xls"))
for(Teacher t : arrayList2){
System.out.println(t.toString())
}
System.out.println("===================================================================")
Student student = new Student()
student.setName("詹三")
student.setNum(2013363232)
student.setClassName("3班")
student.setAge("21")
student.setMajor("计算机")
ArrayList<Student> arrayList3 = new ArrayList<Student>()
arrayList3.add(student)
ArrayList<String> list1 = new ArrayList<String>()
list1.add("姓名")
list1.add("学号")
list1.add("班级")
list1.add("年龄")
list1.add("专业")
Xls.out(arrayList3,"f:/student.xls",list1)
//导入
arrayList3 = ((ArrayList<Student>) Xls.in(Student.class,"f:/student.xls"))
for(Student t : arrayList3){
System.out.println(t.toString())
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
导出到f:/teacher.xls的结果
把f:/teacher.xls表中的数据导入
把f:/student.xls表中的数据导入
导入的结果
深入理解动态代理和深入理解Java Proxy机制点击这里查看