import com.tangcheng.learning.service.lock.annotation.KeyParam;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.junit.Test;
import org.springframework.util.ReflectionUtils; import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List; /**
* @author: tangcheng
* @description:
* @since: Created in 2018/08/02 16:29
*/
public class StringEqualsTest { @Test
public void testEquals() throws IllegalAccessException, NoSuchFieldException {
String a = "abc";
Field valueFieldString = String.class.getDeclaredField("value");
valueFieldString.setAccessible(true);
char[] value = (char[]) valueFieldString.get(a);
value[2] = '@';
String b = "abc";
//a.intern();
System.out.println(a);
System.out.println(b);
System.out.println(a == b); //a和b在内存中的地址是相同的,返回true
System.out.println("abc" == b);//abc和b在内存中的地址是相同的,返回true
System.out.println("ab@" == a); //ab@在内存中的地址和a不相同,返回false
System.out.println(a.equals("ab@"));//"abc"和"ab@"的内存地址不同,但存储的值却是一样的,所以返回 true
System.out.println(a.equals("abc"));//abc的值和a对应的是同一个内内存地址,所以返回true
System.out.println("abc".equals("ab@"));//比较的是对象中的值。abc对应String对象的值已经被更改为ab@,所以返回true
} @Test
public void springReflectionUtilsTest1() {
final List<String> list = new ArrayList<String>();
ReflectionUtils.doWithFields(TwoLevelChildClass.class, new ReflectionUtils.FieldCallback() {
public void doWith(Field field) throws IllegalArgumentException,
IllegalAccessException {
list.add(field.getName());
}
});
System.out.println(list); //[twoLevelChildName, oneLevelChildName, name]
} @Test
public void springReflectionUtilsTest2() {
final List<String> list = new ArrayList<String>();
ReflectionUtils.doWithFields(TwoLevelChildClass.class, field -> list.add(field.getName()), field -> {
KeyParam annotation = field.getAnnotation(KeyParam.class);
if (annotation != null) {
return true;
}
return false;
});
System.out.println(list); //[twoLevelChildName]
} @Data
public static class ParentClass {
private String name;
} @Data
@EqualsAndHashCode(callSuper = true)
public static class OneLevelChildClass extends ParentClass {
private String oneLevelChildName;
} @Data
@EqualsAndHashCode(callSuper = true)
public static class TwoLevelChildClass extends OneLevelChildClass {
@KeyParam
private String twoLevelChildName;
} }

1.方法示例

Java反射相关类中存在大量Declared方法,例如:

Class userClass = User.class;
Method[] methods1 = userClass.getMethods();
Method[] methods2 = userClass.getDeclaredMethods(); Method getUsrMethod = userClass.getDeclaredMethod("getUsername");
Annotation[] annotation1 = getUsrMethod.getAnnotations();
Annotation[] annotation2 = getUsrMethod.getDeclaredAnnotations();

getXxxxx以及getDeclaredXxxx方法到底有什么区别呢?
带Declared的返回 当前Class对象的所有公有的方法/Field,包含从父类或父接口继承而来的方法/Field

不带Declared的返回的是当前Class对象的所有(包括:public,protected,default,private)方法/Field,但是并不包括继承自父类或父接口的方法/Field

2.源码解读

先看一下getMethods()的源代码:

/**
* Returns an array containing {@code Method} objects reflecting all the
* public methods of the class or interface represented by this {@code
* Class} object, including those declared by the class or interface and
* those inherited from superclasses and superinterfaces.
*
* ...省略
*
* @jls 8.2 Class Members
* @jls 8.4 Method Declarations
* @since JDK1.1
*/
@CallerSensitive
public Method[] getMethods() throws SecurityException {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
return copyMethods(privateGetPublicMethods());
}

从方法注释可知:getMethods()返回的是当前Class对象的所有公有的方法,包含从父类或父接口继承而来的方法。


在看一下getDeclaredMethods()的源代码:

