目录

  • 1 什么是反射?主要提供了哪些功能?
  • 2 如何通过反射获取类的信息?
  • 3 数组的特殊处理。
  • 4 反射的应用场景。
  • 5 其他。

正文

1 什么是反射?主要提供了哪些功能?
  1) Java的反射机制是指在程序运行期间,对于任意一个类,都可以知道这个类的属性和方法,并进行调用。
  2) 提供以下功能:
    ① 在运行时可以判断任意一个对象所属的类。
    ② 在运行时可以构造任意一个类的对象。
    ③ 在运行时可以获取任意一个类的所有成员变量和方法。
    ④ 在运行时调用任意一个对象的方法。
    ⑤ 生成动态代理。
  3) 优缺点
    ① 优点:增加灵活性。
    ② 缺点:使用不当会导致效率低、会破坏封装,且可以访问类的私有方法,不安全。

2 如何通过反射获取类的信息?
  1) 首先获取类的Class对象:
    ① 每一个类、接口、数组、基本类型都有唯一的一个对应的Class类对象。通过Class类对象可以获取类的全部信息(包括成员变量、方法、父类、接口等)。
    ② 获得Class对象的三种方式。【参考TestLoadClass.java】
    ③ Class的常用方法:【参考TestClass.java】 

package com.devway.j2se.reflect;

public class TestLoadClass {
public static void main(String[] args) {
try {
// 获取Class对象的三种方法
// 方法一,通过对象实例获取,
A a = new A();
Class<?> class1 = a.getClass();
System.out.println("1:getClass " + class1); // 方法二,根据类名获取
Class<?> class2 = B.class;
System.out.println("2:.class " + class2);
// 方法三,根据类的全名获取
Class<?> class3 = Class.forName("com.devway.j2se.reflect.C");
System.out.println("3:Class.forName " + class3); } catch (ClassNotFoundException e) {
System.err.println(e);
} }
} class A {
static {
System.out.println("init A static");
}
} class B {
static {
System.out.println("init B static");
}
} class C {
static {
System.out.println("init C static");
}
}

TestLoadClass.java

package com.devway.j2se.reflect;

public class TestClass {
public static void main(String[] args) {
try {
Class<?> class1 = Class.forName("com.devway.j2se.reflect.Child");
System.out.println("1:" + class1);// true // Class类的常用方法
// 判断是否是接口
boolean isInterface = class1.isInterface();// false
// 判断是否是数组
boolean isArray = class1.isArray();// false
// 判断是否是8种基本类型
boolean isPrimitive = class1.isPrimitive();// false;
System.out.println("2:" + isInterface + "," + isArray + "," + isPrimitive); // 获取父类的Class类对象
Class<?> superClass = class1.getSuperclass();
// 获取所有接口
Class<?>[] interfaces = class1.getInterfaces();
// 获取类型修饰符
int modifiers = class1.getModifiers();
System.out.println("3:" + superClass + "," + interfaces + "," + modifiers); // 获取数组的组件类型
int[] ints = { 1, 2, 3 };
Class<?> class4 = ints.getClass();
Class<?> class5 = class4.getComponentType();// int
System.out.println("4:" + class4);
System.out.println("4:" + class5); // 返回声明这个的Class对象,如果不是嵌套类型,返回null
Class<?> class6 = class1.getDeclaringClass();// null
System.out.println("5:" + class6); // 获取包
Package package1 = class1.getPackage();
System.out.println("6:" + package1); } catch (ClassNotFoundException e) {
System.err.println(e);
}
}
} package com.devway.j2se.reflect; public interface Interface1 {
String iv1 = "a";
String iv2 = "b"; void f1();
} package com.devway.j2se.reflect; public class Parent {
public String pv1;
protected String pv2; public Parent() { } public String pf1(String s) {
return s;
} protected void pf2() { } void pf3() { } private void pf4() { } } package com.devway.j2se.reflect; public class Child extends Parent implements Interface1 {
public String cv1;
protected String cv2;
private String cv3;
public static String scv1; public Child() { } public Child(String s, int i) { } protected Child(int i) { } private Child(String s) { } public String cf1(String s, int i) throws NullPointerException {
return s + i;
} protected void cf2() {
System.out.println("protected method cf4()");
} void cf3() {
System.out.println("default method cf4()");
} private void cf4() {
System.out.println("private method cf4()");
} @Override
public void f1() {
System.out.println("public method f1()");
} }

