离弦之Ray

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  55 Posts :: 0 Stories :: 33 Comments :: 0 Trackbacks

#

Interfaces

有两种主要的Collection Types
java.util.Map
java.util.SortedMap
java.util.Collection
java.util.Set
java.util.List
java.util.SortedSet


Implementations

List的三种实现

java.util.Vector
java.util.ArrayList
java.util.LinkedList

三者的异同
三者都是有序的,一般就是加入的次序。

        VectorArrayList内部都是用数组实现的,可以把它们想象成为一个数组。当容量不够的时候,就新建一个更大的数组,然后把现在这个数组中的所有元素都拷过去。可以想象这种实现可以很方便的直接取出你要的某个元素而不用遍历。但是如果在中间删除或者插入元素,效率就不高了。甚至每次扩容的时候,都是很影响效率的时候。

        VectorArrayList的区别就是Vector是线程安全的,但ArrayList不是。因为实现线程安全是有代价的,如果应用中不需要线程安全,那么就用ArrayList,如果需要线程安全那就一定要用Vector

至于java中的LinkedList,其实在数据结构中就是双向链表。插入和删除元素都很快,但是要查找一个元素就慢了。有失必有得,如何选择,就看应用的情况了。


MapSortedMap的几种实现

java.util.HashTable
java.util.HashMap
java.util.IdentityHashMap
java.util.WeakHashMap

        以上四种都是无序的。HashTableHashMap的区别是HashTable是线程安全的而HashMap不是,这个关系有点像VectorArrayList

        IdentityHashMap首先它是一个HashMap,不同的是,它不是根据equal()函数来判断是否重复,只要不是同一个对象,哪怕这两个对象的数据都是一样的,那么就可以add进来。


java.util.LinkedHashMap

java.uil.TreeMap

        以上两种是有序的Map,可以进行iterate,当然这是要付出效率代价的。两者不同之处,由名字便可知道,LinkedHashMap用链表来维护这个次序,而TreeMap是用二叉树来维护这个次序。

SetsSortedSets的几种实现

java.util.HashSet
java.util.LinkedSet
java.util.TreeSet

由名字就可知道什么意思了,不多说了

Collection的选择

        需要通过一个key找到一个元素吗?
        Yes,那就用Map
        No,那就用Collection

       如果选择了一个Collection,允许重复元素吗?
       Yes,那就用List
       No,那就用Set

       然后就是决定要不要Sorted...这个就比较难决定了。
       如果常常要sort,那就直接选择sorted的类型
       如果偶尔或者根本不需要sorted,那就选择普通类型,需要sort的时候先拷到sorted的类型中sort一下。

三种Iterators

java.util.Enumeration

这个基本被Iterator替代掉了,但在某些场合,比如J2ME中还可能用到。

java.util.Iterator

用的最广泛

java.util.ListIterator

双向的Iterator,必须用在实现ListCollection上面。


PS很多Collection提供的是Fail-Fast Iterators,就是在iterater的时候,这个Collection是不能被更改的,否则就会报出ConcurrentModificationException在多线程环境下面尤其要注意。


posted @ 2007-10-26 21:14 离弦之ray的技术天空 阅读(750) | 评论 (0)编辑 收藏

Final constrants

       在编程中,用final变量来声明一些常量,这样就不用在每个用到这个常量数字的地方打入令人厌烦的复杂数字(比如PI),只要打入这个常量名字就行了。这大家都知道,可是要注意,这种常量是在编译阶段才被替换的(所谓替换,就是把程序中用到这个常量名字的地方,用常量本身来替代)。那意味着,如果其它类用到了这个常量,如果常量的值发生了更改,那用到这个常量的类必须重新build一下,否则那个类里还是以前的值。

        如果在程序中你用到了private final static常量,并且只在某一个方法内用到,那么你应该把它的声明移到方法以内。如果被两个以上的方法用到,那么还是留在类声明里。

移入方法内部后,不用写private关键字,而且程序看起来比较简单。


Final Variables

首先写个例子

public static String someMethod(final String environmentKey){

           final String key = "env." + environmentKey;

          System.out.println("Key is :" + key);

           return (System.getProperty(key));

}

        在method中声明的final变量和常量是不同的,不同之处在于method-scoped final variables are variable。每次进入这个方法内部,这个变量就被初始化一次。当然,这些变量都是运行时进行替换,而不像常量是在编译时进行替换。