/**
*
* Returns an array containing {@code Method} objects reflecting all the
* declared methods of the class or interface represented by this {@code
* Class} object, including public, protected, default (package)
* access, and private methods, but excluding inherited methods.
*
* ...省略
*
* @jls 8.2 Class Members
* @jls 8.4 Method Declarations
* @since JDK1.1
*/
@CallerSensitive
public Method[] getDeclaredMethods() throws SecurityException {
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
return copyMethods(privateGetDeclaredMethods(false));
}

从方法注释可知:getDeclaredMethods()返回的是当前Class对象的所有(包括:public,protected,default,private)方法,但是并不包括继承自父类或父接口的方法。

https://blog.csdn.net/hanchao5272/article/details/79402533

Java反射获取private属性和方法(子类,父类,祖先….)

先来看一个例子:String可变还是不可变?

大家都应该知道,或者听过,String类是不可变的,为什么呢?因为String其实使用一个 
private final char [] value;来保存字符的;final,private,明显就不让你改了啊。但是,大家请看:

    @Test
public void testEquals() throws IllegalAccessException, NoSuchFieldException {
String a = "abc";
Field valueFieldString = String.class.getDeclaredField("value");
valueFieldString.setAccessible(true);
char[] value = (char[]) valueFieldString.get(a);
value[2] = '@';
String b = "abc";
//a.intern();
System.out.println(a);
System.out.println(b);
System.out.println(a == b); //a和b在内存中的地址是相同的,返回true
System.out.println("abc" == b);//abc和b在内存中的地址是相同的,返回true
System.out.println("ab@" == a); //ab@在内存中的地址和a不相同,返回false
System.out.println(a.equals("ab@"));//"abc"和"ab@"的内存地址不同,但存储的值却是一样的,所以返回 true
System.out.println(a.equals("abc"));//abc的值和a对应的是同一个内内存地址,所以返回true
System.out.println("abc".equals("ab@"));//比较的是对象中的值。abc对应String对象的值已经被更改为ab@,所以返回true
}

输出(猜猜看,和你想的一不一样呢?):

ab@
ab@
true
true
false//(如果把intern那个注释去掉的话,就是true)
true
true
true

如果,你都答对了,恭喜你,那请直接跳到 反射用法.

否则:请看下面分析

先摘一段官方intern()的注释:

