1. Class对象
- 每个类都有一个class对象,每当编写且编译了一个新类,就会产生一个Class对象(更恰当的说,是保存在一个同名的.class文件中)。
- 所有的类都是在对其第一次使用时动态加载到JVM中的。当程序创建第一个对类的静态成员的引用时,就会加载这个类。这个证明构造器也是类的静态方法。
public class Shop {
public static void main(String[] args) {
System.out.println("运行main()...");
new Candy();
System.out.println("获取Cookie的Class对象");
try {
// 获取Cookie类的Class对象
Class<?> forName = Class.forName("clazz.Cookie"); // 包名+类名
System.out.println(forName.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
class Candy {
static {
System.out.println("糖果");
}
}
class Cookie {
static {
System.out.println("饼干");
}
}
运行main()...
糖果
获取Cookie的Class对象
饼干
clazz.Cookie
- 利用Class对象可以获取类型信息并创建实例。
package clazz;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class CateTest {
private static void print(Class c) {
System.out.println(c.getName()+ "是" + (c.isInterface() ? "接口" : "类"));
}
@SuppressWarnings("all")
public static void main(String[] args) throws ClassNotFoundException,
NoSuchMethodException, IllegalAccessException,
InvocationTargetException, InstantiationException {
Class<?> clazz = null;
clazz = Class.forName("clazz.Cate");
print(clazz);
for (Class c : clazz.getInterfaces()) { // 获取接口Class
print(c);
}
Class up = clazz.getSuperclass(); // 获取父类Class
print(up);
//有参构造器创建实例
Constructor<Food> foodInit = up.getConstructor(String.class);
Food food = foodInit.newInstance("food"); // 创建实例
food.print();
//无参构造器创建实例
Constructor<Food> foodNoArgs = up.getConstructor();
Food food1 = foodNoArgs.newInstance();
food1.print();
}
}
class Cate extends Food implements Rice, Drink, Meat {
Cate(String name) {
super(name);
}
}
class Food {
private String name;
public Food() {
this.name = "no food";
}
public Food(String name) { // 构造器一定到用public声明,否则calss对象无法获取
this.name = name;
}
public void print() {
System.out.println(name);
}
}
interface Rice {}
interface Drink {}
interface Meat {}
clazz.Cate是类
clazz.Rice是接口
clazz.Drink是接口
clazz.Meat是接口
clazz.Food是类
food
no food
- 类字面常量
诸如Cate.class
,int.class
即类字面常量。
利用类字面常量可以优化上述代码(因为这种方式获取Class对象更简单、更安全)。
Class<Cate> clazz = Cate.class;
- 使用.class语法获取Class对象不会引发初始化。
instanceof 关键字
- instanceof 关键字用于检查一个对象是否是某个类的实例
Integer i = 12;
boolean b = i instanceof Integer; // true
// boolean c = 12 instanceof Integer; // error
Cate cate = new Cate("");
boolean d = cate instanceof Food; // true
boolean e = cate instanceof Rice; // true
Object o = new Cate("o");
boolean f = o instanceof Cate; // true
反射
a. 概念
java反射机制是在运行状态中,对于任意一个类都能知道这个类的所有属性和方法;对于一个对象,都能调用其任意一个属性和方法。这种动态获取类的信息或动态调用对象的方法叫做反射。
b. 通过反射获取构造方法并使用
public class ConstructorDemo {
public static void main(String[] args) throws Exception {
Class<Student> clazz = Student.class;
System.out.println("获取所有共有构造器");
Constructor[] constructors = clazz.getConstructors();
for (Constructor c : constructors) {
System.out.println(c);
}
System.out.println("获取所有构造器");
constructors = clazz.getDeclaredConstructors();
for (Constructor c : constructors) {
System.out.println(c);
}
//获取无参构造器并调用
Constructor<Student> conNoArgs = clazz.getConstructor();
Student student = conNoArgs.newInstance();
// 获取私有构造器并调用
Constructor<Student> conPri = clazz.getDeclaredConstructor(Integer.class);
conPri.setAccessible(true); // 暴力访问(忽略掉访问修饰符)
Student student1 = conPri.newInstance(13);
}
}
class Student {
public Student() {
System.out.println("student...");
}
public Student(String name) {
System.out.println("student[name=" + name + "]");
}
public Student(String name, Integer age) {
System.out.println("student[name=" + name + ", age=" + age + "]");
}
private Student(Integer age) {
System.out.println("student[age=" + age + "]");
}
}
获取所有共有构造器
public reflect.Student(java.lang.String,java.lang.Integer)
public reflect.Student(java.lang.String)
public reflect.Student()
获取所有构造器
private reflect.Student(java.lang.Integer)
public reflect.Student(java.lang.String,java.lang.Integer)
public reflect.Student(java.lang.String)
public reflect.Student()
student...
student[age=13]
c. 获取成员变量并调用
public class FieldDemo {
public static void main(String[] args) throws Exception {
Class<Teacher> clazz = Teacher.class;
System.out.println("获取公共字段");
Field[] fields = clazz.getFields();
for (Field f : fields) {
System.out.println(f);
}
System.out.println("获取所有字段");
fields = clazz.getDeclaredFields();
for (Field f : fields) {
System.out.println(f);
}
System.out.println("获取公共字段并调用");
Field name = clazz.getField("name");
Constructor<Teacher> constructor = clazz.getConstructor();
Teacher teacher = constructor.newInstance();
name.set(teacher, "小明");
System.out.println(teacher);
System.out.println("获取非公共字段并调用");
Field age = clazz.getDeclaredField("age");
Field email = clazz.getDeclaredField("email");
age.set(teacher, 23);
email.setAccessible(true); //暴力反射,解除私有限定
email.set(teacher, "1234567@qq.com");
System.out.println(teacher);
}
}
class Teacher {
public String name;
protected Integer age;
boolean sex;
private String email;
public Teacher() {}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
", email='" + email + '\'' +
'}';
}
}
获取公共字段
public java.lang.String reflect.Teacher.name
获取所有字段
public java.lang.String reflect.Teacher.name
protected java.lang.Integer reflect.Teacher.age
boolean reflect.Teacher.sex
private java.lang.String reflect.Teacher.email
获取公共字段并调用
Teacher{name='小明', age=null, sex=false, email='null'}
获取非公共字段并调用
Teacher{name='小明', age=23, sex=false, email='1234567@qq.com'}
d. 获取成员方法并调用
public class MethodDemo {
public static void main(String[] args) throws Exception {
Class<Food> clazz = Food.class;
System.out.println("获取所有'共有'方法");
Method[] methods = clazz.getMethods();
for (Method m : methods) {
System.out.println(m);
}
System.out.println("获取所有方法(除Object方法外的所有方法)");
methods = clazz.getDeclaredMethods();
for (Method m : methods) {
System.out.println(m);
}
System.out.println("获取共有方法");
Method eat = clazz.getMethod("eat", String.class);
Object o = (clazz.getConstructor()).newInstance();
eat.invoke(o, "饭");
System.out.println("获取私有方法");
Method peach = clazz.getDeclaredMethod("peach");
peach.setAccessible(true);
peach.invoke(o);
}
}
class Food {
public Food() {}
public void eat(String food) {
System.out.println("吃" + food);
}
protected void water() {
System.out.println("喝水");
}
void apple() {
System.out.println("吃苹果");
}
private void peach() {
System.out.println("吃桃子");
}
}
获取所有'共有'方法
public void reflect.Food.eat(java.lang.String)
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
获取所有方法(除Object方法外的所有方法)
private void reflect.Food.peach()
public void reflect.Food.eat(java.lang.String)
protected void reflect.Food.water()
void reflect.Food.apple()
获取共有方法
吃饭
获取私有方法
吃桃子
e. 动态代理
- 在程序运行期间动态创建代理类及其实例来完成具体的功能叫做动态代理。
- JDK动态代理的相关类和接口
1、java.lang.reflect.Proxy
用于动态生成代理类。通过调用以下方法创建新的实例。
newProxyInstance(ClassLoader loader, Class<?> caller, Constructor<?> cons, InvocationHandler h)
loader
:被监控对象的ClassLoader
。
caller
:被监控对象的实现接口。
h
:调用处理器
2、java.lang.reflect.InvocationHandler
:该接口包含一个invoke
方法,通过该方法实现对委托类的代理的访问,并且添加新的业务逻辑。
public interface Subject {
void eat(String food);
void looks();
}
public class Panda implements Subject {
@Override
public void eat(String food) {
System.out.printf("I like eating %s.\n", food);
}
@Override
public void looks() {
System.out.println("I am so cute.");
}
}
public class DynamicProxy implements InvocationHandler {
private Object subject;
public DynamicProxy(Object subject) {
this.subject = subject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//在代理对象前我们可以执行自己的一些操作
System.out.println("before method...");
System.out.println(method);
// 调用代理对象的方法
method.invoke(subject, args);
System.out.println("after method...");
return null;
}
public static void main(String[] args) {
Subject panda = new Panda();
InvocationHandler handler = new DynamicProxy(panda);
Subject subject = (Subject) Proxy.newProxyInstance(panda.getClass().getClassLoader(),
panda.getClass().getInterfaces(), handler);
subject.eat("bamboo");
subject.looks();
System.out.println(subject instanceof Panda); // false
System.out.println(subject instanceof Subject); // true
}
before method...
public abstract void proxy.Subject.eat(java.lang.String)
I like eating bamboo.
after method...
before method...
public abstract void proxy.Subject.looks()
I am so cute.
after method...
false
true
网友评论