-
Class类
(1) 位于 java.lang 下
(2) JavaDoc的介绍
1° Class代表类的类或者接口的类(enum是一种类,注解是一种接口)
2° Class类没有public构造器,所以Class类的对象实例时由JVM自动在类被加载时构造出来的
3° 获取对应的Class实例的方法: 如果是对象,则可以用 对象.getClass()方法获得(getClass()方法是Object类的方法);如果是类,直接用 类名.class(小写)获得
/** * Instances of the class {@code Class} represent classes and * interfaces in a running Java application. An enum is a kind of * class and an annotation is a kind of interface. Every array also * belongs to a class that is reflected as a {@code Class} object * that is shared by all arrays with the same element type and number * of dimensions. The primitive Java types ({@code boolean}, * {@code byte}, {@code char}, {@code short}, * {@code int}, {@code long}, {@code float}, and * {@code double}), and the keyword {@code void} are also * represented as {@code Class} objects. * * <p> {@code Class} has no public constructor. Instead {@code Class} * objects are constructed automatically by the Java Virtual Machine as classes * are loaded and by calls to the {@code defineClass} method in the class * loader. * * <p> The following example uses a {@code Class} object to print the * class name of an object: * * <blockquote><pre> * void printClassName(Object obj) { * System.out.println("The class of " + obj + * " is " + obj.getClass().getName()); * } * </pre></blockquote> * * <p> It is also possible to get the {@code Class} object for a named * type (or for void) using a class literal. See Section 15.8.2 of * <cite>The Java™ Language Specification</cite>. * For example: * * <blockquote> * {@code System.out.println("The name of class Foo is: "+Foo.class.getName());} * </blockquote> * * @param <T> the type of the class modeled by this {@code Class} * object. For example, the type of {@code String.class} is {@code * Class<String>}. Use {@code Class<?>} if the class being modeled is * unknown.
-
获取Class对象的3种方式(上面其实已经说过2个了)
(1) Class c1 = Test.class;
任何一个类都有一个隐含的__static__成员变量class
(2) Class c2 = test.getClass();
通过对象的getClass()方法获得
(3) Class c3 = Class.forName(“com.myself.Test”);
Class类提供了静态方法
public static Class<?> forName(String className) throws ClassNotFoundException
其中className是类的全限定名
-
值得注意的是,无论通过上面的哪种方式获得Class对象,它们获得的Class实例是相同的(注意Class.forName()的写法使用的是Object类的全限定名)
class Solution { public static void main(String[] args) { Class c1 = Object.class; Class c2 = new Object().getClass(); Class c3 = null; Class c4 = new Object().getClass(); try { c3 = Class.forName("java.lang.Object"); } catch (ClassNotFoundException e) { e.printStackTrace(); } System.out.println(c1 == c2); System.out.println(c1 == c3); System.out.println(c1 == c4); } }
输出
true true true
-
Class类是反射的基础,得到Class类对象之后,我们就可以利用Class类中提供的一系列方法实现反射了
-
反射简介
(1) java的反射机制是指在程序__运行__状态中:给定任意一个类,都可以获取到这个类的属性和方法;给定任意一个对象都可以调用这个对象的属性和方法,这种__动态__的获取类的信息和调用对象的方法的功能称之为java的反射机制
(2) 反射的主要功能
1° 运行时构造对象
2° 运行时获取类的成员变量和方法
3° 运行时获取对象的成员变量和方法
4° 生成__动态代理__(Proxy和InvocationHandler两件套)
-
反射操作__构造函数__
构造函数变成了java.lang.reflect.Constructor对象
(1) 获取全部构造函数:getDeclaredConstructors
包括public, protected, default, private,但是不包括父类的构造函数。如果当前Class是interface、基本类型、数组或void,则返回长度为0的数组。返回值是无序的。
public Constructor<?>[] getDeclaredConstructors() throws SecurityException
示例
class Point { int x, y, z; private Point() { } Point(int x) { this.x = x; } protected Point(int x, int y) { this.x = x; this.y = y; } public Point(int x, int y, int z) { this.x = x; this.y = y; this.z = z; } } class Solution { public static void main(String[] args) { Class clazz = Point.class; Constructor<?>[] constructors = clazz.getDeclaredConstructors(); System.out.println(constructors.length); for (Constructor<?> constructor: constructors) { System.out.println(constructor.toString()); if (constructor.toString().startsWith("private")) { try { constructor.setAccessible(true); //要想使用private构造函数,必须先setAccessible为true Point point = (Point) constructor.newInstance(); System.out.println(point.x + " " + point.y + " " + point.z); } catch (Exception e) { e.printStackTrace(); } } } } }
输出结果
4 public Point(int,int,int) protected Point(int,int) Point(int) private Point() 0 0 0
说明getDeclaredConstructors可以成功返回所有构造函数(4个),并且我们还成功的使用了private构造函数创建Point对象
(2) 获取全部public构造器:getConstructors
public Constructor<?>[] getConstructors() throws SecurityException
示例
class BasePoint { int id; public BasePoint(int id) { this.id = id; } } class Point extends BasePoint { int x, y, z; private Point() { super(0); } Point(int x) { super(x); this.x = x; } protected Point(int x, int y) { super(x); this.x = x; this.y = y; } public Point(int x, int y, int z) { super(x); this.x = x; this.y = y; this.z = z; } public Point(int id, int x, int y, int z) { super(id); this.x = x; this.y = y; this.z = z; } } class Solution { public static void main(String[] args) { Class clazz = Point.class; Constructor<?>[] constructors = clazz.getConstructors(); System.out.println(constructors.length); for (Constructor<?> constructor : constructors) { System.out.println(constructor.toString()); } } }
(3) 无论是getConstructors()方法还是getDeclaredConstructors()方法都提供了只返回一个构造器的方法getConstructor()和getDeclaredConstructor(),它们的参数列表都是Class<?>… parameterTypes,用于指定构造函数中的参数
示例
class Solution { public static void main(String[] args) { Class clazz = Point.class; Constructor<Point> constructor = null; try { constructor = clazz.getDeclaredConstructor(int.class, int.class, int.class, int.class); System.out.println(constructor.toString()); constructor = clazz.getDeclaredConstructor(); System.out.println(constructor.toString()); constructor = clazz.getConstructor(int.class, int.class, int.class, int.class); System.out.println(constructor.toString()); constructor = clazz.getConstructor(); System.out.println(constructor.toString()); } catch (NoSuchMethodException e) { e.printStackTrace(); } } }
输出
public Point(int,int,int,int) private Point() public Point(int,int,int,int) java.lang.NoSuchMethodException: Point.<init>() at java.base/java.lang.Class.getConstructor0(Class.java:3302) at java.base/java.lang.Class.getConstructor(Class.java:2110) at Solution.main(Solution.java:68)
-
反射操作__成员变量__
类的成员变量是java.lang.reflect.Field类的对象
(1) 获取全部变量:getDeclaredFields
包括静态/非静态、public/protected/default/private,但是不包括继承的成员变量
public Field[] getDeclaredFields() throws SecurityException
示例
class BaseObject { public static int a = 6; private static int b = 7; private int c = 200; public int d = 1000; } class MyObject extends BaseObject { public static int x = 3; private static String y = "haha"; public String z; private int w; public MyObject(String z, int w) { this.z = z; this.w = w; } } class Solution { public static void main(String[] args) { Class clazz = MyObject.class; MyObject myObject = new MyObject("heihei", 10); Field[] fields = clazz.getDeclaredFields(); System.out.println(fields.length + " fields"); for (Field field : fields) { try { field.setAccessible(true); System.out.println(field.get(clazz)); } catch (Exception e) { try { field.setAccessible(true); System.out.println(field.get(myObject)); } catch (Exception e1) { e1.printStackTrace(); } } System.out.println(field.toString()); } } }
(2) 获取全部public变量:getFields
如果当前的Class对象代表一个类,那么会返回它的所有public域和它的所有基类、实现的所有超接口的public域;
如果当前的Class对象代表一个接口,那么会返回它的所有public域和所有超接口的public域
示例
前半部分和上面的示例一样 class Solution { public static void main(String[] args) { Class clazz = MyObject.class; Field[] fields = clazz.getFields(); System.out.println(fields.length + " fields"); MyObject myObject = new MyObject("heihei", 10); for (Field field : fields) { try { field.setAccessible(true); System.out.println(field.get(clazz)); } catch (Exception e) { try { field.setAccessible(true); System.out.println(field.get(myObject)); } catch (Exception e1) { e1.printStackTrace(); } } System.out.println(field.toString()); } } }
输出
4 fields 3 public static int MyObject.x heihei public java.lang.String MyObject.z 6 public static int BaseObject.a 1000 public int BaseObject.d
(3) 同理,也可以用getField(String name)和getDeclaredField(String name)获取某个特定的域
-
反射操作__成员方法__
类的成员方法是java.lang.reflect.Method的对象
(1) 和前面的类似,getDeclaredMethods()用来获取所有方法,但是不包括超类的方法;getMethods()用来获取所有当前类对象的public方法和超类型的所有public方法;getDeclaredMethod()和getMethod()通过指定方法名称和参数类型,获取某个特定的方法
(2) method.invoke()可以执行这个方法
(3) 示例
class MyObject{ public static int x = 3; private static String y = "haha"; public String z; private int w; public MyObject(String z, int w) { this.z = z; this.w = w; } public int getW() { return this.w; } private void setW(int w) { this.w = w; } } class Solution { public static void main(String[] args) { Class clazz = MyObject.class; MyObject myObject = new MyObject("haha", 4); System.out.println(myObject.getW()); try { Method method = clazz.getDeclaredMethod("setW", int.class); method.setAccessible(true); //由于是private方法,所以要设置可访问权限 method.invoke(myObject, 10); System.out.println(myObject.getW()); } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } } }
输出
4 10
-
利用反射__可以解决无法访问private构造器、域、成员方法的问题__,无论是Construtor、Field还是Method类,都提供了setAccessible(boolean)方法,只要设为true,private也可以访问使用
11_Java反射机制
最新推荐文章于 2022-03-21 12:21:24 发布