TestClass.java

  2) 对类的构造函数、方法、属性的访问和调用:
    ① Constructor类:用于构造函数。【参考TestConstrcutor.java】
    ② Method类:用于类的方法。【参考TestMethod.java】
    ③ Field类:用于类的属性。【参考TestField.java】
    ④ Modifer类:用于判断修饰符类型。【参考TestModifier.java】
    ⑤ Field、Method、Constructor类都继承了AccessibleObject类(该类用于获取和修该访问权限)【参考TestAccessible.java】,同时也实现了Member接口。

package com.devway.j2se.reflect;

import java.lang.reflect.Constructor;

public class TestConstrcutor {
public static void main(String[] args) {
try {
Class<?> class1 = Class.forName("com.devway.j2se.reflect.Child"); // 获取所有的public构造函数,包括父类和接口的
Constructor<?>[] publicConstructors = class1.getConstructors();
for (Constructor<?> constructor : publicConstructors) {
System.out.println("1:" + constructor);
} // 获取当前类的所有构造函数,不包括父类和接口的
Constructor<?>[] declaredConstructors = class1.getDeclaredConstructors();
for (Constructor<?> constructor : declaredConstructors) {
System.out.println("2:" + constructor);
} // 根据名称和参数获取方法
Constructor<?> constructor1 = class1.getConstructor(String.class, int.class);
System.out.println("3:" + constructor1); // 获取方法参数对应的Class对象
Class<?>[] paramTypesClass = constructor1.getParameterTypes();
for (Class<?> paramType : paramTypesClass) {
System.out.println("4:" + paramType);
} // 获取方法抛出的异常对应的Class对象
Class<?>[] exceptionTypesClass = constructor1.getExceptionTypes();
for (Class<?> exceptionType : exceptionTypesClass) {
System.out.println("6:" + exceptionType);
} // 创建实例并调用方法
Interface1 inf = (Interface1) class1.newInstance();
inf.f1(); } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException e) {
System.err.println(e);
}
}
}

TestConstrcutor.java

package com.devway.j2se.reflect;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; public class TestMethod {
public static void main(String[] args) {
try {
Class<?> class1 = Class.forName("com.devway.j2se.reflect.Child"); // 获取所有的public方法,包括父类和接口的
Method[] publicMethods = class1.getMethods();
for (Method method : publicMethods) {
System.out.println("1:" + method);
} // 获取当前类的所有方法,不包括父类和接口的
Method[] declaredMethods = class1.getDeclaredMethods();
for (Method method : declaredMethods) {
System.out.println("2:" + method);
} // 根据名称和参数获取方法
Method method1 = class1.getMethod("cf1", String.class, int.class);
System.out.println("3:" + method1); // 获取方法返回值类型对应的Class对象
Class<?> returnTypeClass = method1.getReturnType();
System.out.println("4:" + returnTypeClass); // 获取方法参数对应的Class对象
Class<?>[] paramTypesClass = method1.getParameterTypes();
for (Class<?> paramType : paramTypesClass) {
System.out.println("5:" + paramType);
} // 获取方法抛出的异常对应的Class对象
Class<?>[] exceptionTypesClass = method1.getExceptionTypes();
for (Class<?> exceptionType : exceptionTypesClass) {
System.out.println("6:" + exceptionType);
} // 方法调用
Child child = (Child) class1.newInstance();
String value = (String) method1.invoke(child, "abc", 123);
System.out.println("7:" + value);
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException
| IllegalArgumentException | InvocationTargetException e) {
System.err.println(e);
}
}
}

TestMethod.java

package com.devway.j2se.reflect;

import java.lang.reflect.Field;

public class TestField {
public static void main(String[] args) {
try {
Class<?> class1 = Class.forName("com.devway.j2se.reflect.Child"); // 获取所有的public域,包括父类和接口的
Field[] publicFields = class1.getFields();
for (Field field : publicFields) {
System.out.println("1:" + field);
} // 获取当前类的所有域,不包括父类和接口的
Field[] declaredFields = class1.getDeclaredFields();
for (Field field : declaredFields) {
System.out.println("2:" + field);
} // 根据名称获取域
Field field1 = class1.getField("cv1");
System.out.println("3:" + field1); // 获取域类型的Class对象
Class<?> field1Class = field1.getType();
System.out.println("4:" + field1Class); // 读取域的值
Child child = (Child) class1.newInstance();
child.cv1 = "abc";
String field1Value = (String) field1.get(child);// abc
System.out.println("5:" + field1Value); // 修改域的值
field1.set(child, "def");
System.out.println("6:" + child.cv1); } catch (ClassNotFoundException | NoSuchFieldException | SecurityException | InstantiationException | IllegalAccessException e) {
System.err.println(e);
}
}
}

