- 浏览: 77660 次
- 性别:
- 来自: 上海
最新评论
-
rockythd:
视界这个概念终于搞清楚了,谢谢!
Java关于Scala的“视界(view bound)”的模拟 -
regular:
写了一个更通用的方法:ObjectUtils.cast。目的是 ...
Java关于Scala的“视界(view bound)”的模拟 -
lrztiancai:
谢谢分享。正在找这个!
Parsley+SpiceLib 2.4 Developer Manual -
kraft:
第二版什么时候出啊
Programming In Scala 翻译 -
justjavac:
xpf7622 写道haixu.huang@live @前的名 ...
Programming In Scala 翻译
闲来无事,想要用目前的Java技术模拟一个对象数据库。最初只是停留在很简单的构想,单用户的,本地的,仅仅是为了实现一些纯对象化的数据库操作:
public interface DataBase { public <T> T[] select(Filter<T> filter); public <T> void insert(T t); public int update(Filter<T> filter, Updater<T> handler); public <T> int delete(T t); }
其中,Filter和Updater分别是两个接口,处理查询子句和更新子句。
public interface Filter<T> { public boolean where(T obj); } public interface Updater<T> { public void set(T obj); }
这么设计的目的是以一种对象化的方式处理数据,把数据库的操作和业务流程无缝的结合在一起。我说过,这只是我的一个练习,因此请仅把它看成是练习就好。数据库的对象容器用了一个泛型的List,里面可以包含任何对象。
然而在select方法的时候,碰到了一些问题。因为它要返回的是T[]类型结果,而由于T是泛型,在List 的toArray时,仅能生成Object[]类型的数组,与需求有差异。
//... @SuppressWarnings("unchecked") public <T> T[] select(Filter<T> filter) { Collection<T> c= new ArrayList<T>(); for (Object obj : pool) { try { T t = (T) obj; if (filter.where(t)) c.add(t); } catch (Exception ex) { continue; } } // 到现在都OK return c.toArray(); // 不OK,返回类型为Object[],与结果不符 return (T[]) c.toArray(); // 不OK,仍返回 Object[],ClassCastException return c.toArray(new T[0]); // 不OK,编译错误。 } //...
首先要解释一下为什么return c.toArray(new T[0]); 不能通过编译。因为据Java官方所说,为了向旧版本兼容,Java的泛型只是存在于编译期,其目的是编译期的源代码正确性校验,变成了.class之后所有泛型内容全部被抛弃。所以,new T[0]这种写法在运行期是不可能有意义的,因为没有T的具体定义。
加@SuppressWarnings("unchecked")的原因是T t = (T) obj;语句。没有想到更好的办法做泛型的类型比较,用这种方法最直接。不过可能会产生ClassCastException,所以一旦发生转换错误,只是简单地继续处理下一个元素。若有其它解决方案也请能不吝赐教,这里谢过。
现在,回到问题上来:怎么实现这个泛型的数组转换呢?
我这里有一个伪解决方案。就是从结果集合中取一个值出来,然后创建这个值类型的数组,见下:
@SuppressWarnings("unchecked") public <T> T[] select(Filter<T> filter) { Collection<T> c; //... Iterator<T> it = c.iterator(); if (it.hasNext()) { T[] tt = (T[]) Array.newInstance(it.next().getClass(), c.size()); return c.toArray(tt); } else return null; }
说这是个伪解决方案的原因是集合中的值并不就等于是T,有可能是T的子类。若集合中所有元素都是一个类别倒还好说,怕只怕有些元素又是子类的子类(孙类)。那么假设碰巧集合中第一个拿到的就是孙类,那么tt实际是孙类的数组,这样对于包含子类对象的集合执行toArray操作的时候就会出现ArrayStoreException。
好了,在暂时不考虑这个“伪”字的情况下,这里举个使用的例子:
public static void main(String[] args) { DataBase db = new DataBaseImpl(); db.insert("Hello, "); db.insert(" this "); db.insert(new Integer(3)); db.insert("world!"); String[] ss = (db.select(new Filter<String>() { @Override public boolean where(String obj) { return (obj.trim().length() > 4); } })); for (String s : ss) System.out.println(s); }
======== 补充========
春节休假在家,偶尔看了一下论坛。结合下面的评论并思考了一下,目前采用通过传入的Filter获得泛型类的方法:
import java.lang.reflect.*; import java.util.*; public class Container { private Collection<Object> container = new ArrayList<Object>(); public void add(Object obj) { container.add(obj); } @SuppressWarnings("unchecked") public <T> T[] select(Filter<T> filter) { Class clazz; Type[] types = filter.getClass().getGenericInterfaces(); if (types != null && types.length > 0) { clazz = ((Class) ((ParameterizedType) types[0]) .getActualTypeArguments()[0]); } else return null; Collection<T> c = new ArrayList<T>(); for (Object o : container) { if (clazz.isInstance(o) && filter.where((T) o)) c.add((T) o); } T[] tt = (T[]) Array.newInstance(clazz, c.size()); return c.toArray(tt); } public static void main(String[] args) { Container c = new Container(); c.add("Hello"); c.add("world"); c.add("I"); c.add("love"); c.add("you"); c.add(new Integer(4)); c.add("ever"); String[] list = c.select(new Filter<String>() { public boolean where(String s) { return (s.length() > 3); } }); for (String s : list) System.out.println(s); } } interface Filter<T> { boolean where(T t); }
评论
怎么有脱裤子放P感觉。。。素质素质。。
够粗的。
其实直接返回List类型就可以了,没必要搞得那么复杂,你这里的类型检查用 instanceof 就好,异常不是那么用的不过我觉得你的想法还是不错
呵呵,试试看吧。
if (obj instanceof T) ... // 不行,因为T在运行时被erasure为Object
不过我觉得你的想法还是不错
不过有个问题啊,db.insert(new Integer(3)); Integer没有length方法就会抛出异常,除非在用db的时候强制指定范型 DataBase<String> db = new DataBaseImpl<String>(); 否则check里的方法很可能执行不了啊
是这么回事,因为最初的设定就是DataBase能够容纳任何种类的对象。所以原则上,所有的对象都应该能被装在DataBase的实例对象内。等到了要select的时候,因为Filter也是泛型的,所以待检测的对象必然是要符合这个的才能被拣出来。
所以你可以看到在select函数中首先做了一次强制转换。转换失败的不会被拣出来,从catch(Exception) { continue; }走了。
DataBase<String> db = new DataBaseImpl<String>();
否则check里的方法很可能执行不了啊
发表评论
-
把Spring容器中的bean绑定到通过代码创建的对象
2012-04-26 16:17 2269Spring提供了对配置中创建对象的字段实例注入。但如果是通过 ... -
动态注册消息类型及处理函数
2011-10-01 15:56 994内容略。参见代码演示。 -
代码实例
2011-02-14 17:17 1011代码实例文件 -
如何在类外部调用被子类覆盖的父类方法
2011-01-20 14:46 1892题目比较绕。以下用一个简单的例子说明: public cl ... -
SWT应用的开发实例:没有使用到OSGi
2011-01-14 11:27 1521添加音效,以及中奖名单回看功能。 SWT应用一枚。具体方法见 ... -
运行期代码问题检查技术的研究
2010-11-29 13:30 1138以下用我之前代码中的一个bug作为说明,解释如何实现代码在运行 ... -
代码潜在故障的动态分析
2010-11-16 12:24 1503引子 大家都听说过FindBugs的大名。这是一款静态代码分析 ... -
健壮的、便捷的、异步的SocketChannel实现
2010-04-27 10:34 8375Socket通信比较常见的问题有如下几种: 1、设置收发超时; ... -
打算研究学习一下OSGi和Equinox
2010-02-10 11:26 1141看到一本很直接讨论这个题目的书,不过要等到3月1日才出来。 ... -
关键应用服务的集群技术模拟
2010-01-08 14:41 1077集群技术,也就是俗称的Cluster,是为了保证某种应用不间断 ... -
JarSpur 检查引用包归属的小工具
2009-12-25 17:31 1081图形化的界面,允许你导入任意多的在项目中可能需要的Jar包。 ... -
class.getResourceAsStream()与ClassLoader.getResourceAsStream()的区别
2009-11-11 17:33 2047在jar包里获得流形式的资源有两种方法,一个是Class.ge ... -
MultiKeyedMap方案的实现
2009-11-10 11:55 3752方案背景 所谓“MultiKey ... -
Java2D: 硬件加速 - 第二部分 - 缓冲策略:Buffer Strategies
2009-11-02 12:52 2936原文地址:Java2D: Hardware ... -
Java2D: 硬件加速 - 第一部分 - 非恒定图像类:Volatile Image
2009-10-30 16:19 4292原文地址:Java2D: Hareware Accelerat ... -
自建的MiniChart库,目前实现了点图、折线图、柱状图和饼图
2009-07-15 11:08 1231花了大约一个星期时间做的MiniChart库。 由于现在的免费 ... -
BM方案模式匹配的Java代码实现
2009-06-17 13:47 1566速度还算快,例子里比较的文件一共371个,3,293,472字 ... -
对于经典模式匹配算法的一些改动
2009-06-12 12:44 1485从一个很长的字符串(或者数组)中,查找某个子串(模式串)是否存 ... -
读写进程的互斥锁
2009-03-16 15:27 1588以下的代码完成了对某个资源的读写互斥锁,具体说明如下:1. 若 ...
相关推荐
- **Object数组到泛型数组转换的伪解决方案**:探讨了Java中由于类型擦除导致的泛型与非泛型之间的转换问题,以及一些常见的规避策略。 - **Java线程死锁与内存溢出**:深入讲解了Java多线程环境下可能导致的死锁...
在C#编程语言中,泛型是类型系统的一个强大特性,它允许我们在编写代码时定义通用的数据结构和方法,而不必指定具体的...在实际开发中,结合泛型和数组的特性,可以构建出适应各种数据结构和算法需求的高效解决方案。
本文将详细讨论如何在Java中进行List与数组之间的转换,并分析转换过程中可能出现的问题及解决方案。 首先,让我们看看如何将List转换为数组。Java的List接口提供了一个`toArray()`方法,但需要注意的是,这个方法...
更好的解决方案是使用一个通用的数据类型`object`: ```csharp public class Stack { private object[] m_items; public object Pop() { /* ... */ } public void Push(object item) { /* ... */ } public ...
本文将详细介绍 C# 泛型中的数据类型判定与转换,并提供了一些实用的解决方案。 数据类型判定 在 C# 中,数据类型可以分为值类型和引用类型。值类型包括整型家族(int、byte、char、short、long 等)、浮点家族...
#### 泛型问题陈述与解决方案 在未使用泛型的情况下,设计一个能处理多种数据类型的数据结构(如堆栈)往往需要依赖于`object`类型,这虽然提供了灵活性,但也带来了性能损耗和类型安全性的隐患。例如,当使用堆栈...
在编程领域,尤其是在C#语言中,数组和ArrayList是两种常用的数据存储结构。...在实际编程中,我们应根据需求选择最合适的解决方案,同时,随着技术的发展,不断学习新的数据结构和算法,以适应不断变化的编程环境。
4. `void CopyTo(object[] array, int arrayIndex)`:将集合中的元素复制到一个数组中。 5. `int IndexOf(object value)`:返回指定元素在集合中的索引位置。 6. `void Insert(int index, object value)`:在指定...
为了解决这个问题,一种简单的解决方案是将数组类型更改为`Object`,使得可以存储任意类型的对象。 #### 二、使用`Object`作为通用类型 修改后的`MyArrayList`类如下所示: ```java public class MyArrayList { ...
项目中包含的`.git*`文件与Git版本控制有关,`.editorconfig`是代码风格配置,`Directory.Build.props`是MSBuild项目的属性设置,`Peachpie.sln`是Visual Studio解决方案文件。这表明项目使用Git进行版本控制,并且...
《深入理解Fastjson:解析与应用》 Fastjson,由阿里巴巴开发并维护的一款高效、功能强大的JSON库,广泛应用于Java编程环境中。...无论是简单的对象转换,还是复杂的数据操作,Fastjson都能提供简洁而强大的解决方案。
本文将针对一些常见的Java错误进行归纳总结,并提供相应的解决方案,以帮助开发者提高开发效率。 #### 一、NullPointerException (空指针异常) **描述**:当试图访问一个空对象的属性或方法时会抛出此异常。这是...
总之,Gson是一个功能强大且易用的Java JSON库,无论是在简单的数据转换还是复杂的JSON操作中,都能提供高效的解决方案。在Java项目中,特别是涉及到与JSON数据交互时,Gson是一个不可或缺的工具。通过引入"gson2.7....
总结来说,gson-2.8.5.jar是一个强大的JSON处理库,它简化了Java应用程序与JSON数据的交互,提供了高效、灵活且类型安全的解决方案。无论你是进行Web开发、移动开发还是服务器端开发,Gson都能成为你处理JSON数据的...
如上所述,使用`Arrays.asList()`可以快速将数组转换为列表。 需要注意的是,这两种方法都需要确保你的实体类`UserPosition`有对应的JSON字段,以便于JSON库进行映射。此外,为了使Spring MVC能够正确处理JSON,你...
这个库的设计目标是提供高性能、轻量级的解决方案,使得开发者能够高效地解析、生成JSON格式的数据。在"rapidjson的使用封装"这一主题中,我们将深入探讨如何有效地利用Rapidjson,并解决在处理字符编码转换时可能...