一.反射
反射的使用方法
1.学会获得镜像对象,(三种方式)
a.我们知道类的全限类名 com.briup.dat06.Student
Class.forName(全限类名);
b.只知道类的类名 Student
Student.class;
c.只知道有个对象的名字,stu1
stu1.getClass();
2.创建一个测试的例子 ReflectTest.java
java.lang.Class的实例,叫做镜像对象
java.lang.reflect
Field
Method
Construct
Modified
…
3.功能具体测试参见代码
反射的相关测试
package day16;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.util.*;
/**
* 测试反射的功能
*
* @author Acer
*
*/
@Resource
@SuppressWarnings("unchecked")
public class ReflectTest {
public int i;
private double d;
static String s;
protected Map<Integer, String> map;
public List<String> list = new ArrayList<String>();
public ReflectTest() {
System.out.println("调用空参构造器");
this.i = 10;
this.d = 20.0;
this.s = "hello";
}
public ReflectTest(String s) {
System.out.println("调用单参构造器");
this.s = s;
}
public void show() {
System.out.println("这是一个空参的方法");
}
private String show(String s) {
System.out.println(this.s);
System.out.println("这是一个String参数的方法");
return s;
}
//给D添加一个get方法
public double getD() {
return d;
}
public void setD(double d) {
this.d = d;
}
class inner1 {
}
private class Inner2 {
}
public static void main(String[] args) throws Exception {
// 使用三种方式来获得ReflectTest的镜像对象(Class的实例)
// 1.day16.ReflectTest
Class<?> clazz1 = Class.forName("day16.ReflectTest");
// //2.ReflectTest
// Class<ReflectTest> clazz2 = ReflectTest.class;
// //3.只知道对象的名字
// ReflectTest rt = new ReflectTest();
// Class<?> clazz3 = rt.getClass();
System.out.println(clazz1);
// System.out.println(clazz2);
// System.out.println(clazz3);
System.out.println("==========属性===========");
// Field[] fs = clazz1.getFields();//获取的所有public属性
Field[] fs = clazz1.getDeclaredFields();
System.out.println(fs.length);
for (Field field : fs) {
System.out.println(field);
System.out.println("----------------");
System.out.println(field.getName());
System.out.println(field.getType());
System.out.println(field.getModifiers());
}
System.out.println("==========方法==========");
// Method[] ms = clazz1.getMethods();//获取所有的public方法,包括本类和父类的
Method[] ms = clazz1.getDeclaredMethods();// 获得本类的所有方法
for (Method method : ms) {
System.out.println(method);
}
System.out.println("=========构造器========");
Constructor<?>[] cs = clazz1.getConstructors();
for (Constructor<?> constructor : cs) {
System.out.println(constructor);
}
System.out.println("=========内部类========");
Class<?>[] inners = clazz1.getDeclaredClasses();
for (Class<?> class1 : inners) {
System.out.println(class1);
}
// 小小的需求
// 获取第一个内部类的外部类名称
Class<?> innerOne = inners[0];
String className = innerOne.getName();
// 注意一下内部类的全限类名方式
// class day16.ReflectTest$inner1
Class<?> inneroo = Class.forName(className);
// 通过内部类来获得外部类的Class实例
Class<?> outClass = innerOne.getDeclaringClass();
System.out.println(outClass.getName());
System.out.println("==========注解=========");
Annotation[] as = clazz1.getDeclaredAnnotations();
for (Annotation annotation : as) {
System.out.println(annotation);
}
System.out.println("===================");
// 反射主要是在程序的运行阶段动态的修改信息
// 使用反射来创建对象
// 1.使用默认的构造器
// ReflectTest rt = new ReflectTest(); //原始的创建方式
// 用反射产生的新实例是Object的实例
Object obj = clazz1.newInstance();
// 需要在验证时候进行类型转换
ReflectTest rt1 = null;
if (obj instanceof ReflectTest) {
rt1 = (ReflectTest) obj;
}
rt1.show();
System.out.println(rt1.show("String"));
System.out.println("============构造器创建对象=============");
// 2.使用指定的构造器
//首先要获得所制定的构造器
// ReflectTest rt2 = new ReflectTest("Hello, World!");
Constructor<?> c1 = clazz1.getDeclaredConstructor(String.class);
//使用制定的构造器进行对象的创建
ReflectTest rt2 = (ReflectTest) c1.newInstance("Hello, World!");
System.out.println("=============反射调用方法=================");
//调用方法之前先获得方法
Method m1 = clazz1.getDeclaredMethod("show", null);
Method m2 = clazz1.getDeclaredMethod("show", String.class);
//使用对象去调用 invoke(调用方法的方法)
m1.invoke(rt2, null);//rt2.show();
m2.invoke(rt2, "tom");//rt2.show("tom");
//假设运行时期给泛型添加不同的数据类型
System.out.println("============属性值的访问=========");
//先获得想要修改的属性
System.out.println(rt2.s);
Field f1 = clazz1.getDeclaredField("s");
f1.set(rt2, "Hello, Tom!");
System.out.println(rt2.s);
// 以上的部分要求掌握
// 以下的部分为拓展
System.out.println("==========访问泛型=========");
//先要获得泛型类型的属性对象
Field f2 = clazz1.getDeclaredField("map");
Type gf = f2.getGenericType();
if(gf instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType)gf;
System.out.println("原始类型"+pt.getRawType().getTypeName());
//获取泛型的类型参数
Type[] ata = pt.getActualTypeArguments();
for(int i=0;i<ata.length;i++) {
System.out.println("第"+(i+1)+"个参数类型为"+ata[i].getTypeName());
}
}
System.out.println("===========数组========");
//使用反射来动态创建数组和访问数组对象 Array
Object o = Array.newInstance(String.class, 10);
//数组中添加元素
Array.set(o, 0, "hello");
Array.set(o, 1, "world");
Array.set(o, 2, "tom");
Array.set(o, 3, "jerry");
//获得元素
System.out.println(Array.get(o, 2));
//获得数组长度
System.out.println(Array.getLength(o));
System.out.println("=============其他功能===========");
System.out.println(clazz1.getPackage());
System.out.println(clazz1.getSuperclass());
System.out.println(Arrays.toString(clazz1.getInterfaces()));
}
}
得到的输出结果分别为
class day16.ReflectTest
==========属性===========
5
public int day16.ReflectTest.i
----------------
i
int
1
private double day16.ReflectTest.d
----------------
d
double
2
static java.lang.String day16.ReflectTest.s
----------------
s
class java.lang.String
8
protected java.util.Map day16.ReflectTest.map
----------------
map
interface java.util.Map
4
public java.util.List day16.ReflectTest.list
----------------
list
interface java.util.List
1
==========方法==========
public static void day16.ReflectTest.main(java.lang.String[]) throws java.lang.Exception
public void day16.ReflectTest.setD(double)
public double day16.ReflectTest.getD()
private java.lang.String day16.ReflectTest.show(java.lang.String)
public void day16.ReflectTest.show()
=========构造器========
public day16.ReflectTest()
public day16.ReflectTest(java.lang.String)
=========内部类========
class day16.ReflectTest$Inner2
class day16.ReflectTest$inner1
day16.ReflectTest
==========注解=========
@javax.annotation.Resource(shareable=true, lookup=, name=, description=, authenticationType=CONTAINER, type=class java.lang.Object, mappedName=)
===================
调用空参构造器
这是一个空参的方法
hello
这是一个String参数的方法
String
============构造器创建对象=============
调用单参构造器
=============反射调用方法=================
这是一个空参的方法
Hello, World!
这是一个String参数的方法
============属性值的访问=========
Hello, World!
Hello, Tom!
==========访问泛型=========
原始类型java.util.Map
第1个参数类型为java.lang.Integer
第2个参数类型为java.lang.String
===========数组========
tom
10
=============其他功能===========
package day16
class java.lang.Object
[]
二.异常
异常的分类
编译阶段的异常,受检查异常CheckedException
运行阶段的异常,运行时异常RuntimeException
三.心得
今天的内容依然是比较好接受的,主要就是在学习一些反射使用的方法,今天早上对昨天的学生管理系统进行了相关功能的完善,把输入错误数据的情况都补充了一下,同时对年龄和性别的范围做了一些相关的限制,新的源码已经在上一篇博客中更新.明天就是令人激动的周五了,这周总算能舒舒服服的休息休息了.