Final Parameters

将方法的parameters声明成final,可以防止,在方法体内部这个参数被篡改。很好的best practice


Final Collections

        public final static Set VALID_COLORS; 这句语句是不是声明了一个final set?答案是NO。这只是声明了一个final引用,也就是VALID_COLORS这个引用不能被更改。

        如果重新声明一个引用指向这个对象,那么这个对象还是能够更改的,所以这并不是一个final set。那么怎样做才能真正得到一个final set呢?

public final static Set VALID_COLORS;

static{

Set temp = new HashSet();

temp.add(Color.red);

temp.add(Color.blue);

...

VALID_COLORS = Collections.unmodifiableSet(temp);

}

        在实现自己的unmodifiable collections factory的时候,除了要实现Collectionseriallizable接口以外,对于Collection中定义的写操作,要重载。方法体中可以简单地抛出UnsupportedOperationException异常。

Instance-Scoped Variables

        说白了,就是那些在对象被实例化的时候才被初始化的属性,并且是不能被修改的。那么就把他声明成final吧。

exprivate final Date creationDate =

Calendar.getInstance(TimeZone.getTimeZone("GMT")).getTime();

这么做的话,就可以防止误操作,改变这个本来不应该变的值。


Final Classes

ex:

public final class SomeClass(){

//...Class contents

}

        这样的class 不能被继承。

        还有一种方法实现,就是把它所有的构造函数都改成private的。

        这在设计模式中sigleton模式中见过,但这就限制了这个类的重用,所以取个折衷,可以把构造函数声明成protected的。


Final Method

这个很熟悉了,一个类中的某个方法如果被声明成final的,那么这个类的子类是不能override这个方法的。


Conditional Complilation

        编程的时候我们常常会使用System.out.println(".....");来显示一些程序的运行情况,但在真正交付的时候,我们并不希望这些语句被编译到class文件里面去。

        一个做法是所有这种类型的语句前面加上一个if(booleanParameter),然后通过设置这个booleanParameter来实现要不要运行这些语句,编译器在编译的时候如果发现if里面的语句不可达,那么会将这些程序代码直接去掉。

        疑问就是这些booleanParameter放在哪里比较好和方便。作者给出的建议是在包中专门建一个类,里面存放这些静态的boolean常量,当然,命名的时候要仔细。名字要指出用在哪里。

posted @ 2007-10-23 14:07 离弦之ray的技术天空 阅读(292) | 评论 (0)编辑 收藏

1.Java没有指针?NoJava只是没有针对指针的算法。引用其实已经包含了指针。

2.RTTI——Runtime type identification,作用就是告诉你整个object是属于什么类型的。最常用的是getClass()方法。

3.只在for循环中用到的变量,就在for循环中声明和分配,不用担心会循环分配内存。

比如:

for(int i =0;i<10;i++){

String s = a[i];

}

s并不会循环new,编译器会处理,让它只在第一次分配内存。
前面编程,我还特意把s移到外面去呢……汗啊

4.switch语句中,如果在default语句中加一个break是完全没有用的。因为在那个地方的break根本就不会被执行。

5.continue

for(int idx=0;idx<1000,idx++){

if(idx==555){continue;}

}

在这个例子中,循环仅仅跳过了555,如果程序中遇到类似要跳过某个点的情况,可以这么利用continue,会减少很多代码。


6.chaining constructor

活用super()、this()等,来缩减构造函数的复杂度。


7.private for attributes

   public for public methods

   protected for helper methods


8.In Java, instances of the same class are friends and give unrestricted access to all of their properties and methods.

比如

if((obj.value==5)&&(this.value==5)){

obj.value=25;

}

这里面跳过了setter方法,直接给属性赋值,这是很危险的做法。解决的方法是无论什么方法给对象中的属性赋值都要通过setter方法。


9.对于问题代码要尽量用throw exception告知用户,因为有时候不知道代码的执行环境,如EJB等等,很多环境都是没有Console的,若是简单的System.out.println 可能解决不了问题。

posted @ 2007-10-22 10:15 离弦之ray的技术天空 阅读(377) | 评论 (0)编辑 收藏

 

JDBC 主要有两种方法

DriverManager机制:java.sql核心API

DataSource机制:javax.sql可扩展API

DriverManager机制:

stetp1:注册驱动程序

