一、反射

反射:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象。对于反射的操作实际上就是通过Class对象获取:
 *a、java.lang.reflect.Field:提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。操作类的成员变量。
 *b、java.lang.reflect.Constructor<T>:操作类的够造函数。
 *c、java.lang.reflect.Method:操作类的方法。
在学习反射基础前先创建一个Person对象作为实例:
package com.jalja.org.base.relfect;

public class Person {
private String name;
int age;
public String address; public Person() {
} private Person(String name) {
this.name = name;
} Person(String name, int age) {
this.name = name;
this.age = age;
} public Person(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
} public void show() {
System.out.println("show");
} public void method(String s) {
System.out.println("method " + s);
} public String getString(String s, int i) {
return s + "---" + i;
} private void function() {
System.out.println("function");
} @Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", address=" + address
+ "]";
} }

二、获取类的Class对象

 1 public static void getClassObject() throws ClassNotFoundException{
2 //方式一:Object的getClass()方法
3 Person person1=new Person();
4 Person person2=new Person();
5 Class c1=person1.getClass();
6 Class c2=person2.getClass();
7 System.out.println(person1==person2);//false
8 System.out.println(c1==c2);//true 不管JVM内存中有多少个对象,对于字节码文件来说只有一份
9 //方式二:数据类型的静态class属性
10 Class c3=Person.class;
11 System.out.println(c1==c3);//true
12 //方式三:Class 类的静态方法
13 //public static Class<?> forName(String className)throws ClassNotFoundException
14 Class c4=Class.forName("com.jalja.org.base.relfect.Person");
15 System.out.println(c1==c4);//true
16 }

三、java.lang.reflect.Constructor<T>:对象并使用Constructor类。

1、获取Constructor对象

    //获取Class 对象所表示的类的构造方法
public static void getConstructorTest() throws Exception{
Class c4=Class.forName("com.jalja.org.base.relfect.Person");
//1、获取Class 对象所表示的类所有公共构造方法
//public Constructor<?>[] getConstructors() throws SecurityException
Constructor [] cs=c4.getConstructors();
//2、获取Class 对象所表示的类所有构造方法
//public Constructor<?>[] getDeclaredConstructors() throws SecurityException
Constructor[] cs2 =c4.getDeclaredConstructors();
//3、获取Class对象所表示类的指定指定公共构造方法, parameterTypes 参数是 Class 对象的一个数组 ,是指定数据类型的字节码
//public Constructor<T> getConstructor(Class<?>... parameterTypes);
Constructor cs3=c4.getConstructor();//获取公共的无参构造方法的Constructor对象
//获取 该 构造函数 public Person(String name, int age, String address)
Constructor cs4=c4.getConstructor(String.class,int.class,String.class);
//4、获取Clss对象所表示类指定的构造范法官 parameterTypes 参数是 Class 对象的一个数组,它按声明顺序标识构造方法的形参类型的字节码。
//public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes);
//获取该构造 函数 private Person(String name) 的Constructor对象
Constructor cs5=c4.getDeclaredConstructor(String.class); }

2、通过 Constructor 对象创建Class对象所表示类的实例

public static void createObject() throws Exception{
Class c4=Class.forName("com.jalja.org.base.relfect.Person");
//使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例
//public T newInstance(Object... initargs);
// Person person=new Person()
Constructor cs3=c4.getConstructor();//获取公共的无参构造方法的Constructor对象
Object obj=cs3.newInstance(); //Person person=new Person("jalja", 21, "北京");
Constructor cs4=c4.getConstructor(String.class,int.class,String.class);
Object obj1=cs4.newInstance("jalja",21,"北京");
System.out.println(obj1);//Person [name=jalja, age=21, address=北京] //实例化一个私有的构造函数 private Person(String name)
//控制java的访问检查
//public void setAccessible(boolean flag)
//将此对象的 accessible 标志设置为指示的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。
//值为 false 则指示反射的对象应该实施 Java 语言访问检查。
Constructor cs5=c4.getDeclaredConstructor(String.class);
cs5.setAccessible(true);
Object obj2=cs5.newInstance("张三丰");
System.out.println(obj2);//Person [name=张三丰, age=0, address=null]
}

四、java.lang.reflect.Field

1、获取Field对象

//获取Class类的Field对象
public static void getFieldTest() throws Exception{
Class cs=Class.forName("com.jalja.org.base.relfect.Person");
//1、public Field[] getFields() throws SecurityException
//获取Class 对象所表示的类或接口的所有可访问公共(public修饰的)字段
Field [] fs=cs.getFields();
//2、public Field[] getDeclaredFields() throws SecurityException
// 获取Class 对象所表示的类或接口所声明的所有字段。包括公共、保护、默认(包)访问和私有字段,但不包括继承的字段
Field [] fs1=cs.getDeclaredFields();
//3、public Field getField(String name)throws NoSuchFieldException, SecurityException;
//获取Class 对象所表示的类或接口的指定公共成员(public修饰)字段。name 参数是一个 String,用于指定所需字段的简称
Field fs2=cs.getField("address");
//public Field getDeclaredField(String name) throws NoSuchFieldException,SecurityException
//获取 Class 对象所表示的类或接口的指定已声明字段。name 参数是一个 String,它指定所需字段的简称
Field fs3=cs.getDeclaredField("name");
System.out.println(fs3);
}

2、通过Field对象对指定类属性赋值

//使用 Field对象
public static void createVarValue() throws Exception{
Class cs=Class.forName("com.jalja.org.base.relfect.Person");
Object obj=cs.getConstructor().newInstance();
Field addressField=cs.getField("address");
//public void set(Object obj, Object value);
//将指定对象变量上此 Field 对象表示的字段设置为指定的新值。如果底层字段的类型为基本类型,则对新值进行自动解包
//obj - 应该修改其字段的对象 value - 正被修改的 obj 的字段的新值
addressField.set(obj, "北京");
System.out.println(obj); //Person [name=null, age=0, address=北京] //对非public修饰的变量操作
Field nameField=cs.getDeclaredField("name");
//控制java的访问检查
nameField.setAccessible(true);
nameField.set(obj, "张三丰");
System.out.println(obj);//Person [name=张三丰, age=0, address=北京]
}

五、java.lang.reflect.Method

1、获取Method对象

//获取Method对象
public static void getMethodTest() throws Exception{
Class cs=Class.forName("com.jalja.org.base.relfect.Person");
//1、public Method[] getMethods() throws SecurityException
//获取Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。
Method [] m1=cs.getMethods();
//2、public Method[] getDeclaredMethods() throws SecurityException
//获取Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法
Method [] m2=cs.getDeclaredMethods();
//3、public Method getMethod(String name, Class<?>... parameterTypes)throws NoSuchMethodException, SecurityException;
// 获取Class 对象所表示的类或接口的指定公共成员方法。name 参数是一个 String,用于指定所需方法的简称。parameterTypes 参数是按声明顺序标识该方法形参类型的 Class 对象的一个数组
Method m3=cs.getMethod("show");//无参的方法
Method m4=cs.getMethod("method",String.class);//带参的方法
//public Method getDeclaredMethod(String name, Class<?>... parameterTypes)throws NoSuchMethodException,SecurityException
// Class 对象所表示的类或接口的指定已声明方法。name 参数是一个 String,它指定所需方法的简称,parameterTypes 参数是 Class 对象的一个数组
Method m5=cs.getDeclaredMethod("function");//无参的方法
System.out.println(m5);
}

2、通过Method对象调用指定类的方法

// Method对象的使用
public static void createMethod() throws Exception{
Class cs=Class.forName("com.jalja.org.base.relfect.Person");
Object obj=cs.getConstructor().newInstance();
Method m3=cs.getMethod("show");//无参的方法
//public Object invoke(Object obj,Object... args)
//对带有指定参数的指定对象调用由此 Method 对象表示的底层方法 obj - 从中调用底层方法的对象 args - 用于方法调用的参数
m3.invoke(obj);
//对带参方法的操作
Method m4=cs.getMethod("method",String.class);//带参的方法
m4.invoke(obj,"北京");
//对有返回值得方法操作
Method m6=cs.getMethod("getString",String.class,int.class);//带参的方法
Object str=m6.invoke(obj,"北京",200);
System.out.println(str);
//对私有无参方法的操作
Method m5=cs.getDeclaredMethod("function");
m5.setAccessible(true);
m5.invoke(obj);
}

六、反射操作注解