TestField.java

package com.devway.j2se.reflect;

import java.lang.reflect.Modifier;

public class TestModifier {
public static void main(String[] args) {
try {
Class<?> class1 = Class.forName("com.devway.j2se.reflect.Child");
boolean isPrivate = Modifier.isPrivate(class1.getModifiers());// false;
System.out.println("1:" + isPrivate); boolean isAbastract = Modifier.isAbstract(class1.getModifiers());// false
System.out.println("2:" + isAbastract);
} catch (ClassNotFoundException e) {
System.err.println(e);
}
}
}

TestModifier.java

package com.devway.j2se.reflect;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; public class TestAccessible {
public static void main(String[] args) {
try {
Class<?> class1 = Class.forName("com.devway.j2se.reflect.Child");
Method method1 = class1.getDeclaredMethod("cf4"); Interface1 inf = (Interface1) class1.newInstance();
// ! method1.invoke(inf,null);//cf4是private方法,不能访问
System.out.println("1:" + method1.isAccessible());//false //取消访问限制
method1.setAccessible(true);
method1.invoke(inf,null);
System.out.println("2:" + method1.isAccessible());//true
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException
| IllegalArgumentException | InvocationTargetException e) {
System.err.println(e);
} }
}

TestAccessible.java

3 数组的特殊处理。

  1) 数组是没有方法和属性的对象,所以不能通过反射常用的的方法来获取或设置成员。
  2) 可以通过反射创建数组,使用两种new Instance的方法来创建。使用Array.set和Array.get来设置或获取数组元素的值。【参考TestArray.java】  

package com.devway.j2se.reflect;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method; public class TestArray {
public static void main(String[] args) {
Integer[] arrays1 = { 1, 2, 3, 4 };
Class<?> class1 = arrays1.getClass(); // 数组是没有方法和域的对象,所以都返回null
Method[] delcaredMethods = class1.getDeclaredMethods();
for (Method method : delcaredMethods) {
System.out.println("1:" + method);// null
} Field[] delcaredFields = class1.getDeclaredFields();
for (Field field : delcaredFields) {
System.out.println("2:" + field);// null
} // 创建数组方式1
Integer[] arrays2 = (Integer[]) Array.newInstance(Integer.class, 5); // 创建数组方式2,返回多为数组
int[] intval = { 2, 2 };
Integer[][] arrays3 = (Integer[][]) Array.newInstance(Integer.class, intval); // 设置数组元素的值
for (int i = 0; i < arrays2.length; i++) {
Array.set(arrays2, i, i + 1);
} // 获取数组元素的值
for (int i = 0; i < arrays2.length; i++) {
System.out.println("3:" + Array.get(arrays2, i));
} }
}

TestArray.java

4 反射的应用场景。

  1) 用于基础框架中,如Spring。
  2) JDBC,数据库可能使用Oracle,也可能使用Mysql,不同的数据库有不同的驱动,在运行时,再通过Class.forName()运用反射动态加载。
  3) 应用开发中,尽量避免使用反射。

5 其他。

  1) class.getName方法返回结果
    ① 数组类型以[为前缀,后面跟着成员的类型编码,基础类型则简写如下。
    (B:byte、C:char、D:double、F:float、I:int、J:long、S:short、Z:boolean)
    ② 嵌套类型使用$符号将类型名隔开:Outer$Inner
  2) 注意这种写法是错误的:Class<Parent> c = Child.class; 因为Child.class不是Parent的子类,正确写法是:Class<? extends Parent> c= Child.class。
  3) 向上转型和向下转型:
    ① 向上转型:子类转为父类,自动转换。
    ② 向下转型:父类转为子类,需要强制转换。

J2SE-反射的更多相关文章

  1. J2SE 8的反射

    1.获得Class的四种方式 //(1) 利用对象调用getClass()方法获取该对象的Class实例 Class<? extends ReflectTest> class1 = new ...

  2. Java反射机制的学习

    Java反射机制是Java语言被视为准动态语言的关键性质.Java反射机制的核心就是允许在运行时通过Java Reflection APIs来取得已知名字的class类的相关信息,动态地生成此类,并调 ...

  3. 初识JAVA(【面向对象】:pub/fri/pro/pri、封装/继承/多态、接口/抽象类、静态方法和抽象方法;泛型、垃圾回收机制、反射和RTTI)

    JAVA特点: 语法简单,学习容易 功能强大,适合各种应用开发:J2SE/J2ME/J2EE 面向对象,易扩展,易维护 容错机制好,在内存不够时仍能不崩溃.不死机 强大的网络应用功能 跨平台:JVM, ...

  4. Java 使用反射拷贝对象一般字段值

    在<Java解惑>上面看到第八十三例--诵读困难者,要求使用非反射实现单例对象的拷贝.查阅了部分资料,先实现通过反射拷贝对象. 1. 编写需要被拷贝的对象Person package co ...

  5. Java反射机制(转载)

    原文链接:http://www.blogjava.net/zh-weir/archive/2011/03/26/347063.html Java反射机制是Java语言被视为准动态语言的关键性质.Jav ...

  6. 认识J2SE

    1. J2SE的定义 J2SE:全称为Java 2 Standard Edition.Java 2平台包括:标准版(J2SE).企业版(J2EE)和微缩版(J2ME)三个版本. J2SE主要包括UI. ...

  7. (转载)Java反射机制

    Java反射机制是Java语言被视为准动态语言的关键性质.Java反射机制的核心就是允许在运行时通过Java Reflection APIs来取得已知名字的class类的相关信息,动态地生成此类,并调 ...

  8. J2SE 8的注解

    1. 注解概念 (1) 注解格式 modifiers @interface AnnotationName { type elementName(); type elementName() defaul ...

  9. J2SE语言--百度百科

    Java2平台包括:标准版(J2SE).企业版(J2EE)和微缩版 (J2ME)三个版本.J2SE,J2ME和J2EE,这也就是SunONE(Open NetEnvironment)体系.J2SE就是 ...

  10. J2SE核心开发实战(一)——认识J2SE

    认识J2SE 一.课程简单介绍 在本章学习開始前,你应该具备一些Java的基础知识. 我们将在本章来认识J2SE,并复习一下前面学过的面向对象的相关知识. 注:全部的蓝色文字都是带超链接的,这些链接是 ...

随机推荐

  1. JSP前后台数据交互

    1.一般方法:在页面加载时载入数据 首先,新建一个包,在包内创建一个类,类实现接口Servlet-javax.servlet 然后,在web.xml文件里配置如下 <?xml version=& ...

  2. canvas绘制太阳系

    原文地址:http://jeffzhong.space/2017/10/26/solar/ 学习canvas有一段时间了,顺便写个小项目练手,该项目用到的知识点包括: ES6面向对象 基本的三角函数 ...

  3. 使用ftp软件上传下载php文件时换行丢失bug(全部变为一行)

    文章来源:http://www.piaoyi.org/computer/ftp-php-r-n-bug.html 正 文: 在使用ftp软件上传下载php源文件时,我们偶尔会发现在本地windows下 ...

  4. 【工具】Spring项目转化Spring Web项目插件

    前言 源于前一篇博文中提到,将Spring项目转化为Spring Web项目,发现添加项目文件和修改pom.xml文件等都是手动完成的,心想着开发一个Idea插件来自动化完成上面的过程,实现一键转化. ...

  5. Android Studio常见问题解决

    1.Error:Execution failed for task ':XXXX:processDebugManifest'. > Manifest merger failed with mul ...

  6. 移动端通过ajax上传图片(文件)并在前台展示——通过H5的FormData对象

    前些时候遇到移动端需要上传图片和视频的问题,之前一直通过ajax异步的提交数据,所以在寻找通过ajax上传文件的方法.发现了H5里新增了一个FormData对象,通过这个对象可以直接绑定html中的f ...

  7. 前端开发:H5直播起航

    前言 前不久抽空对目前比较火的视频直播,做了下研究与探索,了解其整体实现流程,以及探讨移动端HTML5直播可行性方案. 发现目前 WEB 上主流的视频直播方案有 HLS 和 RTMP,移动 WEB 端 ...

  8. 为Lua5.3编写C模块简单示例

    为Lua5.3编写C模块简单示例 一.编译安装Lua5.3 MSVC 命令行安装脚本: @echo off md bin md lib md include cd src cl /c /nologo ...

  9. IdentityServer4 指定角色授权(Authorize(Roles="admin"))

    1. 业务场景 IdentityServer4 授权配置Client中的AllowedScopes,设置的是具体的 API 站点名字,也就是使用方设置的ApiName,示例代码: //授权中心配置 n ...

  10. iOS 中的 Delayed Transition

    Android 的动画体系中,存在一类由 TransitionManager. beginDelayedTransition 管理的动画.这个方法,很特殊.执行此方法后,其后续的 UI 变化,不会立即 ...