1)隐式注册Class.forName("JDBCDriverName");

2)显示注册DriverMnager.registerDriver(new JDBCDriverName());

step 2:建立数据库连接

Connection conn = DriverManager.getConnection(URL,username,password);

//其中URLjdbc:driver:databasename

step3:SQL操作

DataSource机制

step1:查询数据源对象

Context ctx = new InitialContext();

DataSource ds = (DataSource)ctx.lookup(DataSourceJNDIName);

step2:获取数据库连接

Connection con = ds.getConnection();

step3SQL操作

SQL操作

1)使用Statement

      Statement stmt = con.createStatement();

      stmt.executeUpdate("SQL语句");

      stmt.close();

2)使用PreparedStatement

      例子

      PreparedStatement psmt = conn.preparedStatement("INSERT INTO employee                                                  VALUES(?,?,?)");

       psmt.setString(1,"Benjamin");

       psmt.setString(2,"France");

       psmt.setInt(3,55);

       int opNum = psmt.executeUpdate();

       还可以批量处理

       psmt.setString(1,"Benjamin");

       psmt.setString(2,"France");

       psmt.setInt(3,55);

       psmt.addBatch();

       psmt.setString(1,"Rob");

       psmt.setString(2,"America");

       psmt.setInt(3,56);

       psmt.addBatch();

       int [] updateCounts = psmt.executeBatch();

关于ResultSet

ResultSet rs = stmt.executeQuery("SQL");

next()——移到下一行,如果没有了则返回false。常常放在while(rs.next)用来循环取数据

getString(String ColumnName)

absolute(int row)

beforeFist()

isAfterLast()

isBeforeFirst()

isFirst()

isLast()

refreshRow()

关于元数据

所谓元数据就是描述数据的数据,这里当然指列名等等信息了

ResultSetMetaData rsmd = rs.getMetaData();

rsmd.getColumnCount();

rsmd.getColumnName(index);

posted @ 2007-10-21 18:41 离弦之ray的技术天空 阅读(311) | 评论 (0)编辑 收藏

        作为j2ee小菜鸟,初次遭遇JNDI还是在大三的时候,当时学院搞j2ee实训,我们还没搞清楚servletJSP就依葫芦画瓢的搞Struts了。所以在配置mysqlds.xml的时候完全不知道在配置DataSource,现在知道这就是在使用JNDI。网上查了几个网页,拼拼凑凑,模模糊糊地理解了:

        JNDI——Java Naming and Directory InterfaceTM

       直接翻译就是Java命名和目录接口,实现这个接口,提供的是一个服务,这是个什么样的服务呢?

       首先在连接数据库的时候(我使用的是mysqljboss4.0),我们会用到Context这个类,context是一套name-to-object的绑定,可以理解为层次或目录,他可以包括下一层subContext。在使用命名和目录服务时获得initial context 是对整个名字空间操作的入口。

       针对Datasource而言,说白了,就是给你的数据库连接(注意,是数据库连接Connection这个对象,不是数据库)起个简单易懂的名字,你在程序中直接调用这个名字,就得到这个连接的对象,而具体的生成和管理就靠服务器了。

      通常会形成一个connection pool,动态的来管理这些对象以节省资源。

      这样,如果项目移植到其它数据库或者服务器什么的,只要配置服务器就行了。配置比如这个连接用什么JDBC驱动啊,用户名和密码啊等等。程序代码可以不作改动。这里的DataSource不一定就是数据库连接,还可以是其它比如文件连接等等。


     其实EJB都是靠JNDI得到EJB objectreference的,具体的机理是不太了解,不过就是那个意思,初学者这样理解应该就够了。


    今天郁闷了半天,在jboss里面配置JNDI DataSource,想看看如果外面直接用普通的Java工程能不能连接数据库,答案是否。后来想通了。服务器提供JNDI服务所使用的类,这个普通的工程又不知道在哪,当然搞不起来。而Web工程和EJB工程因为发布到服务器下面的目录的,所以能使用JNDI服务。


    这是我的理解,请各位高手指点。


   至于JBoss等等服务器怎么配置,网上搜一下,有很多牛人总结的,这里就不重复了。


posted @ 2007-10-15 21:54 离弦之ray的技术天空 阅读(319) | 评论 (0)编辑 收藏

仅列出标题
共11页: First 上一页 2 3 4 5 6 7 8 9 10 下一页 Last