* Returns a canonical representation for the string object.
* <p>
* A pool of strings, initially empty, is maintained privately by the
* class {@code String}.
* <p>
* When the intern method is invoked, if the pool already contains a
* string equal to this {@code String} object as determined by
* the {@link #equals(Object)} method, then the string from the pool is
* returned. Otherwise, this {@code String} object is added to the
* pool and a reference to this {@code String} object is returned.

3个点: 
* 1.常量池(JVM中就是方法区)是由 String 这个class来私有的管理的。* 
* 2.调用intern()时,会查看常量池是否存在这个String对象,这是通过equals()方法来判断的。* 
* 3.如果存在,则返回常量池中那个String对象,否则,加入到常量池,并返回当前对象。*

ps : equals()方法,首先是看obj1==obj2,也就是引用地址是否相等,如果等则返回true,然后是逐个字符比较。

ok,有了以上知识。其实到这里你自己也可以分析出来了。

我们来分析一下 
首先,String a="abc"; 这句话在内存(常量池)中放入了一个String对象:“abc”(内存地址假设为0x123,由char [] value = [‘a’,’b’,’c’]保存), 
然后第2~5行,我们先不管语法,只要知道是把“abc”这个字符串的第三个字符’c’替换为’@’, 
此时char [] value = [‘a’,’b’,’c’] 变为了char [] value = [‘a’,’b’,’@’],String这个class对象管理的还是“abc”这个对象。 
接下来 String b="abc",这句话会从常量池中寻找“abc”,此时会发现常量池中“abc”是存在的,于是,b就指向了“abc”,b其实就是“abc”的位置的一个引用,a也是一个“abc”位置的引用。 
那么接下来就是顺理成章了:

        System.out.println(a);//a指向"abc"这个对象,而这个对象,内部存储却是{'a','b','@'}
System.out.println(b);//同上
System.out.println(a==b);//都指向0x123
System.out.println("abc"==b);//都是0x123
System.out.println("ab@"==a);//"ab@"这个对象在常量池中没有,会先在常量中生成,地址显然不是0x123,所以输出false,但是,当调用了a.intern()后,会调用String的equals()去常量池中新建一个对象"ab@',并返回这个位置。
System.out.println(a.equals("ab@"));
System.out.println(a.equals("abc"));
System.out.println("abc".equals("ab@"));

如果仔细想想,其实还是有疑问,在这里就不展开了,不然偏题了,因为我对底层也不懂,intern是c++实现的,具体看这篇:

http://www.wtoutiao.com/a/1023451.html

反射

反射,RTTI,Class对象,这些就不说了,看一段代码:

static void getClassFieldAndMethod(Class cur_class) {
String class_name = cur_class.getName();
Field[] obj_fields = cur_class.getDeclaredFields();
for (Field field : obj_fields) {
field.setAccessible(true);
System.out.println(class_name + ":" + field.getName());
}
Method[] methods = cur_class.getDeclaredMethods();
for (Method method : methods) {
method.setAccessible(true);
System.out.println(class_name + ":" + method.getName());
}
if (cur_class.getSuperclass() != null) {
getClassFieldAndMethod(cur_class.getSuperclass());
}
}

或:

private void listAllFields(Object obj) {
List<Field> fieldList = new ArrayList<Field>();
Class tmpClass = obj.getClass();
while (tmpClass != null) {
fieldList.addAll(Arrays.asList(tmpClass .getDeclaredFields()));
tmpClass = tmpClass .getSuperclass();
}
}

https://stackoverflow.com/questions/16295949/get-all-fields-even-private-and-inherited-from-class

 

这段代码输入是一个Class的对象,递归输出这个类的父类,祖父类直到Object类的所有方法和域。

再看一段:

    static void getObjField(Object obj) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{

        Class cur_class = obj.getClass();
getClassFieldAndMethod(cur_class);
Field vfield=cur_class.getDeclaredField("value");
vfield.setAccessible(true);
char[]value=(char[])vfield.get(obj);
System.out.println(Arrays.toString(value));
}

ok,这段代码输入任意一个对象,调用上面那段代码的方法getClassFieldAndMethod(),这样你就知道这个对象都有些什么域,什么方法了,再通过域的名称,就可以获取当前这个对象的域的值,进而可以修改了!!

Java反射 : Declared的作用 ( 例如 : getMethods和getDeclaredMethods )的更多相关文章

  1. Java反射机制的作用?

    Java反射机制的作用? 解答:Java反射机制的作用是: 1)在运行时判断任意一个对象所属的类. 2)在运行时构造任意一个类的对象. 3)在运行时判断任意一个类所具有的成员变量和方法. 4)在运行时 ...

  2. Java反射机制的作用

    假如我们有两个程序员,一个程序员在写程序的时候,需要使用第二个程序员所写的类,但第二个程序员并没完成他所写的类.那么第一个程序员的代码能否通过编译呢?这是不能通过编译的.利用Java反射的机制,就可以 ...

  3. java反射机制的作用与优点

    java的反射机制就是增加程序的灵活性,避免将程序写死到代码里,例如: 实例化一个 person()对象, 不使用反射, new person(); 如果想变成 实例化 其他类, 那么必须修改源代码, ...

  4. 理解Java反射机制

    理解Java反射机制 转载请注明出处,谢谢! 一.Java反射简介 什么是反射? Java的反射机制是Java特性之一,反射机制是构建框架技术的基础所在.灵活掌握Java反射机制,对学习框架技术有很大 ...

  5. Java反射机制的浅显理解(这篇文章还没写好,留个草稿给自己看的)

    目前只是有一个大概的理解,先把自己感觉容易立即的概念放这里,等以后结合实际工作理解深刻了再来补充. 一.什么是Java反射机制?(多种定义) 1. JAVA反射机制是在运行状态中,对于任意一个类,都能 ...

  6. 有关java反射的几个小方法的作用和区别

    1.Class类中 getXXX()和getDeclaredXXX()的作用和区别: 前者获取某个类的所有公共(public)的字段(or方法or构造函数),包括父类.后者获取所有的字段(or方法or ...

  7. java反射的使用场合和作用、及其优缺点

    1)使用场合 在编译时根本无法知道该对象或类可能属于哪些类,程序只依靠运行时信息来发现该对象和类的真实信息. 2)主要作用 通过反射可以使程序代码访问装载到JVM 中的类的内部信息,获取已装载类的属性 ...

  8. java反射技术主要实现类有哪些,作用分别是什么

    Java反射技术主要实现类有哪些,作用分别是什么? 在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中 1)Class类:代表一个类 2)Field 类 ...

  9. 浅谈Java的反射机制和作用

    浅谈Java的反射机制和作用 作者:Java大师 欢迎转载,转载请注明出处 很多刚学Java反射的同学可能对反射技术一头雾水,为什么要学习反射,学习反射有什么作用,不用反射,通过new也能创建用户对象 ...

