17.反射
缺点:耗内存,主要用于做工具和框架。
获取Class的方法:
①数据类型.class; (可以基本数据类型、viod、引用数据类型);
②Class.forName("包路径");
③对象.getClass();
如:Person p=new Person();
p.getClass()==Person.class
Class.forName("review.Person")==User.class 都为true
基本数据类型class:
数据类型.class获取基本数据类型的class;
任何包装类型.TYPE都返回被包装的基本数据类型.class
如:Integer.TYPE--->int.class;
获取数组的class:
同类型同维数组的class为同一个,和数组中元素无关。
String [] str1={};
String [] str2={"AB","SD"};
Class clazz=String[].class;
Class clazz2=arr1.getClass();
Class clazz3=arr2.getClass();
clazz2==clazz3为true
多维数组
String [][] str3={};
Class clazz4=arr4.getClass();
clazz2==clazz2为false;
获取构造器:
Class clazz=Class.forName("review.Person");
①Constructor[] list=clazz.getConstructors():只能获取public修饰符的构造方法。
②Constructor constructor=clazz.getConstructors(String.class,Integer.class):获取public的指定构造器,指定参数;
③list=getDeclaredConstructors():可以获取任意修饰符的构造器。
④constructor=getDeclaredConstructor(String.class,Integer.class):获取本类中指定构造器,指定参数;
创建实列对象:
①Person person=(Person) constructor.newInstance("zgm",11):使用constructor调用指定参数创建对象
②Person p=(Person) clazz.newInstance():使用clazz调用无参构造器创建对象
注意:constructor.setAccessible(true):对于私有构造器,使用前需要调用setAccessible()方法,将值设置为true。
获取和使用方法:
获取方法
①getMethods():获取所有public的方法,包括父类的public的方法;
②getMethod("show", String.class):获取public的指定方法,"show"为方法名;
③getDeclaredMethods():获取所有的本类方法与修饰符无关;
④getDeclaredMethods("show", String.class):获取本类方法中的指定带参方法,"show"为方法名;
调用方法
①method.invoke(clazz.newInstance(), "zgm");传入参数clazz.newInstance()为底层所属对象,参数值。
注意:method.setAccessible(true);设置忽略访问修饰符
②method.invoke(null,"cqr"):调用静态方法,传入底层所属对象可以省略。
③method.invoke(clazz.newInstance(),new int[]{1,2,3,4,5}):调用不定参方法,有些不定参会被解包,所以需要在外面再包装如:
method.invoke(clazz.newInstance(),new Object[]{new String[]{"a","b","c"}});
所以总结在无论是定参还是可变参下都使用new Object(){}进行再包装;
获取字段
①getFields();获取所以public的字段,包括继承的。
getFields(String name);获取具体字段,name为字段名。
②getDeclaredFields();获取本类中所以字段。
getDeclaredFields(String name);获取具体字段,name为字段名,如果私有的话则需要打开忽略权限,setAccessible(true)。
操作字段
赋值
①获取Class,获取字段
②如果为非public字段则设置setAccessible(true)
③创建对象.newInstance();
④setXX(obj对象,值);XX为数据类型,也可以省略。
取值
getXX(obj对象,值);XX为数据类型,也可以省略。
18.内部类
①OutClass为外部内,InClass为内部类
public class OutClass {
public class InClass{}
}
②内部类隐藏在外部类防止外界类访问
③内部类可以访问外部类成员,可以看作外部类的一个成员
可以使用private、缺省、protected、public修饰符修饰还可以使用static修饰
④类部类根据修饰符类型或使用位置分为四种:
实例内部类:没使用static修饰
静态内部类:使用static修饰
局部内部类:在方法中定义的内部类
匿名内部类:属于局部内部类特殊情况(用的多)
实例内部类: 修饰符可以是private、缺省、protected、public
编译后名称:外部类$内部类
①在外部调用时需要先实例化外部类对象再调用:
OutClass outClass=new OutClass();
OutClass.InClass inClass=outClass.new InClass();
②实例内部类自动持有外部类的实例引用,内部内可以直接访问外部类成员;
③外部类不能直接访问内部类的成员,必须通过内部类实例方法去访问。
④不能定义static成员变量
⑤当外部内和内部类存在相同成员变量时
内部类调用内部类成员:this.name
内部类调用外部类成员:OutClass.this.name
静态内部类:再内部类创建时加入static
①在外部调用时直接使用 new 外部类.内部类:
OutClass.staticInClass sClass=new OutClass.staticInClass();
②静态内部类可以直接访问外部类的静态成员,如果访问外部类的实例成员需要实例再去访问。
局部内部类:在方法体内定义类,编译后名字为:外部类名称$数字+内部类名称
①只能在方法内使用
②在局部内部类中只能调用final的常量
匿名内部类:是一个没有名称的局部内部类。在开发中值定义一次使用一次就丢弃,编译后名字为:外部类名称$数字
①不存在构造器,使用时调用父类构造器
②
③
语法格式:
new 父类构造器(实参)或接口()
{ 匿名内部类的类体部分
}
Java反射与内部类复习总结
最新推荐文章于 2022-09-19 10:09:39 发布