@ClassAnnotation("tb_person")
public class Person {
@FieldAnnotation(name="table_name",length=32,type="varchar")
private String name;
@FieldAnnotation(name="table_age",length=3,type="int")
private int age;
@FieldAnnotation(name="table_address",length=32,type="varchar")
public String address;
  ....get;
  ....set;
}
//注解类
@Target(value={ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldAnnotation {
String name();
int length();
String type();
}
//注解类
@Target(value={ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ClassAnnotation {
String value();
}
    //Annotation
public static void createAnnotation() throws Exception{
Class cs=Class.forName("com.jalja.org.base.relfect.Person");
//获取该类的所有注解
Annotation[] as= cs.getAnnotations();
//获取该类指定类型的注解 //@com.jalja.org.base.relfect.ClassAnnotation(value=tb_person)
ClassAnnotation at=(ClassAnnotation) cs.getAnnotation(ClassAnnotation.class);
//获取该注解设置的值
String an_value=at.value();//tb_person //获取类 name属性(Field)的注解类型
FieldAnnotation fieldName=cs.getDeclaredField("name").getAnnotation(FieldAnnotation.class);
//获取注解值 #table_name--32--varchar
System.out.println(fieldName.name()+"--"+fieldName.length()+"--"+fieldName.type());
}

java反射基础知识(一)的更多相关文章

  1. java反射基础知识(五)反射应用实践

    详解Java反射各种应用   Java除了给我们提供在编译期得到类的各种信息之外,还通过反射让我们可以在运行期间得到类的各种信息.通过反射获取类的信息,得到类的信息之后,就可以获取以下相关内容: Cl ...

  2. java反射基础知识(四)反射应用实践

    反射基础 p.s: 本文需要读者对反射机制的API有一定程度的了解,如果之前没有接触过的话,建议先看一下官方文档的Quick Start. 在应用反射机制之前,首先我们先来看一下如何获取一个对象对应的 ...

  3. java反射基础知识(三)

    原文地址:http://tutorials.jenkov.com/java-reflection/index.html http://www.cnblogs.com/penghongwei/p/329 ...

  4. java反射基础知识(二)

    1. 了解 Java 中的反射 1.1 什么是 Java 的反射 Java 反射是可以让我们在运行时获取类的函数.属性.父类.接口等 Class 内部信息的机制.通过反射还可以让我们在运行期实例化对象 ...

  5. Java反射基础知识

    反射机制就是可以把一个类,类的成员(属性.方法)当成一个对象来操作,也就是说,类,类的成员,我们在运行的时候可以动态的去操作它们. 所有的Java类都继承了Object类,在Object类中定义了一个 ...

  6. 什么才是java的基础知识?

    近日里,很多人邀请我回答各种j2ee开发的初级问题,我无一都强调java初学者要先扎实自己的基础知识,那什么才是java的基础知识?又怎么样才算掌握了java的基础知识呢?这个问题还真值得仔细思考. ...

  7. Java 多线程——基础知识

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  8. java必备基础知识(一)

    学习的一点建议: 每一门语言的学习都要从基础知识开始,学习是一个过程,"万丈高楼平地起",没有一个好的地基,想必再豪华的高楼大厦终究有一天会倒塌.因此,我们学习知识也要打牢根基,厚 ...

  9. java部分基础知识整理----百度脑图版

    近期发现,通过百度脑图可以很好的归纳总结和整理知识点,本着学习和复习的目的,梳理了一下java部分的知识点,不定期更新,若有不恰之处,请指正,谢谢! 脑图链接如下:java部分基础知识整理----百度 ...

随机推荐

  1. powerDesigner建表时选择不同数据库类型

    l  使用powerDesigner创建表模型的时候可选择数据库类型 如图设置为mysql:

  2. php中while($row = $results->fetch_row())调用出错

    php中while($row = $results->fetch_row())调用出错 错误处在sql语句上

  3. libcgi库安装

    官网:https://boutell.com/cgic/#build 1. 可直接tar包安装 tar xvf libcgi-1.0.tar.gzcd libcgi-1.0./configuremak ...

  4. hdu6035 Colorful Tree 树形dp 给定一棵树,每个节点有一个颜色值。定义每条路径的值为经过的节点的不同颜色数。求所有路径的值和。

    /** 题目:hdu6035 Colorful Tree 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6035 题意:给定一棵树,每个节点有一个颜色值.定 ...

  5. 关于MongoDB最大连接数的查看与修改

    一. MongoDB连接数 在Linux平台下,无论是64位或者32位的MongoDB默认最大连接数都是819,WIN平台不知道,估计也没有人在 WIN平台下使用MongoDB做生产环境 [root@ ...

  6. 2017 ACM区域赛(南宁站) 参赛流水账

    day0: 早上四点起床赶飞机,还好没有吵醒室友导致被打死.本来想在飞机上准备一下下周的小测,结果飞机一点都不平稳,只能全程和队友吹逼聊天.下午在宾馆里和johann通关了一部合金弹头,重温了童年的经 ...

  7. [翻译]在ASP.NET Web API中通过OData支持查询和分页

    OData可以通过形如http://localhost/Products?$orderby=Name这样的QueryString传递查询条件.排序等.你可以在任何Web API Controller中 ...

  8. jquery 复选框全选/全不选切换 普通DOM元素点击选中/取消选中切换

    1.要选中的复选框设置统一的name 用prop() prop() 方法设置或返回被选元素的属性和值. $("#selectAll").click(function(){ $(&q ...

  9. python入门(三):分支、循环、函数

    1.分支 if循环格式:if condition_1: statement_block_1elif condition_2: statement_block_2else: statement_bloc ...

  10. [读书笔记]java核心技术

    ps:有时间好好整理下格式.从别的编辑器拷贝过来啥都没了. ~~~~~~~~~~~~~~· 2.java程序设计环境 JDK 开发java使用的软件: JRE 运行java使用的软件: SE 用于桌面 ...