随机推荐

  1. 脚踏实地学C#3-装箱和拆箱

    装箱:一种接受值类型的值,根据这个值在堆中创建一个完整的引用类型对象并返回对象的引用(堆地址)的隐式转换 int i_number = 2; //在栈中声明int类型i_Number变量并初始化 ob ...

  2. FFT的常数优化

    卡得一手好常数..学习了..(似乎只对FFT有效) JZOJ 4349 #include <bits/stdc++.h> #define LL long long #define DB l ...

  3. c++之拷贝构造函数详解

    C++中经常使用一个常量或变量初始化另一个变量,例如: double x=5.0: double y=x; 使用类创建对象时,构造函数被自动调用以完成对象的初始化,那么能否象简单变量的初始化一样,直接 ...

  4. PhpStorm中如何配置SVN,详细操作方法

    1.简介: PhpStorm是一个轻量级且便捷的PHP IDE,其提供的智能代码补全,快速导航以及即时错误检查等功能大大提高了编码效率.它是一款商业的 PHP 集成开发工具,以其独特的开发便利性,短时 ...

  5. 21.java方法详解

    public class MethondTest07{ //入口 public static void main(String[] args){ A.m1(); //error:若方法名字的前面什么都 ...

  6. CS231n 2016 通关 第四章-反向传播与神经网络(第一部分)

    在上次的分享中,介绍了模型建立与使用梯度下降法优化参数.梯度校验,以及一些超参数的经验. 本节课的主要内容: 1==链式法则 2==深度学习框架中链式法则 3==全连接神经网络 =========== ...

  7. java.lang.NoSuchMethodError: org.springframework.core.io.ResourceEditor错误

    一般是jar包冲突,或者某些jar包版本不同. 如上,spring其他包的版本均为4.2.5,而spring-webmvc的jar包为1.2.6版本,造成版本冲突. 把该包版本改为4.2.5,宣告成功 ...

  8. sql之视图、触发器、函数、存储过程、事务

    视图 # 视图也是一张表,但在data文件里只有表结构,没有表数据 # 不建议使用,扩展性差,程序需改变时,依赖的视图也要改变 # 视图牵涉到多张表时,视图中的记录不能修改. create view ...

  9. Identity Server 4 原理和实战(完结)_为 MVC 客户端刷新 Token

    服务端修改token的过期使劲为60秒 过期了 仍然还能获取到api1的资源 api1,设置每隔一分钟就验证token 并且要求token必须要有超时时间这个参数, 1分钟后提示超时,两边都是一分钟, ...

  10. CodeForces - 566D Restructuring Company 并查集的区间合并

    Restructuring Company Even the most successful company can go through a crisis period when you have ...