`
javatar
  • 浏览: 1704907 次
  • 性别: Icon_minigender_1
  • 来自: 杭州699号
社区版块
存档分类
最新评论

修复Getter取值BUG

    博客分类:
  • HTTL
阅读更多
http://www.commontemplate.org
BUG: 在获取特殊Class(内部类)的属性时可能抛出异常, 将在下一版本(0.8.2)更新修复此bug.
重构前程序:
public class ClassUtils {

	/**
	 * 获取对象的属性值
	 * 
	 * @param object 对象实例
	 * @param property 属性名
	 * @return 属性的值
	 */
	public static Object getObjectProperty(Object object, String property) throws NoSuchMethodException, SecurityException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchFieldException {
		if (object == null)
			return null;
		try {
			return getClassGetter(object.getClass(), property).invoke(object, new Object[0]);
		} catch (NoSuchMethodException e) {
			return object.getClass().getField(property).get(object);
		}
	}

	/**
	 * 查找getXXX与isXXX的属性Getter方法
	 * 
	 * @param clazz 类元
	 * @param property 属性名
	 * @return 属性Getter方法
	 */
	public static Method getClassGetter(Class clazz, String property) throws NoSuchMethodException, SecurityException {
		Assert.assertNotNull(clazz, "class不能为空!");
		Assert.assertNotEmpty(property, "property不能为空!");
		property = property.trim();
		String upper = property.substring(0, 1).toUpperCase() + property.substring(1);
		try {
			Method getter = clazz.getMethod("get" + upper);
			Assert.assertTrue(getter.getReturnType() != Void.class, "getter返回值类型不能为void!");
			return getter;
		} catch (NoSuchMethodException e1) {
			try {
				Method getter = clazz.getMethod("is" + upper);
				Assert.assertTrue(getter.getReturnType() != Void.class, "getter返回值类型不能为void!");
				return getter;
			} catch (NoSuchMethodException e2) {
				Method getter = clazz.getMethod(property);
				Assert.assertTrue(getter.getReturnType() != Void.class, "getter返回值类型不能为void!");
				return getter;
			}
		}
	}

}

其中: clazz . getMethod(), 在普通public的POJO下是正常的, 但对私有实现类, 内部类, 匿名类等都有问题.
测试:
Map map = new HashMap();
map.put("aa", "bb");
Map.Entry entry = (Map.Entry)map.entrySet().iterator().next();
Object key = ClassUtils.getObjectProperty(entry, "key");

此测试会抛出异常: can not access a member of class java.util.HashMap$Entry with modifiers "public"
这是因为 HashMap$Entry 是内部实现类, 其类修饰符不是public造成的.

重构如下: (加入getClassMethod)
public class ClassUtils {

	/**
	 * 获取对象的属性值
	 * 
	 * @param object 对象实例
	 * @param property 属性名
	 * @return 属性的值
	 */
	public static Object getObjectProperty(Object object, String property) throws NoSuchMethodException, SecurityException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchFieldException {
		if (object == null)
			return null;
		try {
			return getClassGetter(object.getClass(), property).invoke(object, new Object[0]);
		} catch (NoSuchMethodException e) {
			return object.getClass().getField(property).get(object);
		}
	}

	/**
	 * 查找getXXX与isXXX的属性Getter方法
	 * 
	 * @param clazz 类元
	 * @param property 属性名
	 * @return 属性Getter方法
	 */
	public static Method getClassGetter(Class clazz, String property) throws NoSuchMethodException, SecurityException {
		Assert.assertNotNull(clazz, "class不能为空!");
		Assert.assertNotEmpty(property, "property不能为空!");
		property = property.trim();
		String upper = property.substring(0, 1).toUpperCase() + property.substring(1);
		try {
			Method getter = getClassMethod(clazz, "get" + upper);
			Assert.assertTrue(getter.getReturnType() != Void.class, "getter返回值类型不能为void!");
			return getter;
		} catch (NoSuchMethodException e1) {
			try {
				Method getter = getClassMethod(clazz, "is" + upper);
				Assert.assertTrue(getter.getReturnType() != Void.class, "getter返回值类型不能为void!");
				return getter;
			} catch (NoSuchMethodException e2) {
				Method getter = getClassMethod(clazz, property);
				Assert.assertTrue(getter.getReturnType() != Void.class, "getter返回值类型不能为void!");
				return getter;
			}
		}
	}

	/**
	 * 获取类的方法 (保证返回方法的公开性)
	 * 
	 * @param clazz 类
	 * @param methodName 方法名
	 * @return 公开的方法
	 */
	public static Method getClassMethod(Class clazz, String methodName) throws NoSuchMethodException, SecurityException {
		Assert.assertNotNull(clazz, "class不能为空!");
		Assert.assertNotNull(methodName, "methodName不能为空!");
		try {
			return searchPublicMethod(clazz.getInterfaces(), methodName);
		} catch (NoSuchMethodException e1) {
			try {
				return searchPublicMethod(clazz.getClasses(), methodName);
			} catch (NoSuchMethodException e2) {
				return clazz.getMethod(methodName, new Class[0]);
			}
		}
	}

	// 查找公开的方法 (辅助方法)
	private static Method searchPublicMethod(Class[] classes, String methodName) throws NoSuchMethodException, SecurityException {
		if (classes != null && classes.length > 0) {
			for (int i = 0, n = classes.length; i < n; i ++) {
				Class cls = classes[i];
				if ((cls.getModifiers() & Modifier.PUBLIC) == 1) { // 首先保证类是公开的
					try {
						Method method = cls.getMethod(methodName, new Class[0]);
						if ((method.getModifiers() & Modifier.PUBLIC) == 1) // 再保证方法是公开的
							return method;
					} catch (NoSuchMethodException e) {
						// ignore, continue
					}
				}
			}
		}
		throw new NoSuchMethodException(); // 未找到方法
	}

}
0
0
分享到:
评论
5 楼 javatar 2008-08-05  
估计是javaeye的bug, 你可能是从baidu或站内搜索链入该文章, javaeye通过span来高亮显示关键字, 但与code中html的冲突.
4 楼 bingobird 2008-07-28  
楼主的代码怎么一大堆html标签?没法看
e:
<SPAN class=hilite11>public</SPAN> <SPAN class=hilite7>class</SPAN> <SPAN class=hilite7>Class</SPAN>Utils ...
3 楼 javatar 2008-05-06  
[quote=myhouse0]好文!
是否应该继续查找超类??
是的, clazz.getClasses()需要递归向上找.

[quote=myhouse0]此时怎样执行C.foo()

上面的ClassUtils对public的内部类没有问题的, 因为工具类本身不创建实例. 如:
public abstract class A {

    public abstract String foo();

}

public class B {

    public C getC() {
        return new C();
    }

    public class C extends A {
        public String foo() {
            return "ok";
        }
    }
}

public class Test {

	public static void main(String[] args) {
		try {
			B.C bc = new B().getC();
			System.out.println(ClassUtils.getObjectProperty(bc, "foo"));
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}


public abstract class A {

    public abstract String foo();

}

public class B {

    public static class C extends A {
        public String foo() {
            return "ok";
        }
    }
}

public class Test {

	public static void main(String[] args) {
		try {
			B.C bc = new B.C();
			System.out.println(ClassUtils.getObjectProperty(bc, "foo"));
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}
2 楼 myhouse0 2008-05-04  
例如:
public abstract class A {

	public abstract void foo();

}

public class B {
	public /*static*/ class C extends A {
		@Override
		public void foo() {

		}
	}
}


此时怎样执行C.foo()
1 楼 myhouse0 2008-05-04  
好文!
是否应该继续查找超类??

相关推荐

    ES6 类(Class)的继承(extends)和自定义存(setter)取值(getter)详解

    ES6 类(Class)的继承(extends)和自定义存(setter)取值(getter)详解,博客地址: http://blog.csdn.net/pcaxb/article/details/53784309

    iOS getter setter方法

    在iOS开发中,getter和setter方法是Objective-C和Swift中对象属性访问的重要组成部分。它们用于获取(get)和设置(set)对象的属性值。本文将深入探讨getter和setter的概念、作用以及如何在代码中使用它们。 首先...

    Vue 理解之白话 getter/setter详解

    在深入学习Vue框架的过程中,理解和掌握getter和setter机制是非常重要的。Vue通过响应式原理,将普通的JavaScript对象属性转换成getter和setter,以此来实现数据的双向绑定和状态管理。下面我们将详细地探讨Vue中的...

    eclipse 自动 getter setter 注释

    在Java编程中,getter和setter方法是面向对象设计原则中的封装特性的重要体现。它们用于访问和修改类的私有成员变量,确保数据的安全性。Eclipse是一款广泛使用的集成开发环境(IDE),它提供了丰富的代码自动补全和...

    Eclipse setter/getter 注释成字段的注释

    在Java编程中,Eclipse是一款广泛使用的集成开发环境(IDE),它提供了许多便捷的功能,包括自动生成getter和setter方法。这些方法通常用于封装类的属性,以保护数据并实现对象的访问控制。当我们为类的每个字段添加...

    eclipse中setter、getter注释

    在Java编程语言中,getter和setter方法是面向对象设计的一部分,它们主要用于封装对象的属性,以保护数据并提供访问控制。Eclipse是一款流行的集成开发环境(IDE),它提供了丰富的自动代码生成功能,包括生成getter...

    Does the parameter type of the setter match the return type of the getter?

    在编程领域,尤其是在面向对象的设计中,getter和setter方法是常见的属性访问控制手段。它们用于封装对象的状态,提供对外的接口来读取(getter)和修改(setter)对象的私有变量。标题“Does the parameter type of...

    eclipse修改setter/getter配置

    eclipse修改setter/getter配置,实现自动生成方法时自动抽取属性上的注释:https://blog.csdn.net/yyaijunji/article/details/84639609

    eclipse 自动为getter和setter 添加中文注释

    在Java编程中,getter和setter方法是用于封装对象属性的重要工具。Eclipse作为一个强大的集成开发环境(IDE),提供了丰富的代码生成功能,包括自动为getter和setter添加注释。本篇文章将详细探讨如何在Eclipse中...

    第二十五课 getter设置1

    本节课重点讲解了在 Vuex 中如何设置和使用 getter,以便于从 store 的状态中派生出新的计算状态。 getter 在 Vuex 中的作用类似于 Vue 组件中的计算属性,它们都可以根据依赖的数据进行计算,并且当依赖数据发生...

    Eclipse中setter/getter方法自动添加属性注释

    在Eclipse这款强大的Java开发工具中,为类的属性生成setter和getter方法是常见的操作,这些方法用于封装类的私有变量,确保数据的安全性。然而,为了代码的可读性和维护性,开发者通常会在setter和getter方法上添加...

    C++ getter和setter生成器

    c++的成员变量的get和set生成器,简单易用。

    java普通类编译成json但只是当前类的有getter、setter方法的版本

    这个场景中提到的是将一个Java类编译成JSON,但只包含那些具有getter和setter方法的属性。这样的转换有助于减少JSON输出中的冗余信息,只保留与业务逻辑相关的数据。下面我们将深入探讨这个过程。 首先,我们需要...

    Go-go-getter-一个Go库用于从各种来源使用URL下载文件或目录

    【标题】"Go-getter: 一个Go库用于从各种来源使用URL下载文件或目录" 在Go编程语言中,开发人员经常需要从互联网上下载文件或目录,这在构建自动化工具、部署流程或者数据获取应用时尤其常见。"Go-getter"是一个...

    java简便方法引入getter/setter/tostring等方法

    java 的eclipse或idea等 定义变量时 直接引入lombok.jar包 在类外部 引入@AllArgsConstructor @NoArgsConstructor @Data 简便方法引入getter/setter/tostring等方法

    idea getter/setter插件

    **IntelliJ IDEA Getter/Setter 插件详解** 在Java编程中,getter和setter方法是对象属性访问的重要组成部分,它们提供了封装和数据访问控制。为了提高开发效率,IntelliJ IDEA,一款广受欢迎的Java集成开发环境...

    自动生成带注释的getter和setter方法(注释)插件

    在编程领域,尤其是在Java开发中,getter和setter方法是面向对象设计的重要组成部分,它们用于封装对象的属性,确保数据的安全性。然而,手动编写这些方法可能会耗费大量时间。为了解决这个问题,开发者们通常会利用...

    jfinal model自动生成工具,自带setter与getter

    标题中的“jfinal model自动生成工具,自带setter与getter”指的是一个专为JFinal框架设计的模型类(Model)自动生成工具。JFinal是基于Java的轻量级Web开发框架,它提倡的是“约定优于配置”的开发理念,旨在提高...

    自动生成带注释的getter和setter方法(Intellij、AndroidStudio插件).zip

    标题中的“自动生成带注释的getter和setter方法(Intellij、AndroidStudio插件)”指的是在编程过程中,开发者可以利用特定的插件自动化生成Java Bean模式中的getter和setter方法,并且这些方法会带有注释。...

    Intellij IDEA 插件,可以将实例变量上的JavaDoc暴露到Getter和Setter的定制模版中

    本篇将详细讲解一个名为"Intellij Plugin Expose Javadoc"的插件,它能够帮助开发者将实例变量上的JavaDoc注释自动应用到对应的Getter和Setter方法中,从而提高代码的可读性和维护性。 JavaDoc是一种在Java源代码中...

Global site tag (gtag.js) - Google Analytics