本文鏈接: http://blog.csdn.net/jrq/archive/2005/10/27/517428.aspx
正文:
1. 為了方便按列作外循環(huán),想把ArrayList構(gòu)造成一個(gè)二維數(shù)組,如下:
......
ArrayList result=GetResult();
int n=result.size();
String[][] myArray=new String[n][]; //定義二維數(shù)組
for (int i=0;i<n;i++) //構(gòu)造二維數(shù)組
{
ArrayList tempArray= (ArrayList)result.get(i);
myArray[i]=(String[])tempArray.toArray();
}
......
程序可以編譯通過(guò)。
但在運(yùn)行到myArray[i]=(String[])tempArray.toArray()時(shí),出現(xiàn)java.lang.ClassCastException的錯(cuò)誤,很奇怪。
花了一晚上時(shí)間,查了N多資料,總算搞定了。現(xiàn)把問(wèn)題記錄下來(lái),以備參考。
2. 此事從頭說(shuō)起。
ArrayList類(lèi)擴(kuò)展AbstractList并執(zhí)行List接口。ArrayList支持可隨需要而增長(zhǎng)的動(dòng)態(tài)數(shù)組。
ArrayList有如下的構(gòu)造函數(shù):
ArrayList( )
ArrayList(Collection c)
ArrayList(int capacity)
如果調(diào)用new ArrayList()構(gòu)造時(shí),其默認(rèn)的capacity(初始容量)為10。
參見(jiàn)ArrayList源碼,其中是這樣定義的:
public ArrayList() {
this(10);
}
默認(rèn)初始化內(nèi)部數(shù)組大小為10。為什么是10?不知道。可能SUN覺(jué)得這樣比較爽吧。
程序編譯后執(zhí)行ArrayList.toArray(),把ArrayList轉(zhuǎn)化為數(shù)組時(shí),該數(shù)組大小仍為capacity(為10)。
當(dāng) 裝入的數(shù)據(jù)和capacity值不等時(shí)(小于capacity),比如只裝入了5個(gè)數(shù)據(jù),數(shù)組中后面的(capacity - size)個(gè)對(duì)象將置為null,此時(shí)當(dāng)數(shù)組強(qiáng)制類(lèi)型轉(zhuǎn)換時(shí),容易出現(xiàn)一些問(wèn)題,如java.lang.ClassCastException異常等。
解決辦法是:在用ArrayList轉(zhuǎn)化為數(shù)組裝數(shù)據(jù)后,使用trimToSize()重新設(shè)置數(shù)組的真實(shí)大小。
3. 本例修改后的代碼修如下,可順利運(yùn)行:
for (int i=0;i<n;i++) //構(gòu)造二維數(shù)組
{
ArrayList tempArray= (ArrayList)result.get(i);
myArray[i]=(String[])tempArray.toArray(new String[0]); //注意此處的寫(xiě)法
}
看看下面這些也許就明白了--
ArrayList.toArray()之一:
public Object[] toArray() {
Object[] result = new Object[size];
System.arraycopy(elementData, 0, result, 0, size);
return result;
}
返回ArrayList元素的一個(gè)數(shù)組,注意這里雖然生成了一個(gè)新的數(shù)組,但是數(shù)組元素和集合中的元素是共享的,Collection接口中說(shuō)這個(gè)是安全的,這是不嚴(yán)格的。
下面的例子演示了這個(gè)效果。
ArrayList al=new ArrayList();
al.add(new StringBuffer("hello"));
Object[] a=al.toArray();
StringBuffer sb=(StringBuffer)a[0];
sb.append("changed"); //改變數(shù)組元素同樣也改變了原來(lái)的ArrayList中的元素
System.out.println(al.get(0));
這里不要用String來(lái)代替StringBuffer,因?yàn)镾tring是不可變的。
ArrayList.toArray()之二:
public Object[] toArray(Object a[]) {
if (a.length < size)
a = (Object[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
這個(gè)方法有可能不需要生成新的數(shù)組,注意到如果數(shù)組a容量過(guò)大,只在size處設(shè)置為null。
如果這個(gè)數(shù)組a足夠大,就會(huì)把數(shù)據(jù)全放進(jìn)去,返回的數(shù)組也是指向這個(gè)數(shù)組,(數(shù)組多余的空間存儲(chǔ)的是null對(duì)象);要是不夠大,就申請(qǐng)一個(gè)跟參數(shù)同樣類(lèi)型的數(shù)組,把值放進(jìn)去,然后返回。
4. 網(wǎng)上的資料一:
public String[] getPlatformIDList()
{
Vector result = new Vector();
try
{
Statement stmt = conn.createStatement();
String sql = "SELECT PlatformID FROM Platform";
rs = stmt.executeQuery(sql);
while(rs.next())
{
result.add(rs.getString(1));
}
if (result.size() > 0)
{
String[] str = (String[]) result.toArray(); // 出現(xiàn)ClassCastException
return str;
}
else
return null;
}
catch(Exception e)
{
System.err.println(e);
return null;
}
finally
{
try
{
rs.close();
conn.close();
}
catch(Exception e2)
{}
}
}
程序運(yùn)行后,發(fā)現(xiàn)不能將Vector類(lèi)經(jīng)過(guò)toArray()方法得到的Object[]直接轉(zhuǎn)換成String[]。
找到用另一個(gè)帶有參數(shù)的 toArray(T[] a)方法才可以。
將該語(yǔ)句改為:
String[] str = (String[]) result.toArray(new String[1]);即告訴Vector,我要得到的數(shù)組的類(lèi)型。
回想一下,應(yīng)該是java中的強(qiáng)制類(lèi)型轉(zhuǎn)換只是針對(duì)單個(gè)對(duì)象的,想要偷懶,將整個(gè)數(shù)組轉(zhuǎn)換成另外一種類(lèi)型的數(shù)組是不行的。
5. 網(wǎng)上的資料二:
正確使用List.toArray()--
在程序中,往往得到一個(gè)List,程序要求對(duì)應(yīng)賦值給一個(gè)array,可以這樣寫(xiě)程序:
Long [] l = new Long[list.size()];
for(int i=0;i<list.size();i++)
l[i] = (Long) list.get(i);
要寫(xiě)這些code,似乎比較繁瑣,其實(shí)List提供了toArray()的方法。
但是要使用不好,就會(huì)有ClassCastExceptiony異常。究竟這個(gè)是如何產(chǎn)生的,且看代碼:
List list = new ArrayList();
list.add(new Long(1));list.add(new Long(2));
list.add(new Long(3));list.add(new Long(4));
Long[] l = (Long[])list.toArray();
for(int i=0; i<l.length; i++)
System.out.println(l[i].longValue());
紅色代碼會(huì)拋java.lang.ClassCastException。
當(dāng)然,為了讀出值來(lái),你可以這樣code:
Object [] a = list.toArray();
for(int i=0;i<a.length;i++)
System.out.println(((Long)a[i]).longValue());
但是讓數(shù)組丟失了類(lèi)型信息,這個(gè)不是我們想要得。
toArray()正確使用方式如下:
1) Long[] l = new Long[<total size>];
list.toArray(l);
2) Long[] l = (Long []) list.toArray(new Long[0]);
3) Long [] a = new Long[<total size>];
Long [] l = (Long []) list.toArray(a);
6. 總結(jié)補(bǔ)充:
java sdk doc 上講:
public Object[] toArray(Object[] a)
a--the array into which the elements of this list are to be stored, if it is big enough; otherwise, a new array of the same runtime type is allocated for this purpose.
如果這個(gè)數(shù)組a足夠大,就會(huì)把數(shù)據(jù)全放進(jìn)去,返回的數(shù)組也是指向這個(gè)數(shù)組,(數(shù)組多余的空間存儲(chǔ)的是null對(duì)象);要是不夠大,就申請(qǐng)一個(gè)跟參數(shù)同樣類(lèi)型的數(shù)組,把值放進(jìn)去,然后返回。
需要注意的是:你要是傳入的參數(shù)為9個(gè)大小,而list里面有5個(gè)object,那么其他的四個(gè)很可能是null , 使用的時(shí)候要特別注意。
7. 完畢。
J.R.Q.
2005.10.27凌晨于廣州
之前看網(wǎng)上有人發(fā)帖說(shuō)有個(gè)解決辦法是“在viewservlet.jar下找到org/eclipse/birt/report/utility下找到ParameterAccessor.class文件,現(xiàn)在要修改這個(gè)文件的源代碼,
你可以在你從CVS中簽出的源代碼中的org.eclipse.birt.report.viewer/birt/WEB-INF/classes/org/eclipse/birt/report/utility文件夾中找到ParameterAccessor.java文件,在這個(gè)java文件中找到這行:
public static final String UTF_8_ENCODE = "UTF-8"; //$NON-NLS-1$
將這行改為
public static final String UTF_8_ENCODE = "GBK"; //$NON-NLS-1$
然后將這個(gè)編譯好的class文件壓縮到viewservlets.jar的同等目錄下,替換原來(lái)的文件”,本人也試了這種方法,但沒(méi)見(jiàn)湊效,不過(guò)上面的解決方法好像是在birt2.1的環(huán)境下,這個(gè)沒(méi)仔細(xì)試,也許對(duì)birt2.1有效吧。
本人使用birt版本2.3,解決辦法如下:
在JSP中調(diào)用BIRT報(bào)表時(shí),傳的參數(shù)中有中文字符,即URL中包含中文字符,這時(shí)在BIRT端接收到的參數(shù)拼SQL語(yǔ)句后發(fā)現(xiàn)中文字符被轉(zhuǎn)碼,造成SQL中的條件不正確。
因?yàn)樵贘SP中調(diào)用BIRT是在一個(gè)JS腳本中,因此要想辦法在JS中先將中文轉(zhuǎn)成UTF-8,并且在BIRT獲取參數(shù)后再將UTF-8轉(zhuǎn)換回中文即可。
實(shí)現(xiàn)代碼:
頁(yè)面JS:
Var mychecktype = “中文”;
sqlWhere+="and t.CHECK_TYPE = '"+escape(encodeURI(mychecktype))+"'";
BIRT腳本:
sql+=decodeURI(mycondition);
問(wèn)題:
頁(yè)面中寫(xiě)了一個(gè)函數(shù)a,在另一個(gè)函數(shù)中調(diào)用,頁(yè)面用的是一個(gè)iframe框架,即通過(guò)iframe的src參數(shù)來(lái)刷新iframe中的頁(yè)面,每次在第一次調(diào)用函數(shù)a時(shí)沒(méi)問(wèn)題,但第二次點(diǎn)擊按鈕調(diào)用函數(shù)a時(shí)老報(bào)“缺少函數(shù)”的錯(cuò)誤?
function a(var1)
{
...
return a;
}
第一次 alert(a(var1)) 沒(méi)有問(wèn)題,第二次就出錯(cuò)了
解決:
后來(lái)發(fā)現(xiàn)函數(shù)中返回值變量名和函數(shù)名定義為同一個(gè)名字,把返回值變量名改成其它名字后問(wèn)題就解決了,好弱的一個(gè)問(wèn)題啊,折騰了我半天,氣憤!
改成 return b 就好了 -_-
經(jīng)常遇到備份了一個(gè)幾十M的SQL文件,還原時(shí)無(wú)法執(zhí)行或執(zhí)行一半就掛了,好像就是因?yàn)樘罅耍緛?lái)用MYSQL 的Administrator工具
還原備份會(huì)方便點(diǎn),但有時(shí)也會(huì)出現(xiàn)無(wú)法還原的問(wèn)題,不知如何是好,最后只能想到在命令窗口來(lái)執(zhí)行SQL文件,好像還挺管用,具
體執(zhí)行命令如下:
先進(jìn)入cmd命令行;
然后進(jìn)入mysql命令行;
>mysql -u admin -p
>*****
>use dbname
mysql>source %pass%\mySQLFile.sql(這里的%pass%指的就是SQL文件所在的路徑,如F:/date/mysqlDB.sql,這里路徑盡量別用中
文吧,像安裝ORACLE一樣,中文路徑可能會(huì)出現(xiàn)問(wèn)題,用英文保險(xiǎn)一點(diǎn)^_^)