■ 问题1:
1、对象有编译类型和运行类型
Object obj = new java.util.Date();
□ 需求:通过obj对象,调用java.util.Date类中的toLocaleString方法。
直接 obj.toLocaleString(); 此时编译报错,编译时会检查编译类型中是否存在toLocaleString方法。
解决方案:因为咱知道obj的真实类型是java.util.Date类,可以进行类型的强制转化
java.util.Date d = (java.util.Date)obj; d.toLocaleString();//此时编译成功,成功调用方法
但是,若是不知道obj的真实类型,就不能强转(底层有一个方法-返回类型是Object类型的java.util.Date对象)
底层代码:
public static Object getObj(){
return new java.util.Date();
}
//使用反射:
Object obj = new java.util.Date();
Method m = obj.getClass().getMethod("toLocaleString");
m.invoke();
■ 问题2:
□ 当类一旦被加载进内存,就会变成Class对象【字节码对象】
类-用来描述对象,Class-用来描述类这种对象的类
(1)Class类:用来描述类或接口的类型,描述类的类
。
(2)Class类的实例:在jvm中的一份份字节码
,Class 实例表示在jvm中的类或者接口,枚举是一种特殊的类,注解是一种特殊的接口。
□ 当程序第一次使用某个类(例如:java.util.Date类)的时候,就会把该类的字节码(编译生成的字节码),加载进行虚拟机,并创建一个Class对象【字节码对象】,此时的Class对象可以表示java.util.Date类的字节码,
但是Class 类可以表示N个类的字节码对象,问题:要怎么区分Class类此时表示的是哪一个类的字节码呢?
解决方案:Class类的设计者使用了泛型 Class
//需求:获取java.util.Date类的字节码对象
//方式1:通过class属性
Class<java.util.Date> clazz1 = java.util.Date.class;
//方式2:通过对象的getClass方法,getClass方法是Object类的方法
java.util.Date date = new java.util.Date();
Class<?> clazz2 = date.getClass();
//方式3:通过Class类中的静态方法forName(String className)
Class clazz3 = Class.forName("java.util.Date");
■ 问题:上述的三种方式获取Class对象,对于基本类型:不能表示为对象,不能使用getClass方式,基本类型也没有类名的概念,不能使用Class.forName()方式,如何表示基本类型的字节码对象呢?—通过第一种方式
所有的数据类型都有class属性
Class clazz = 数据类型.class;
九大内置Class实例:jvm中预先提供好的Class实例,分别是byte、short、int、long、float、double、char、void
表示:byte.class,short.class,int.class…void.class
数组时引用类型,其实就是对象
如何表示数组的Class实例呢? 方式1:数组类型.class; 方式2: 数组对象.getClass();
注意:所有的具有相同的维数、相同的元素类型的数组共享同一份字节码对象,和元素没有关系。
① 获取该类的字节码(要获取一个类的构造器,需要将该类先加载进虚拟机)
② 从该字节码对象中去寻找需要获取的构造器
Constructor 类:表示类中构造器的类型,Constructor的实例就是某一个类中的某一个构造器
获取所有构造器: getConstructors() 【所有,public修饰的】 getDeclaredConstructors()【所有,和访问权限无关】
/* 获取所有的构造器 */
//1、获取构造器所在类的字节码对象
Class clazz = User.class;
//2、获取字节码对象中所有的构造器
// getConstructors() 只能获取当前Class对象所表示类的【public修饰的构造器】
Constructor[] cs = clazz.getConstructors();
//getDeclaredConstructors() 获取当前Class所表示的所有的构造器【和访问权限无关】
cs = clazz.getDeclaredConstructors();
获取指定的一个构造器:
/* 获取指定的一个构造器 */
//1、获取构造器所在类的字节码对象
Class clazz = User.class;
//2、获取字节码对象中获取指定的一个构造器
//获取public User() 无参构造器
Constructor constructor = clazz.getConstructor();
//获取public User(String name) 参数是String 的有参构造器
constructor = clazz.getConstructor(String.class);
//获取private User(String name, int age) 的私有有参构造器
constructor = clazz.getDeclaredConstructor(String.class, int.class);
创建对象
对xml解析,得到元素的属性值是字符串
,需要通过Class.forName方法创建对象)1)找到构造器所在类的字节码对象
2)获取构造器对象
3)使用反射创建对象(调用构造器的方法创建对象)
newInstance方法
创建对象设置当前构造器为可以访问
** Constructor对象.setAccessible(true)
//类中的构造器可以被外界访问同时没有参数,直接使用Class类的newInstance方法创建对象
Class<Person> clazz = Person.class;
Constructor<Person> con= clazz.getConstructor();
con.newInstance();
System.out.println("========================");
//反射:调用构造器的方法创建对象[无参构造器]
clazz = Person.class;
con= clazz.getConstructor(String.class);
con.newInstance("shan");
System.out.println("========================");
//反射:调用构造器的方法创建对象[无参构造器]
clazz = Person.class;
con= clazz.getDeclaredConstructor(String.class, int.class);
//设置当前的构造器【私有的】可以访问
con.setAccessible(true);
con.newInstance("shan", 10);
------跟操作构造器差不多啦。。。
public Method getMethods():获取包括自身和继承过来的所有public 方法
public Method getDeclaredMethods():获取自身所有方法(不包括继承、和访问权限无关)
1)获取方法所在类的字节码对象
2)获取方法对象
3)使用反射调用方法
在Method类中有方法:public Object invoke
(Object obj, Object…args): 表示调用当前Method所表示的方法
obj 表示被调用的方法底层所属的对象【Class对象.newInstance() 当无参外界可访问时】
设置可访问私有的成员 Method对象.setAccessible(true)
静态方法不属于任何对象,静态方法属于类本身
此时把invoke方法的第一个参数设置为null即可 public Object invoke
(null, Object…args)
------跟操作构造器差不多啦。。。
加载资源文件路径: db.properties
Properties p = new Properties();
InputStream in = new FileInputStream("db.properties文件的绝对路径");//绝对路径
p.load(in);//加载资源
类加载器ClassLoader
,类加载器默认就是从classpath根路径去寻找文件的Properties p = new Properties();
//ClassLoader loader = CreateObjDemo.class.getClassLoader();//可以通过Class类的getClassLoader()方法获取
ClassLoader loader = Thread.currentThread().getContextClassLoader();//一般选择通过线程获取类加载器【因为可以不用写类名啦】
InputStream in = loader.getResourceAsStream("db.properties");//相对路径-相对于当前项目的输出路径
p.load(in);//加载资源
Properties p = new Properties();
InputStream in = CreateObjDemo.class.getResourceAsStream("db.properties");//相对路径-相对于加载当前资源文件的字节码根路径
p.load(in);//加载资源