引入
多态确实提高了扩展性,但是并未达到最好,看一下例子
package com.hz;
public interface Pay {
void NFC(); // 移动支付
}
package com.hz;
class Alipay implements Pay{
@Override
public void NFC() {
System.out.println("使用支付宝支付");
}
}
class WeChatPay implements Pay{
@Override
public void NFC() {
System.out.println("使用微信支付");
}
}
package com.hz;
class Test{
public static void main(String[] args) {
// 如果还有其他支持,还要加一堆判断。 多态的无奈
// String payType = "微信";
String payType = args[0];
Pay pay = null;
if (payType.equals("微信")){
pay = new WeChatPay();
}else if(payType.equals("支付宝")){
pay = new Alipay();
}
assert pay != null;
pay.NFC();
}
}
如果使用反射
package com.hz;
class Test{
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
// 配置文件配置要使用的类
String payClass = "com.hz.WeChatPay";
Pay pay = (Pay) Class.forName(payClass).newInstance();
pay.NFC();
}
}
反射机制
-
Java可以称为 "准动态语言"。即java有一定的动态性,可以利用反射机制获得类似动态语言的特性。
-
反射机制允许程序在执行期间借助于ReflectionAPI获取任何类的内部信息,并且能够直接操作任意对象的内部属性及方法。
-
反射机制使得Java编程时更加灵活,从而达到最佳的扩展性。
如何获得Class对象
-
如果已有具体的类,通过类的class属性获取,最为安全可靠且性能最高的方法
Class c = Person.class -
已知某个类的实例,调用此实例的getClass()方法获取Class对象
Class c = person.getClass() -
已知一个类的全名且在类路径下,可以通过Class类的静态方法forName()获取
Class c= ClassforName(“com.hz.Person”); -
内置基本数据类型可以直接使用 类名.Type
Person.Type -
用ClassLoader
类型的Class对象
- class:外部类、成员(成员内部类、静态内部类),局部内部类,匿名内部类。
- interface:接口
- []:数组
- enum:枚举
- annotation:注解
- primitive type:基本数据类型
- void
Class c1= Object.class; //类
Class c2= Runnable.class; //接口
Class c3= String[].class; //一维数组
Class c4= int[][].class; //二维数组
Class c5=Override.class; //注解
Class c6= ElementType.class; //枚举
Class c7= Integer.class; //基本数据类型
Class c8= void.class; //void
Class c9= Class.class; //Class
常用方法
[ 示例类]
以下都基于这个类来说明
package com.hz;
import java.lang.reflect.Constructor;
enum Gender{
Male, Female
}
public class Person {
public String name;
int age;
Gender sex;
public Person() {
}
private Person(String name){
}
public Person(String name, int age, Gender sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Gender getSex() {
return sex;
}
public void setSex(Gender sex) {
this.sex = sex;
}
private void doSth(){
System.out.println("干活干活");
}
private List<String> printCollection(List<Integer> list, Map<Integer, String> map){
System.out.println(list);
System.out.println(map);
List<String> ls = new ArrayList<>();
ls.add("张三");
return ls;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
'}';
}
}
获取类
Class.forName(String classPath) 返回指定类名name对应的Class对象
try {
Class clz = Class.forName("com.hz.Person");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
获取构造器
getDeclaredConstructors() 获取所有的构造函数
getDeclaredConstructor(paramTypes) 获取一个所有的构造函数
getConstructors() 获取所有公开的构造函数
getConstructor(paramTypes) 获取单个公开的构造函数
所有构造器
Class clz = Class.forName("com.hz.Person");
Constructor[] constructors = clz.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
无参构造器
Class clz = Class.forName("com.hz.Person");
Constructor constructor = clz.getConstructor();
System.out.println(constructor);
有参构造器
Class clz = Class.forName("com.hz.Person");
Constructor constructor = clz.getDeclaredConstructor(
String.class,
int.class,
Gender.class);
System.out.println(constructor);
私有构造器
Class clz = Class.forName("com.hz.Person");
Constructor declaredConstructor = clz.getDeclaredConstructor(String.class);
System.out.println(declaredConstructor);
获取修饰符
getModifiers() 获取所有修饰符
返回类型:int
返回值: 修饰符之和,比如:public static void test(){} 返回值是: public + static
| 修饰符 | 值 |
|---|---|
| 默认 | 0 |
| public | 1 |
| private | 2 |
| protected | 4 |
| static | 8 |
| final | 16 |
| synchronized | 32 |
| volatile | 64 |
| transient | 128 |
| native | 256 |
| interface | 521 |
| abstract | 1024 |
Class clz = Class.forName("com.hz.Person");
Constructor declaredConstructor = clz.getDeclaredConstructor(String.class);
final int modifiers = declaredConstructor.getModifiers();
System.out.println(modifiers);
// Modifier 类可以判断修饰符, 这里判断是否是私有
System.out.println(Modifier.isPrivate(modifiers));
获取名字
getName() 获取全名 例如:com.hz.Person
getSimpleName() 获取类名 例如:Person
Class clz = Class.forName("com.hz.Person");
System.out.println(clz.getName());
System.out.println(clz.getSimpleName());
获取包
getPackage()
Package aPackage = clz.getPackage();
获取接口
getSuperclass()
System.out.println(clz.getSuperclass());
获取方法
getMethods() 获取所有公开的方法
getDeclaredMethods() 获取所有的方法
getMethod(String name) 获取单个public方法,参数为方法名
getDeclaredMethod(String name) 获取单个任意方法,参数为方法名
Class clz = Class.forName("com.hz.Person");
System.out.println(Arrays.toString(clz.getMethods()));
System.out.println(Arrays.toString(clz.getDeclaredMethods()));
System.out.println(clz.getMethod("getName"));
System.out.println(clz.getDeclaredMethod("doSth"));
获取字段
getFields() 获取所有的public字段
getDeclaredFields() 获取所有的字段
getField(String name) 获取单个public字段,参数为指定字段
getDeclaredField(String name) 获取单个任意字段,参数为指定字段
Class clz = Class.forName("com.hz.Person");
System.out.println(Arrays.toString(clz.getFields()));
System.out.println(Arrays.toString(clz.getDeclaredFields()));
System.out.println(clz.getField("name"));
System.out.println(clz.getDeclaredField("age"));
实例化对象
newInstance(Object initargs)
Class clz = Class.forName("com.hz.Person");
// 无参构造器
Constructor constructor = clz.getConstructor();
System.out.println(constructor.newInstance());
// 有参构造器
constructor = clz.getConstructor(String.class, int.class, Gender.class);
System.out.println(constructor.newInstance("张三", 16, Gender.Male));
安全检查
-
setAccessible 作用是启用和禁用访问安全检查的开关
-
提高反射的效率, 如果反射代码频繁被调用,请设置为true
-
私有成员可以被读写,私有方法可以被调用
setAccessible(true) 禁用检查
setAccessible(false) 启用检查
Class clz = Class.forName("com.hz.Person");
Constructor constructor = clz.getConstructor();
Person person= (Person) constructor.newInstance();
Field age = clz.getDeclaredField("age");
// 默认是false
age.setAccessible(true);
age.setInt(person, 22);
System.out.println(person);
方法调用
method.invoke(Object obj, Object... args)
obj:实例方法,传类对象; 静态方法,传null
args:方法的参数,没有写null或不写
Class clz = Class.forName("com.hz.Person");
Constructor constructor = clz.getConstructor();
Person person= (Person) constructor.newInstance();
Method getName = clz.getMethod("setName", String.class);
getName.invoke(person, "李四");
System.out.println(person);
浙公网安备 33010602011771号