论坛首页 Java企业应用论坛

Object数组到泛型数组转换的伪解决方案

浏览 15919 次
精华帖 (11) :: 良好帖 (0) :: 新手帖 (2) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-01-31   最后修改:2009-01-31

我只是提供一个思路,并没有让你照搬,你用这种方法需要改一下设计

 

public abstract class Filter<T> {

	protected Class clazz = (Class)((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
	
	public boolean check(Object obj){
		boolean flag = false;
		if(clazz.isInstance(obj) && filter(obj))
			flag = true;
		return flag;
	}
	
	public abstract boolean filter(Object obj);
}
 

0 请登录后投票
   发表时间:2009-01-31   最后修改:2009-01-31
把Filter的check()改成where()看起来会更符合SQL标准,呵呵
0 请登录后投票
   发表时间:2009-01-31  
public static void main(){
}
0 请登录后投票
   发表时间:2009-01-31   最后修改:2009-01-31
一个我通常用的方法是把Class这个对象传进去,就是说需要加一个方法为
Class<T> getDataType()


然后通过

Array.newInstance(getDataType(), 0);


来创建一个数组
0 请登录后投票
   发表时间:2009-01-31  
javatar 写道
把Filter的check()改成where()看起来会更符合SQL标准,呵呵

 

我是尽量参照楼主原来的命名

0 请登录后投票
   发表时间:2009-02-01  
wendong007 写道

javatar 写道
把Filter的check()改成where()看起来会更符合SQL标准,呵呵
&nbsp;
我是尽量参照楼主原来的命名

吼嘞吼嘞,已经啊补充过嘞……

的确where更符合品鉴的口味。呵呵,采纳了。
0 请登录后投票
   发表时间:2009-02-01  
wendong007 写道
其实直接返回List类型就可以了,没必要搞得那么复杂,你这里的类型检查用 instanceof 就好,异常不是那么用的
不过我觉得你的想法还是不错



同意wendong007的看法。

这里的类型不安全在于设计上的缺陷,有两种解决方法:

  • 将DataBase本身设计成泛型,这时DataBase只持有某种类型的对象,就像Collection类型
  • 如果想使DataBase能够容纳任何对象,原来的方法最好加上一个Class<T>类型的参数代表要过滤的对象类型。

public interface DataBase 

    public <T> T[] select(Filter<? super T> filter, Class<T> clazz); // 可以将Filter<T>改成Filter<? super T>
    public void insert(Object obj);  // 这里没有必要使用泛型,因为T只在一个地方(参数或返回值)被使用
    public int update(Filter<T> filter, Class<T> clazz, Updater<T> handler);  // 按照这种设计,我总觉得Updater没有必要设计成泛型
    public int delete(Object obj);  // 同样,这里也没有必要使用泛型
}

 

下面这种捕获异常的方式实在不敢恭维,异常不是这么用的。一个副作用是它捕获了filter的异常。

         try { 
             T t = (T) obj; 
             if (filter.where(t)) c.add(t); 
         } catch (Exception ex) { 
             continue; 
         }

0 请登录后投票
   发表时间:2009-02-01  
同意wendong007的看法。

泛型的出现是为了改进使用object类型时转换类型的效率。
这么的写法不如直接用实际的类型或是Object[]和List来的好一些。
0 请登录后投票
   发表时间:2009-02-01   最后修改:2009-02-01
Filter<T>接口的实例, 如果实现了多个接口且无法保证顺序时, 会造成ClassCastException.

即 FilterImpl implements A<String>, Filter<T>, B<String>
楼主代码里写死 types[0], 会给以后重构或者其他因素的代码改动, 带来风险, 欠妥.

建议, ((Class<?>)types[0].getRawType() ==  Filter.class) + 遍历types

0 请登录后投票
   发表时间:2009-02-01  
kimmking 写道
同意wendong007的看法。

泛型的出现是为了改进使用object类型时转换类型的效率。
这么的写法不如直接用实际的类型或是Object[]和List来的好一些。

Java里泛型的出现不是为了源码“更安全”么?执行效率应该没有多少区别才对。你看对这样的一个测试代码:
import java.util.ArrayList;

public class TestGeneric {
    public static void main(String[] args) {
        foo1();
        foo2();
    }

    private static void foo1() {
        ArrayList list = new ArrayList();
        MyObject obj = new MyObject();
        list.add(obj);
        MyObject objref = (MyObject)list.get(0);
    }

    private static void foo2() {
        ArrayList<MyObject> list = new ArrayList<MyObject>();
        MyObject obj = new MyObject();
        list.add(obj);
        MyObject objref = list.get(0);
    }
}

class MyObject { }

其中的foo1()和foo2()编译出来是完全一样的,都是这样:
   0:	new	#4; //class java/util/ArrayList
   3:	dup
   4:	invokespecial	#5; //Method java/util/ArrayList."<init>":()V
   7:	astore_0
   8:	new	#6; //class MyObject
   11:	dup
   12:	invokespecial	#7; //Method MyObject."<init>":()V
   15:	astore_1
   16:	aload_0
   17:	aload_1
   18:	invokevirtual	#8; //Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
   21:	pop
   22:	aload_0
   23:	iconst_0
   24:	invokevirtual	#9; //Method java/util/ArrayList.get:(I)Ljava/lang/Object;
   27:	checkcast	#6; //class MyObject
   30:	astore_2
   31:	return

注意在标号为27的那条指令,那个就对应着foo1()的强制类型转换,而foo2()使用了泛型之后隐式的包含了这个操作。

我也觉得干脆不返回数组比较好。其实很多时候数组用起来都很尴尬,与Iterable<E>也不兼容。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics