posts - 39,  comments - 44,  trackbacks - 0
  2008年1月20日
“补充说明”通常是在求职简历的结束部分,可以填写,也可以空着。不过,如果能够善于利用它,求职成功率将会大大提高。毕竟,作为求职简历的最后部分,它是表现自我的最后机会。

  在“补充说明”中填写的最佳信息因人而异,这取决于求职者的职业目标和背景。请记住,求职简历是自我营销的手段,其中的信息应当有助于向用人单位推销自己,以实现自己的职业目标。可以这样考虑问题:如果这是向潜在的用人单位推销自己的最会机会,你会说些什么?

  以下是一些填写“补充说明”的思路,供大家参考:

  能力或业绩总结

  在补充说明对自己的能力和职业生涯进行总结。在能力或业绩总结中要突出自己主要的“卖点”和成功案例——这一切都应当与你想要应聘的职位有关系。

  获奖情况

  用列举自己的获奖情况作为求职简历的结束,会给用人单位留下深刻印象。

  证明书或推荐信

  你是否收到过对于你的工作情况表示满意的推荐信或业绩评估证明?如果有,可以摘选其中的精采部分作为“补充说明”。

  发表作品

  如果在报刊、杂志上发表过作品,可以考虑在“补充说明”里罗列出来。

  专利

  如果拥有专利(包括正在申请的),请在“补充说明”中列出。

  演讲能力

  许多职位要有演讲能力才能胜任。列举自己参加过的演讲、主题发言会给用人单位留下好印象。

  计算机运用技能

  在“补充说明”中列举自己在计算机操作系统、网络和硬件等方面的技能,多多益善。

  培训情况

  在“补充说明”中列出自己参加过的专业培训和继续教育。

  再次强调工作地点

  在“补充说明”中再次强调工作地点不失为结束求职简历的好办法。

  说明自己愿意出差

  如果愿意出差,可以在补充说明中加以说明,用人单位或许会因为这一点而看上你。

  应该省略的内容

  补充说明不要涉及婚姻状况、年龄、有多少个孩子等情况,如果兴趣爱好与工作无关,最好也不要提及。

 来源:中华英才网 
posted @ 2008-11-21 20:01 矿矿 阅读(270) | 评论 (1)编辑 收藏

下表是元字符及其在正则表达式上下文中的行为的一个完整列表:

字符 描述
将下一个字符标记为一个特殊字符、或一个原义字符、或一个后向引用、或一个八进制转义符。例如,'n' 匹配字符 "n"。'\n' 匹配一个换行符。序列 '\' 匹配 "" 而 "\(" 则匹配 "("。
^
匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 '\n' 或 '\r' 之后的位置。
$
匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 '\n' 或 '\r' 之前的位置。
*
匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。 * 等价于{0,}。[/size]
+
匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
?
匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}。
{n}
是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。
{n,}
是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。
{n,m}
和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。刘, "o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。
?
当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 "oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有 'o'。
.
匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式。
(pattern)
匹配pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中则使用 {CONTENT}… 属性。要匹配圆括号字符,请使用 '\(' 或 '\)'。
(?:pattern)
匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 "或" 字符 (|) 来组合一个模式的各个部分是很有用。例如, 'industr(?:y|ies) 就是一个比 'industry|industries' 更简略的表达式。
(?=pattern)
正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如, 'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern)
负向预查,在任何不匹配Negative lookahead matches the search string at any point where a string not matching pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows",但不能匹配 "Windows 2000" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
x|y
匹配 x 或 y。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 则匹配 "zood" 或 "food"。
[xyz]
字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。
[^xyz]
负值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain" 中的'p'。
[a-z]
字符范围。匹配指定范围内的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。
[^a-z]
负值字符范围。匹配任何不在指定范围内的任意字符。例如,'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范围内的任意字符。
\b
匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\B
匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
\cx
匹配由x指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。 x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。
\d
匹配一个数字字符。等价于 [0-9]。
\D
匹配一个非数字字符。等价于 [^0-9]。
\f
匹配一个换页符。等价于 \x0c 和 \cL。
\n
匹配一个换行符。等价于 \x0a 和 \cJ。
\r
匹配一个回车符。等价于 \x0d 和 \cM。
\s
匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S
匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\t
匹配一个制表符。等价于 \x09 和 \cI。
\v
匹配一个垂直制表符。等价于 \x0b 和 \cK。
\w
匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。
\W
匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。
\xn
匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如, '\x41' 匹配 "A"。'\x041' 则等价于 '\x04' & "1"。正则表达式中可以使用 ASCII 编码。.
\num
匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。例如,'(.)' 匹配两个连续的相同字符。
\n
标识一个八进制转义值或一个后向引用。如果 \n 之前至少 n 个获取的子表达式,则 n 为后向引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。
\nm
标识一个八进制转义值或一个后向引用。如果 \nm 之前至少有is preceded by at least nm 个获取得子表达式,则 nm 为后向引用。如果 \nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的后向引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字 (0-7),则 \nm 将匹配八进制转义值 nm。
\nml
如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八进制转义值 nml。
\un
匹配 n,其中 n 是一个用四个十六进制数字表示的 Unicode 字符。例如,\u00A9 匹配版权符号 (?)。

posted @ 2008-11-21 19:35 矿矿 阅读(2237) | 评论 (0)编辑 收藏

匹配中文字符的正则表达式: [u4e00-u9fa5]
评注:匹配中文还真是个头疼的事,有了这个表达式就好办了

匹配双字节字符(包括汉字在内):[^x00-xff]
评注:可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)

匹配空白行的正则表达式:ns*r
评注:可以用来删除空白行

匹配HTML标记的正则表达式:<(S*?)[^>]*>.*?|<.*? />
评注:网上流传的版本太糟糕,上面这个也仅仅能匹配部分,对于复杂的嵌套标记依旧无能为力

匹配首尾空白字符的正则表达式:^s*|s*$
评注:可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式

匹配Email地址的正则表达式:w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*
评注:表单验证时很实用

匹配网址URL的正则表达式:[a-zA-z]+://[^s]*
评注:网上流传的版本功能很有限,上面这个基本可以满足需求

匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
评注:表单验证时很实用

匹配国内电话号码:d{3}-d{8}|d{4}-d{7}
评注:匹配形式如 0511-4405222 或 021-87888822

匹配腾讯QQ号:[1-9][0-9]{4,}
评注:腾讯QQ号从10000开始

匹配中国邮政编码:[1-9]d{5}(?!d)
评注:中国邮政编码为6位数字

匹配身份证:d{15}|d{18}
评注:中国的身份证为15位或18位

匹配ip地址:d+.d+.d+.d+
评注:提取ip地址时有用


匹配特定数字:
^[1-9]d*$    //匹配正整数
^-[1-9]d*$   //匹配负整数
^-?[1-9]d*$   //匹配整数
^[1-9]d*|0$  //匹配非负整数(正整数 + 0)
^-[1-9]d*|0$   //匹配非正整数(负整数 + 0)
^[1-9]d*.d*|0.d*[1-9]d*$   //匹配正浮点数
^-([1-9]d*.d*|0.d*[1-9]d*)$  //匹配负浮点数
^-?([1-9]d*.d*|0.d*[1-9]d*|0?.0+|0)$  //匹配浮点数
^[1-9]d*.d*|0.d*[1-9]d*|0?.0+|0$   //匹配非负浮点数(正浮点数 + 0)
^(-([1-9]d*.d*|0.d*[1-9]d*))|0?.0+|0$  //匹配非正浮点数(负浮点数 + 0)
评注:处理大量数据时有用,具体应用时注意修正

匹配特定字符串:
^[A-Za-z]+$  //匹配由26个英文字母组成的字符串
^[A-Z]+$  //匹配由26个英文字母的大写组成的字符串
^[a-z]+$  //匹配由26个英文字母的小写组成的字符串
^[A-Za-z0-9]+$  //匹配由数字和26个英文字母组成的字符串
^w+$  //匹配由数字、26个英文字母或者下划线组成的字符串


在使用RegularExpressionValidator验证控件时的验证功能及其验证表达式介绍如下:


只能输入数字:“^[0-9]*$”
只能输入n位的数字:“^d{n}$”
只能输入至少n位数字:“^d{n,}$”
只能输入m-n位的数字:“^d{m,n}$”
只能输入零和非零开头的数字:“^(0|[1-9][0-9]*)$”
只能输入有两位小数的正实数:“^[0-9]+(.[0-9]{2})?$”
只能输入有1-3位小数的正实数:“^[0-9]+(.[0-9]{1,3})?$”
只能输入非零的正整数:“^+?[1-9][0-9]*$”
只能输入非零的负整数:“^-[1-9][0-9]*$”
只能输入长度为3的字符:“^.{3}$”
只能输入由26个英文字母组成的字符串:“^[A-Za-z]+$”
只能输入由26个大写英文字母组成的字符串:“^[A-Z]+$”
只能输入由26个小写英文字母组成的字符串:“^[a-z]+$”
只能输入由数字和26个英文字母组成的字符串:“^[A-Za-z0-9]+$”
只能输入由数字、26个英文字母或者下划线组成的字符串:“^w+$”
验证用户密码:“^[a-zA-Z]w{5,17}$”正确格式为:以字母开头,长度在6-18之间,


只能包含字符、数字和下划线。
验证是否含有^%&',;=?$"等字符:“[^%&',;=?$x22]+”
只能输入汉字:“^[u4e00-u9fa5],{0,}$”
验证Email地址:“^w+[-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*$”
验证InternetURL:“^http://([w-]+.)+[w-]+(/[w-./?%&=]*)?$”
验证电话号码:“^((d{3,4})|d{3,4}-)?d{7,8}$”


正确格式为:“XXXX-XXXXXXX”,“XXXX-XXXXXXXX”,“XXX-XXXXXXX”,


“XXX-XXXXXXXX”,“XXXXXXX”,“XXXXXXXX”。
验证身份证号(15位或18位数字):“^d{15}|d{}18$”
验证一年的12个月:“^(0?[1-9]|1[0-2])$”正确格式为:“01”-“09”和“1”“12”
验证一个月的31天:“^((0?[1-9])|((1|2)[0-9])|30|31)$”


正确格式为:“01”“09”和“1”“31”。


匹配中文字符的正则表达式: [u4e00-u9fa5]
匹配双字节字符(包括汉字在内):[^x00-xff]
匹配空行的正则表达式:n[s| ]*r
匹配HTML标记的正则表达式:/<(.*)>.*</1>|<(.*) />/
匹配首尾空格的正则表达式:(^s*)|(s*$)
匹配Email地址的正则表达式:w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*
匹配网址URL的正则表达式:http://([w-]+.)+[w-]+(/[w- ./?%&=]*)?

(1)应用:计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)
String.prototype.len=function(){return this.replace([^x00-xff]/g,"aa").length;}

(2)应用:javascript中没有像vbscript那样的trim函数,我们就可以利用这个表达式来实现
String.prototype.trim = function()
{
return this.replace(/(^s*)|(s*$)/g, "");
}
(3)应用:利用正则表达式分解和转换IP地址
function IP2V(ip) //IP地址转换成对应数值
{
re=/(d+).(d+).(d+).(d+)/g //匹配IP地址的正则表达式
if(re.test(ip))
{
return RegExp.$1*Math.pow(255,3))+RegExp.$2*Math.pow(255,2))+RegExp.$3*255+RegExp.$4*1
}
else
{
throw new Error("Not a valid IP address!")
}
}
(4)应用:从URL地址中提取文件名的javascript程序
s="http://www.9499.net/page1.htm";
s=s.replace(/(.*/){0,}([^.]+).*/ig,"$2") ; //Page1.htm
(5)应用:利用正则表达式限制网页表单里的文本框输入内容
用正则表达式限制只能输入中文:onkeyup="value=value.replace(/[^u4E00-u9FA5]/g,'') " onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^u4E00-u9FA5]/g,''))"
用正则表达式限制只能输入全角字符: onkeyup="value=value.replace(/[^uFF00-uFFFF]/g,'') " onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^uFF00-uFFFF]/g,''))"
用正则表达式限制只能输入数字:onkeyup="value=value.replace(/[^d]/g,'') "onbeforepaste= "clipboardData.setData('text',clipboardData.getData('text').replace(/[^d]/g,''))"
用正则表达式限制只能输入数字和英文:onkeyup="value=value.replace(/[W]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^d]/g,''

posted @ 2008-11-21 10:58 矿矿 阅读(1996) | 评论 (2)编辑 收藏
[转]自天极网

1使用不带参数的存储过程

  使用 JDBC 驱动程序调用不带参数的存储过程时,必须使用 call SQL 转义序列。不带参数的 call 转义序列的语法如下所示:

  

以下是引用片段:
{call procedure-name}

  作为实例,在 SQL Server 2005 AdventureWorks 示例数据库中创建以下存储过程:

  

以下是引用片段:
CREATE PROCEDURE GetContactFormalNames
  AS
  BEGIN
   SELECT TOP 10 Title + ' ' + FirstName + ' ' + LastName AS FormalName
   FROM Person.Contact
  END
此存储过程返回单个结果集,其中包含一列数据(由 Person.Contact 表中前十个联系人的称呼、名称和姓氏组成)。

  在下面的实例中,将向此函数传递 AdventureWorks 示例数据库的打开连接,然后使用 executeQuery 方法调用 GetContactFormalNames 存储过程。

 

以下是引用片段:
  public static void executeSprocNoParams(Connection con) ...{
   try ...{
   Statement stmt = con.createStatement();
  ResultSet rs = stmt.executeQuery("{call dbo.GetContactFormalNames}");
  
   while (rs.next()) ...{
 System.out.println(rs.getString("FormalName"));
  }
  rs.close();
  stmt.close();
  }
  catch (Exception e) ...{
  e.printStackTrace();
  }
  }

  2使用带有输入参数的存储过程

  使用 JDBC 驱动程序调用带参数的存储过程时,必须结合 SQLServerConnection 类的 prepareCall 方法使用 call SQL 转义序列。带有 IN 参数的 call 转义序列的语法如下所示:

  

以下是引用片段:
{call procedure-name[([parameter][,[parameter]]...)]}

  构造 call 转义序列时,请使用 ?(问号)字符来指定 IN 参数。此字符充当要传递给该存储过程的参数值的占位符。可以使用 SQLServerPreparedStatement 类的 setter 方法之一为参数指定值。可使用的 setter 方法由 IN 参数的数据类型决定。

  向 setter 方法传递值时,不仅需要指定要在参数中使用的实际值,还必须指定参数在存储过程中的序数位置。例如,如果存储过程包含单个 IN 参数,则其序数值为 1。如果存储过程包含两个参数,则第一个序数值为 1,第二个序数值为 2。

  作为如何调用包含 IN 参数的存储过程的实例,使用 SQL Server 2005 AdventureWorks 示例数据库中的 uspGetEmployeeManagers 存储过程。此存储过程接受名为 EmployeeID 的单个输入参数(它是一个整数值),然后基于指定的 EmployeeID 返回雇员及其经理的递归列表。下面是调用此存储过程的 Java 代码:

  

 

以下是引用片段:
  public static void executeSprocInParams(Connection con) ...{
   try ...{
   PreparedStatement pstmt = con.prepareStatement("{call dbo.uspGetEmployeeManagers(?)}");
   pstmt.setInt(1, 50);
   ResultSet rs = pstmt.executeQuery();
   while (rs.next()) ...{
   System.out.println("EMPLOYEE:");
   System.out.println(rs.getString("LastName") + ", " + rs.getString("FirstName"));
   System.out.println("MANAGER:");
   System.out.println(rs.getString("ManagerLastName") + ", " + rs.getString("ManagerFirstName"));
   System.out.println();
   }
   rs.close();
   pstmt.close();
   }
   catch (Exception e) ...{
   e.printStackTrace();
   }
  }

  3使用带有输出参数的存储过程

  使用 JDBC 驱动程序调用此类存储过程时,必须结合 SQLServerConnection 类的 prepareCall 方法使用 call SQL 转义序列。带有 OUT 参数的 call 转义序列的语法如下所示:

  

以下是引用片段:
{call procedure-name[([parameter][,[parameter]]...)]}

  构造 call 转义序列时,请使用 ?(问号)字符来指定 OUT 参数。此字符充当要从该存储过程返回的参数值的占位符。要为 OUT 参数指定值,必须在运行存储过程前使用 SQLServerCallableStatement 类的 registerOutParameter 方法指定各参数的数据类型。

  使用 registerOutParameter 方法为 OUT 参数指定的值必须是 java.sql.Types 所包含的 JDBC 数据类型之一,而它又被映射成本地 SQL Server 数据类型之一。有关 JDBC 和 SQL Server 数据类型的详细信息,请参阅了解 JDBC 驱动程序数据类型。

  当您对于 OUT 参数向 registerOutParameter 方法传递一个值时,不仅必须指定要用于此参数的数据类型,而且必须在存储过程中指定此参数的序号位置或此参数的名称。例如,如果存储过程包含单个 OUT 参数,则其序数值为 1;如果存储过程包含两个参数,则第一个序数值为 1,第二个序数值为 2。

  作为实例,在 SQL Server 2005 AdventureWorks 示例数据库中创建以下存储过程: 根据指定的整数 IN 参数 (employeeID),该存储过程也返回单个整数 OUT 参数 (managerID)。根据 HumanResources.Employee 表中包含的 EmployeeID,OUT 参数中返回的值为 ManagerID。

  在下面的实例中,将向此函数传递 AdventureWorks 示例数据库的打开连接,然后使用 execute 方法调用 GetImmediateManager 存储过程:

 

以下是引用片段:
  public static void executeStoredProcedure(Connection con) ...{
   try ...{
   CallableStatement cstmt = con.prepareCall("{call dbo.GetImmediateManager(?, ?)}");
   cstmt.setInt(1, 5);
   cstmt.registerOutParameter(2, java.sql.Types.INTEGER);
   cstmt.execute();
   System.out.println("MANAGER ID: " + cstmt.getInt(2));
   }
   catch (Exception e) ...{
   e.printStackTrace();
   }
  } 

本示例使用序号位置来标识参数。或者,也可以使用参数的名称(而非其序号位置)来标识此参数。下面的代码示例修改了上一个示例,以说明如何在 Java 应用程序中使用命名参数。请注意,这些参数名称对应于存储过程的定义中的参数名称: CREATE PROCEDURE GetImmediateManager

 
以下是引用片段:
 @employeeID INT,
   @managerID INT OUTPUT
  AS
  BEGIN
   SELECT @managerID = ManagerID
   FROM HumanResources.Employee
   WHERE EmployeeID = @employeeID
  END
  存储过程可能返回更新计数和多个结果集。Microsoft SQL Server 2005 JDBC Driver 遵循 JDBC 3.0 规范,此规范规定在检索 OUT 参数之前应检索多个结果集和更新计数。也就是说,应用程序应先检索所有 ResultSet 对象和更新计数,然后使用 CallableStatement.getter 方法检索 OUT 参数。否则,当检索 OUT 参数时,尚未检索的 ResultSet 对象和更新计数将丢失。

  4 使用带有返回状态的存储过程

  使用 JDBC 驱动程序调用这种存储过程时,必须结合 SQLServerConnection 类的 prepareCall 方法使用 call SQL 转义序列。返回状态参数的 call 转义序列的语法如下所示:

 

以下是引用片段:
 {[?=]call procedure-name[([parameter][,[parameter]]...)]}
  构造 call 转义序列时,请使用 ?(问号)字符来指定返回状态参数。此字符充当要从该存储过程返回的参数值的占位符。要为返回状态参数指定值,必须在执行存储过程前使用 SQLServerCallableStatement 类的 registerOutParameter 方法指定参数的数据类型。

  此外,向 registerOutParameter 方法传递返回状态参数值时,不仅需要指定要使用的参数的数据类型,还必须指定参数在存储过程中的序数位置。对于返回状态参数,其序数位置始终为 1,这是因为它始终是调用存储过程时的第一个参数。尽管 SQLServerCallableStatement 类支持使用参数的名称来指示特定参数,但您只能对返回状态参数使用参数的序号位置编号。

  作为实例,在 SQL Server 2005 AdventureWorks 示例数据库中创建以下存储过程:

  

以下是引用片段:
CREATE PROCEDURE CheckContactCity
   (@cityName CHAR(50))
  AS
  BEGIN
   IF ((SELECT COUNT(*)
   FROM Person.Address
   WHERE City = @cityName) > 1)
   RETURN 1
  ELSE
   RETURN 0
  END
  该存储过程返回状态值 1 或 0,这取决于是否能在表 Person.Address 中找到 cityName 参数指定的城市。

  在下面的实例中,将向此函数传递 AdventureWorks 示例数据库的打开连接,然后使用 execute 方法调用 CheckContactCity 存储过程:

 

以下是引用片段:
 public static void executeStoredProcedure(Connection con) ...{
   try ...{
   CallableStatement cstmt = con.prepareCall("{? = call dbo.CheckContactCity(?)}");
   cstmt.registerOutParameter(1, java.sql.Types.INTEGER);
   cstmt.setString(2, "Atlanta");
   cstmt.execute();
   System.out.println("RETURN STATUS: " + cstmt.getInt(1));
   }
   cstmt.close();
   catch (Exception e) ...{
   e.printStackTrace();
   }
  }
  5 使用带有更新计数的存储过程

  使用 SQLServerCallableStatement 类构建对存储过程的调用之后,可以使用 execute 或 executeUpdate 方法中的任意一个来调用此存储过程。executeUpdate 方法将返回一个 int 值,该值包含受此存储过程影响的行数,但 execute 方法不返回此值。如果使用 execute 方法,并且希望获得受影响的行数计数,则可以在运行存储过程后调用 getUpdateCount 方法。

  作为实例,在 SQL Server 2005 AdventureWorks 示例数据库中创建以下表和存储过程:

  

以下是引用片段:
CREATE TABLE TestTable
   (Col1 int IDENTITY,
   Col2 varchar(50),
   Col3 int);
  
  CREATE PROCEDURE UpdateTestTable
   @Col2 varchar(50),
   @Col3 int
  AS
  BEGIN
   UPDATE TestTable
   SET Col2 = @Col2, Col3 = @Col3
  END;
在下面的实例中,将向此函数传递 AdventureWorks 示例数据库的打开连接,并使用 execute 方法调用 UpdateTestTable 存储过程,然后使用 getUpdateCount 方法返回受存储过程影响的行计数。
以下是引用片段:
public static void executeUpdateStoredProcedure(Connection con) ...{
   try ...{
   CallableStatement cstmt = con.prepareCall("{call dbo.UpdateTestTable(?, ?)}");
   cstmt.setString(1, "A");
   cstmt.setInt(2, 100);
   cstmt.execute();
   int count = cstmt.getUpdateCount();
   cstmt.close();
  
   System.out.println("ROWS AFFECTED: " + count);
   }
   catch (Exception e) ...{
   e.printStackTrace();
   }
  }
posted @ 2008-11-07 22:21 矿矿 阅读(250) | 评论 (0)编辑 收藏
[转]自天极网

1使用不带参数的存储过程

  使用 JDBC 驱动程序调用不带参数的存储过程时,必须使用 call SQL 转义序列。不带参数的 call 转义序列的语法如下所示:

  

以下是引用片段:
{call procedure-name}

  作为实例,在 SQL Server 2005 AdventureWorks 示例数据库中创建以下存储过程:

  

以下是引用片段:
CREATE PROCEDURE GetContactFormalNames
  AS
  BEGIN
   SELECT TOP 10 Title + ' ' + FirstName + ' ' + LastName AS FormalName
   FROM Person.Contact
  END
此存储过程返回单个结果集,其中包含一列数据(由 Person.Contact 表中前十个联系人的称呼、名称和姓氏组成)。

  在下面的实例中,将向此函数传递 AdventureWorks 示例数据库的打开连接,然后使用 executeQuery 方法调用 GetContactFormalNames 存储过程。

 

以下是引用片段:
  public static void executeSprocNoParams(Connection con) ...{
   try ...{
   Statement stmt = con.createStatement();
  ResultSet rs = stmt.executeQuery("{call dbo.GetContactFormalNames}");
  
   while (rs.next()) ...{
 System.out.println(rs.getString("FormalName"));
  }
  rs.close();
  stmt.close();
  }
  catch (Exception e) ...{
  e.printStackTrace();
  }
  }

  2使用带有输入参数的存储过程

  使用 JDBC 驱动程序调用带参数的存储过程时,必须结合 SQLServerConnection 类的 prepareCall 方法使用 call SQL 转义序列。带有 IN 参数的 call 转义序列的语法如下所示:

  

以下是引用片段:
{call procedure-name[([parameter][,[parameter]]...)]}

  构造 call 转义序列时,请使用 ?(问号)字符来指定 IN 参数。此字符充当要传递给该存储过程的参数值的占位符。可以使用 SQLServerPreparedStatement 类的 setter 方法之一为参数指定值。可使用的 setter 方法由 IN 参数的数据类型决定。

  向 setter 方法传递值时,不仅需要指定要在参数中使用的实际值,还必须指定参数在存储过程中的序数位置。例如,如果存储过程包含单个 IN 参数,则其序数值为 1。如果存储过程包含两个参数,则第一个序数值为 1,第二个序数值为 2。

  作为如何调用包含 IN 参数的存储过程的实例,使用 SQL Server 2005 AdventureWorks 示例数据库中的 uspGetEmployeeManagers 存储过程。此存储过程接受名为 EmployeeID 的单个输入参数(它是一个整数值),然后基于指定的 EmployeeID 返回雇员及其经理的递归列表。下面是调用此存储过程的 Java 代码:

  

 

以下是引用片段:
  public static void executeSprocInParams(Connection con) ...{
   try ...{
   PreparedStatement pstmt = con.prepareStatement("{call dbo.uspGetEmployeeManagers(?)}");
   pstmt.setInt(1, 50);
   ResultSet rs = pstmt.executeQuery();
   while (rs.next()) ...{
   System.out.println("EMPLOYEE:");
   System.out.println(rs.getString("LastName") + ", " + rs.getString("FirstName"));
   System.out.println("MANAGER:");
   System.out.println(rs.getString("ManagerLastName") + ", " + rs.getString("ManagerFirstName"));
   System.out.println();
   }
   rs.close();
   pstmt.close();
   }
   catch (Exception e) ...{
   e.printStackTrace();
   }
  }

  3使用带有输出参数的存储过程

  使用 JDBC 驱动程序调用此类存储过程时,必须结合 SQLServerConnection 类的 prepareCall 方法使用 call SQL 转义序列。带有 OUT 参数的 call 转义序列的语法如下所示:

  

以下是引用片段:
{call procedure-name[([parameter][,[parameter]]...)]}

  构造 call 转义序列时,请使用 ?(问号)字符来指定 OUT 参数。此字符充当要从该存储过程返回的参数值的占位符。要为 OUT 参数指定值,必须在运行存储过程前使用 SQLServerCallableStatement 类的 registerOutParameter 方法指定各参数的数据类型。

  使用 registerOutParameter 方法为 OUT 参数指定的值必须是 java.sql.Types 所包含的 JDBC 数据类型之一,而它又被映射成本地 SQL Server 数据类型之一。有关 JDBC 和 SQL Server 数据类型的详细信息,请参阅了解 JDBC 驱动程序数据类型。

  当您对于 OUT 参数向 registerOutParameter 方法传递一个值时,不仅必须指定要用于此参数的数据类型,而且必须在存储过程中指定此参数的序号位置或此参数的名称。例如,如果存储过程包含单个 OUT 参数,则其序数值为 1;如果存储过程包含两个参数,则第一个序数值为 1,第二个序数值为 2。

  作为实例,在 SQL Server 2005 AdventureWorks 示例数据库中创建以下存储过程: 根据指定的整数 IN 参数 (employeeID),该存储过程也返回单个整数 OUT 参数 (managerID)。根据 HumanResources.Employee 表中包含的 EmployeeID,OUT 参数中返回的值为 ManagerID。

  在下面的实例中,将向此函数传递 AdventureWorks 示例数据库的打开连接,然后使用 execute 方法调用 GetImmediateManager 存储过程:

 

以下是引用片段:
  public static void executeStoredProcedure(Connection con) ...{
   try ...{
   CallableStatement cstmt = con.prepareCall("{call dbo.GetImmediateManager(?, ?)}");
   cstmt.setInt(1, 5);
   cstmt.registerOutParameter(2, java.sql.Types.INTEGER);
   cstmt.execute();
   System.out.println("MANAGER ID: " + cstmt.getInt(2));
   }
   catch (Exception e) ...{
   e.printStackTrace();
   }
  } 

本示例使用序号位置来标识参数。或者,也可以使用参数的名称(而非其序号位置)来标识此参数。下面的代码示例修改了上一个示例,以说明如何在 Java 应用程序中使用命名参数。请注意,这些参数名称对应于存储过程的定义中的参数名称: CREATE PROCEDURE GetImmediateManager

 
以下是引用片段:
 @employeeID INT,
   @managerID INT OUTPUT
  AS
  BEGIN
   SELECT @managerID = ManagerID
   FROM HumanResources.Employee
   WHERE EmployeeID = @employeeID
  END
  存储过程可能返回更新计数和多个结果集。Microsoft SQL Server 2005 JDBC Driver 遵循 JDBC 3.0 规范,此规范规定在检索 OUT 参数之前应检索多个结果集和更新计数。也就是说,应用程序应先检索所有 ResultSet 对象和更新计数,然后使用 CallableStatement.getter 方法检索 OUT 参数。否则,当检索 OUT 参数时,尚未检索的 ResultSet 对象和更新计数将丢失。

  4 使用带有返回状态的存储过程

  使用 JDBC 驱动程序调用这种存储过程时,必须结合 SQLServerConnection 类的 prepareCall 方法使用 call SQL 转义序列。返回状态参数的 call 转义序列的语法如下所示:

 

以下是引用片段:
 {[?=]call procedure-name[([parameter][,[parameter]]...)]}
  构造 call 转义序列时,请使用 ?(问号)字符来指定返回状态参数。此字符充当要从该存储过程返回的参数值的占位符。要为返回状态参数指定值,必须在执行存储过程前使用 SQLServerCallableStatement 类的 registerOutParameter 方法指定参数的数据类型。

  此外,向 registerOutParameter 方法传递返回状态参数值时,不仅需要指定要使用的参数的数据类型,还必须指定参数在存储过程中的序数位置。对于返回状态参数,其序数位置始终为 1,这是因为它始终是调用存储过程时的第一个参数。尽管 SQLServerCallableStatement 类支持使用参数的名称来指示特定参数,但您只能对返回状态参数使用参数的序号位置编号。

  作为实例,在 SQL Server 2005 AdventureWorks 示例数据库中创建以下存储过程:

  

以下是引用片段:
CREATE PROCEDURE CheckContactCity
   (@cityName CHAR(50))
  AS
  BEGIN
   IF ((SELECT COUNT(*)
   FROM Person.Address
   WHERE City = @cityName) > 1)
   RETURN 1
  ELSE
   RETURN 0
  END
  该存储过程返回状态值 1 或 0,这取决于是否能在表 Person.Address 中找到 cityName 参数指定的城市。

  在下面的实例中,将向此函数传递 AdventureWorks 示例数据库的打开连接,然后使用 execute 方法调用 CheckContactCity 存储过程:

 

以下是引用片段:
 public static void executeStoredProcedure(Connection con) ...{
   try ...{
   CallableStatement cstmt = con.prepareCall("{? = call dbo.CheckContactCity(?)}");
   cstmt.registerOutParameter(1, java.sql.Types.INTEGER);
   cstmt.setString(2, "Atlanta");
   cstmt.execute();
   System.out.println("RETURN STATUS: " + cstmt.getInt(1));
   }
   cstmt.close();
   catch (Exception e) ...{
   e.printStackTrace();
   }
  }
  5 使用带有更新计数的存储过程

  使用 SQLServerCallableStatement 类构建对存储过程的调用之后,可以使用 execute 或 executeUpdate 方法中的任意一个来调用此存储过程。executeUpdate 方法将返回一个 int 值,该值包含受此存储过程影响的行数,但 execute 方法不返回此值。如果使用 execute 方法,并且希望获得受影响的行数计数,则可以在运行存储过程后调用 getUpdateCount 方法。

  作为实例,在 SQL Server 2005 AdventureWorks 示例数据库中创建以下表和存储过程:

  

以下是引用片段:
CREATE TABLE TestTable
   (Col1 int IDENTITY,
   Col2 varchar(50),
   Col3 int);
  
  CREATE PROCEDURE UpdateTestTable
   @Col2 varchar(50),
   @Col3 int
  AS
  BEGIN
   UPDATE TestTable
   SET Col2 = @Col2, Col3 = @Col3
  END;
在下面的实例中,将向此函数传递 AdventureWorks 示例数据库的打开连接,并使用 execute 方法调用 UpdateTestTable 存储过程,然后使用 getUpdateCount 方法返回受存储过程影响的行计数。
以下是引用片段:
public static void executeUpdateStoredProcedure(Connection con) ...{
   try ...{
   CallableStatement cstmt = con.prepareCall("{call dbo.UpdateTestTable(?, ?)}");
   cstmt.setString(1, "A");
   cstmt.setInt(2, 100);
   cstmt.execute();
   int count = cstmt.getUpdateCount();
   cstmt.close();
  
   System.out.println("ROWS AFFECTED: " + count);
   }
   catch (Exception e) ...{
   e.printStackTrace();
   }
  }
posted @ 2008-11-07 22:16 矿矿 阅读(192) | 评论 (0)编辑 收藏

--创建数据库
use master
go
if exists(select * from sysdatabases where name = 'BankDB')
drop database BankDB
go
exec xp_cmdshell 'md E:\朱矿龙',NO_OUTPUT
create database BankDB
go
use BankDB
--创建帐户信息表AccountInfo
if exists(select * from sysobjects where name = 'AccountInfo')
drop table AccountInfo
go
create table AccountInfo
(
CustID int identity(1,1) primary key,
CustName varchar(20) not null,
IDCard varchar(18) check(len(IDCard) = 15 or len(IDCard) = 18),
TelePhone varchar(13) check(len(TelePhone)=11 or len(TelePhone) like'[0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9][0-9]' or len(TelePhone) like'[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]') ,
Address varchar(50) default '地址不详'
)
go
--创建信用卡信息表CardInfo
if exists(select * from sysobjects where name = 'CardInfo')
drop table CardInfo
go
create table CardInfo
(
CardID varchar(19) check(len(CardID)=19) primary key,
CardPassWord varchar(6) default'888888',
CustID int references AccountInfo(CustID),
SaveType varchar(10) not null check(SaveType in('活期','定期')),
OpenDate datetime not null default(getdate()),
OpenMoney money not null check(OpenMoney >= 1),
LeftMoney money not null check(LeftMoney >= 1),
IsLoss varchar(2) not null check(IsLoss in('是','否')) default '否'
)
go
--创建交易信息表TransInfo
if exists(select * from sysobjects where name = 'TransInfo')
drop table TransInfo
go
create table TransInfo
(
CardID varchar(19) not null,
TransType varchar(4) not null check(TransType in('存入','支取')),
TransMoney money not null check(TransMoney > 0),
TransDate datetime default(getdate())
)
go


-------------------------------插入测试数据-------------------------------------
---为AccountInfo表插入测试数据
insert into AccountInfo values('孙悟空','422322123902140019','027-8888988','花果山')
insert into AccountInfo values('唐僧','422322001902140019','027-8536896','大唐')
insert into AccountInfo values('沙和尚','410334020157144719','13295654665','通天河')
---为CardInfo表插入测试数据
insert into CardInfo values('1027 3726 1536 1135',default,1,'定期',default,500.00,500.00,default)
insert into CardInfo values('1029 3526 1235 1235',default,2,'活期',default,1500.00,1500.00,default)
insert into CardInfo values('1324 7532 1536 1935',default,3,'活期',default,4500.00,4500.00,default)


---表的查看
select * from AccountInfo

select * from CardInfo

select * from TransInfo

-----------------T-SQL----------------------------
--孙悟空修改密码
update CardInfo set CardPassWord = 611234 where CustID = 1

--孙悟空取钱
--事务开始
begin transaction tran_Qu
--定义一个用于记录错误的变量
declare @tran_error int
set @tran_error = 0;
--将孙悟空交易进行记录
insert into TransInfo values('1027 3726 1536 1135','支取',200.00,getdate())
set @tran_error = @tran_error + @@error
--从孙悟空的帐户中减去200.00
update CardInfo set LeftMoney = LeftMoney - 200
where CardID = '1027 3726 1536 1135'
set @tran_error = @tran_error + @@error
if @tran_error <> 0
   begin
      --执行错误,回滚事务
      rollback transaction
      print '支取失败,交易已取消'
   end
else
  begin
    --没有发现错误,提交事务
    commit transaction
    print'交易成功,已保存新数据'
  end
go
select * from CardInfo where CustID = 1

--沙和尚存钱
begin transaction tran_bring
declare @tran_error int
set @tran_error = 0;
insert into TransInfo values('1324 7532 1536 1935','存入',1200.00,getdate())
set @tran_error = @tran_error + @@error
update CardInfo set LeftMoney = LeftMoney + 1200
where CardID = '1324 7532 1536 1935'
set @tran_error = @tran_error + @@error
if @tran_error <> 0
   begin
      rollback transaction
      print '存入失败,交易已取消'
   end
else
  begin
    commit transaction
    print'交易成功,已保存新数据'
  end
go
select * from CardInfo where CustID = 3

--唐僧卡丢失
update CardInfo set IsLoss='是' where CustID = 2

--查询最近10开户的银行卡信息
select * from CardInfo where datediff(dd,OpenDate,getdate()) <= 10

--查询最大交易的卡信息
declare @maxMoney money
select @maxMoney = max(TransMoney) from TransInfo
select * from CardInfo where CardID in(select CardID from TransInfo where TransMoney = @maxMoney)

--查询交易信息表中总的交易
declare @allMoney money
declare @QuMoney money
declare @CunMoney money
select @allMoney = sum(TransMoney) from TransInfo
select @QuMoney = sum(TransMoney) from TransInfo where TransType = '支取'
select @CunMoney = sum(TransMoney) from TransInfo where TransType = '存入'
print '总交易金额:' + convert(varchar(10),@allMoney)
print '支取交易金额:' + convert(varchar(10),@QuMoney)
print '存入交易金额:' + convert(varchar(10),@CunMoney)

--给交易信息表加上非聚集索引,并利用非聚集索引查询数据
if exists(select * from sysobjects where name = 'IX_CardID')
drop index BankDB.IX_CardID
go
create nonclustered index IX_CardID
on TransInfo(CardID)
with fillfactor = 30
go
select * from TransInfo with(index = IX_CardID) where CardID = '1324 7532 1536 1935'

--查询挂失的账户信息
select * from AccountInfo where CustID in(select CustID from CardInfo where IsLoss = '是')


--账户信息视图
if exists(select * from sysobjects where name = 'view_AccountCardInfo')
drop view view_AccountCardInfo
go
create view view_AccountCardInfo
as
select AccountInfo.CustID '帐户编号',CustName '帐户姓名',IDCard'身份证号码',TelePhone'客户电话',Address'客户地址',
        CardID'信用卡编号',SaveType'储蓄类型',OpenDate'开户日期',OpenMoney'开户金额',IsLoss'是否挂失'
from AccountInfo join CardInfo
on AccountInfo.CustID = CardInfo.CustID
go
select * from view_AccountCardInfo

--交易信息视图
if exists(select * from sysobjects where name = 'view_TransInfo')
drop view view_TransInfo
go
create view view_TransInfo
as
select CardID '卡号',TransType '交易类型',TransMoney '交易金额',TransDate '交易时间'
from TransInfo
go
go
select * from view_TransInfo

---------------第三阶段----------------
--------T-SQL-------------
if exists(select name from sysobjects where name = 'Tri_TransInfo_Insert')
drop trigger Tri_TransInfo_Insert
go
create trigger Tri_TransInfo_Insert on TransInfo for insert
as
 declare @TempTransType varchar(10)     --定义临时的变量存放交易类型
 declare @TempTransMoney money          --定义临时的变量存放交易金额
 declare @TempCardID varchar(19)        --定义临时的变量存放卡号
 declare @TempLeftMoney money           --定义临时的变量存放客户的余额
 
--从inserted临时表中取出数据赋值
select @TempTransType = TransType,@TempTransMoney = TransMoney,@TempCardID = CardID
from inserted
select @TempLeftMoney = LeftMoney from CardInfo where CardID = @TempCardID

if(@TempTransType = '支取')      
  begin
    if(@TempLeftMoney - @TempTransMoney >=1)  
       begin
          update CardInfo set LeftMoney = @TempLeftMoney - @TempTransMoney where CardID = @TempCardID
          print '交易成功!'
       end
     else
       begin
          rollback transaction
          print '余额不足,交易失败!'
       end
  end
else
  begin
    update CardInfo set LeftMoney = @TempLeftMoney + @TempTransMoney where CardID = @TempCardID
    print '交易成功!'
  end
select @TempLeftMoney = LeftMoney from CardInfo where CardID = @TempCardID  
print '卡号:' + convert(varchar(19),@TempCardID) + '  余额:' + convert(varchar(10),@TempLeftMoney)
go
set nocount on   --不显示语句影响记录行数
--测试触发器,沙和尚支取
insert into TransInfo(CardID,TransType,TransMoney) values('9645 9087 9371 4492','支取',500)
go

select * from TransInfo
select * from accountinfo
select * from CardInfo

--利用存储过程实现备份交易信息的业务
if exists(select *from sysobjects where name = 'Proc_Backup_TransInfo')
    drop procedure Proc_Backup_TransInfo
go
create procedure Proc_Backup_TransInfo
@BackupDate datetime
as
declare @MyError int
set @MyError = 0
print '开始备份......'
if exists(select * from sysobjects where name ='Back_TransInfo')
begin
 begin tran 
 insert into Back_TransInfo select * from TransInfo where datediff(dd,TransDate,getdate()) >=0
set @MyError = @MyError + @@error
if @MyError != 0
   begin
       rollback transaction
      print '备份失败'
   end
else
  begin
      commit transaction
       print'备份成功'
   end
  end
else
  begin
    begin tran 
    select * into Back_TransInfo from TransInfo where datediff(dd,TransDate,getdate()) >=0
    set @MyError = @MyError + @@error
if @MyError != 0
   begin
      rollback transaction
      print '备份失败!'
   end
else
   begin
      commit transaction
      print '备份成功!'
   end
end
go
insert into TransInfo values('1324 7532 1536 1935','支取',500.00,getdate()) 
insert into TransInfo values('1324 7532 1536 1935','支取',500.00,getdate())
insert into TransInfo values('1324 7532 1536 1935','支取',500.00,getdate())
declare @BackDate datetime
set @BackDate = getDate()
exec Proc_Backup_TransInfo '2008-10-31'
go
select * from Back_TransInfo

--实现银行卡的存储过程
if exists(select * from sysobjects where name = 'Proc_GetCardID')
    drop procedure Proc_GetCardID
go
create procedure Proc_GetCardID
@CardID varchar(19) output
as
declare @TempRand numeric(18,16)
declare @TempStr varchar(18)
set @TempRand = rand(datepart(ms,getdate())*10000)
set @TempStr = convert(varchar(18),@TempRand)
set @CardID = substring(@TempStr,3,4)+' '+substring(@TempStr,7,4)+' '+substring(@TempStr,11,4)+' '+substring(@TempStr,15,4)
go
declare @MyCardID varchar(19)
exec Proc_GetCardID @MyCardID output
print '产生的随即卡号是:' + @MyCardID
go

--实现开户的存储过程
if exists(select * from sysobjects where name = 'Proc_OpenAcount')
    drop procedure Proc_OpenAcount
go
create procedure Proc_OpenAcount
@CustName varchar(20),
@IDCard varchar(18),
@Telephone varchar(13),
@OpenMoney money = 1,
@SaveType varchar(10) = '活期',
@Address varchar(50)= '地址不详'
as
 declare @MyCardID varchar(19)
 declare @MyCustID int
 exec Proc_GetCardID @MyCardID output
while(1=1)
 begin
 if exists(select * from CardInfo where CardID = @MyCardID)
 exec Proc_GetCardID @MyCardID output
else
 break
 end
insert into AccountInfo values(@CustName,@IDCard,@TelePhone,@Address)  
select @MyCustID = CustID from AccountInfo where IDCard = @IDCard      
insert into CardInfo values(@MyCardID,default,@MyCustID,@SaveType,default,@OpenMoney,@OpenMoney,default)
print '尊敬的客户:' +@CustName +'开户成功,卡号为:'+@MyCardId

print '产生的随机卡号为:' + @MyCardID
exec Proc_OpenAcount '白骨精','245687556977812345','12478964568'
exec Proc_OpenAcount '嫦娥公主','745687476912812335','14796653141',@Address = '月亮'

----销户
if exists(select * from sysobjects where name = 'Proc_DropAcount')
    drop procedure Proc_DropAcount
go
create procedure Proc_DropAcount
 --@CardID varchar(19)
@IDCard varchar(18) --身份证号
as
declare @TempCustID int
declare @TempLeftMoney money
--select @TempCustID = CustID from CardInfo where CardID = @CardID 
--select @TempLeftMoney = LeftMoney from CardInfo where CardID = @CardID
print '该帐户余额:' +convert(varchar(10),@TempLeftMoney)+'正在取出。。。'
delete from CardInfo where custid in(select custid from accountinfo where IDCard=@IDCard)
delete from  AccountInfo where IDCard=@IDCard
go
declare @CardID varchar(19)
select @CardID = CardID from CardInfo where CustID in(select CustID from AccountInfo where CustName = '唐僧')
exec Proc_DropAcount '422322001902140019'--根据身份证号删除
go
---表的查看
select * from AccountInfo
select * from CardInfo

posted @ 2008-10-31 19:31 矿矿 阅读(491) | 评论 (0)编辑 收藏

类和对象:
 类:主观抽象,是对象的模板,可以实例化对象
  习惯上类的定义格式:
   package xxx;  
   import xxx;  
   public class Xxxx{
    属性 ······;
    
    构造器 ······;
    
    方法 ······;
   }

  定义属性:实例变量
   格式:[ 修饰符 ]  类型 变量名  [ = ? ]
   实例变量定义在类中但在任何方法之外。
   实例变量有默认值:各种各样的0。(同数组)
   实例变量的作用域至少在本类内部,受访问控制符的限制。
   在重合作用域,实例变量和局部变量允许有命名冲突,“局部优先”。
   
  定义方法:
   格式: [ 修饰符 ]  返回类型 方法名( 参数列表 ) [ throws  异常 ] { ······ }
   java中所有参数都是值传递。
      当没有值返回时,返回类型必须被定义为void。
   返回类型必须与方法名相邻,其他修饰符可以调换位置。
   
  构造器:
   在创建对象的过程中调用的方法。
   构造器没有返回类型。
   构造器的名字与类名相同。
   格式为:[ 修饰符 ]  类名( 参数列表 ){  },修饰符可以是private、 protected、 default、private
   在一个对象的生成周期中构造器只用一次,由系统自动调用,不允许手工调用。
   程序员没有提供一个构造器,系统会自动提供一个无参的构造器。
   获得对象的方式:
    通过new(在堆空间中申请分配空间),new 类名(),可以通过这种形式或的一个对象,这时的对象是无法使用,必须把他的地址存放进一个对象变量才能够使用。
    例如 :
     Car c=new Car();
   注意:
    最好在写类时提供一个无参的构造器。
      
  this关键字:
   this是个隐式参数,代表当前对象;
    publie class Student{
     private String name;
     public void setName(String name){
      this.name=name;  //this.name为当前对象的成员变量
     }
    }
    
   如果某个构造方法的第一个语句具有形式this( ··· ),那么这个构造方法将调用同一类中的其他构造方法。
   
          注意:
           在构造器中this(...)必须放在该构造器的第一行。
    this不能出现在静态方法里面  
 
 类、对象、实例三者的关系:
  类:是对象的模板,可以实例化对象
  对象:类的个体
  实例:实现的对象
  student s; 
  s=new student();
   其中 Student为类,s为对象,new Student()为实例,s赋值后也是实例了。

方法重载:
 方法名相同,参数表不同,不考虑返回值类型(但最好还是使返回类型一致)。
 编译器根据参数,选择一个方法,如果没有完全匹配的,对于参数表采用“向上就近匹配原则”,但不允许模棱两可。
 方法重载屏蔽了一个对象的同一类方法由于参数不同所造成的差异。
   
封装:
 类的属性加private修饰符,来限制只能够在类的内部进行访问,有效的保护数据。
 对于类中的私有属性,要对其给出一对方法getXxx(),setXxx()访问私有属性,保证对私有属性的操作的安全性。
 方法公开的是方法的声明,即只须知道参数和返回值就可以调用该方法,隐藏方法的实现的细节。
 一个对象和外界的联系应当通过一个统一的接口,应当公开的公开,应当隐藏的隐藏。
  
继承:
 父类到子类是从一般到特殊的关系。
  泛化:将不同子类中的共性抽象成父类的过程。
  特化:在原有父类的基础上加入一些个性的过程。
  原则:父类放共性,子类放个性。
 继承的关键字:extends
 Java只支持单继承:一个类最多只有一个直接的父类。

      方法覆盖:
  方法名:相同
  参数表:相同
  访问限制符:相同或者更宽
  返回值类型:相同或者子类返回的类型是父类返回的类型的子类(在JDK5.0以后)
  抛出的异常:不能比父类更宽。
    
      super关键字:
  super()表示调用父类的构造器
  super()也和this()一样必须放在方法的第一句
  super()和this()不能同时出现        
  super可以屏蔽子类属性和父类属性重名时带来的属性遮盖,super. 表示调用父类的方法或属性
  在子类的构造器中如果没有指定调用父类的哪一个构造器,那么就会调用父类的无参构造器,即super()
  
 注意:
  父类的构造器不能被子类继承
  方法和属性可以被继承,权限不限制能否继承过来,限制的是能否直接访问
  先构造父类,后构造子类,先this后super
  
多态:
 多态分为两种:编译时多态和运行时多态。
  编译时类型:主观概念,把它看作什么。
  运行时类型:客观概念,实际它是什么。
    例:Animal a=new Dog();
         指着狗问,这个动物是什么?
         
      运行时多态的三原则:
  对象类型不变。
  只能对对象调用编译时类型中定义的方法。
  在程序的运行时,根据对象的运行时类型,找覆盖后的方法来调用。(运行时动态类型绑定)
  
      强制类型转换: 一定没有新对象生成。(父类的引用赋值给子类的引用需要进行强制类型转换)
      关键字:instanceof
           用法:引用  instanceof  类名    判断这个引用所指向的对象是否属于这个类。
    用在强制转换之前,避免类型转换异常。
   if(a instanceof Dog){
    Dog d=(Dog)a;
   }
   
 多态的作用:把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。

posted @ 2008-10-26 21:04 矿矿 阅读(246) | 评论 (0)编辑 收藏

局部变量:不是声明在类体括号里面的变量
 (1)必须要先赋值,后使用,否则通不过编译,局部变量没有默认初始化值
 (2)作用范围:定义开始到定义它的代码块结束
 (3)同一范围内,不允许2个局部变量命名冲突

 参数传递时,简单类型进行值转递 (参数进行传递时都会先去栈中生成一个副本的,使用结束后释放)
 
自动类型提升:
 byte a = 1;
 byte b = 2;
 a = a+b;          //编译出错自动类型提升成int
 a += b;       //自加没有自动类型提升问题
 类型自动提升规则:
  a和b作某种运算
  a和b中有double,结果就是double
  a和b中有float,结果就是float
  a和b中有long,结果就是long
  除此之外,结果都是int
 把高字节转成低字节,需要作强制类型转换. byte c=(byte)a+b;
 
移位运算符:效率最高
 >>   有符号右移,补符号位
  移负数位,则将该数值加32后再进行移位
  数值的2进制是按照补码保存的
 >>>  右移后高位都补0
 
逻辑运算符:
 &/|也可以作为逻辑运算符
 && 先判断前面一个条件,如果为假,则不用计算后一个条件
 || 先判断前面一个条件,如果为真,则不用计算后一个条件
 
" + "运算符:
 两个操作的对象是数值时,是加法
 如果有一个是字符串时,则是字符串的连接
 
流程控制语句:
 同Core C++
 switch中的变量类型只能是byte、 short、int、char四种类型
 
数组:
 声明数组:  
  数组能以下列形式声明:
   类型[] array;
   类型 array[]; 
  注:
   JAVA中推荐用:类型[] array;
   一个数组是一个对象
   声明一个数组没有创建一个对象
   声明时不用指定长度
   
 创建数组:
  创建基本数据类型数组:int[] i = new int[2];
  创建引用数据类型数组:Student[] s = new Student[100];
  数组创建后其中的元素有初始值
   类型                     黙认值
   byte                      0
   short                     0
   int                       0
   long                      0l
   float                     0.0f
   double                   0.0d
   char                      \u0000
   boolean                 false
   reference types     null
  注:
   创建时一定要指定长度
   int[] i2=new int[];            //error
   
 初始化数组:
  声明、创建、初始化分开:
   int[] i;   //定义数组
   i = new int[2];  //分配空间
   i[0] = 0;    //初始化
   i[1] = 1;
   
  声明、创建、初始化在同一时间 :
   int[] i = {0,1};   //显示初始化  {}中有几个值,则数组长度为几
   Student[] s = {new Student(),new Student()};
   
  注: int[] i=new int[]{1,2,3};      //后面[]中不可以写数值
   int[] i1=new int[3]{1,2,3};    //error
   
 二维数组:(其实是一个一维数组,它的每一个元素又是一个一维数组)
  int[][] i1 = new int[2][3];
  int[][] i4 = {{1,1,1},{2,2,2},{3,3,3}};
  int[][] i3 = new int[][3];  //不允许高维没分配空间而先给低维分配空间
  int[][] i2 = new int[2][];
  i2[0] = new int[2];
  i2[1] = new int[3];    
  
 数组长度:
  数组的属性length
  数组长度一旦确定,不可改变    
  int[] i = new int[5]; 则i.length= 5
  
 数组拷贝:
  系统类System提供的
  static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
   src: 源数组  
   srcPos: 从源数组哪个位置开始拷贝(位置指的是元素的下标)
   dest: 目标数组
   destPos: 拷贝的元素放到目标数组的起始位置
   length: 拷贝多少个
   
 数组排序:
  自己实现一个排序方法来进行排序
  或者调用java.util.Arrays.sort(Object o)

posted @ 2008-10-20 22:43 矿矿 阅读(170) | 评论 (0)编辑 收藏

JAVA_HOME:配置JDK的目录
 CLASSPATH:指定到哪里去找运行时需要用到的类代码(字节码)
 PATH:指定可执行程序的位置
 
 LINUX系统(在" .bash_profile "下的环境变量设置)
  JAVA_HOME=/opt/jdk1.5.0_06
  CLASSPATH=.:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar
  PATH=$PATH:$JAVA_HOME/bin:.
  export JAVA_HOME CLASSPATH PATH     (将指定的环境变量声明为全局的)
   
 windows系统:
  右击我的电脑-->属性-->高级-->环境变量
  
Java的运行过程:
 编译:生成可执行文件,如C++中利用g++生成a.out,效率高,但不跨平台
 解释:解释器把源文件逐行解释,跨平台但效率不高
 
 在java中:先编译后解释,把.java文件编译成.class字节码文件
  Java源代码文件(.java文件)--->
  Java编译器(javac)--->
  Java字节码文件(.class文件,平台无关的)--->
  Java解释器(java),执行Java字节码

Java的垃圾回收:
 由一个后台线程gc进行垃圾回收
 虚拟机判定内存不够的时候会中断代码的运行,这时候gc才进行垃圾回收
 缺点:不能够精确的去回收内存
 java.lang.System.gc(); 建议回收内存,但系统不一定回应,他会先去看内存是否够用,够用则不予理睬,不够用才会去进行垃圾回收
 内存中什么算是垃圾:
  不在被引用的对象(局部变量,没有指针指向的)
  
java的安全性:
 沙箱机制:只能做沙箱允许的操作
 通过下面环节,实现安全
  加载有用的类文件,不需要的不加载
  校验字节码,查看允许的操作
   查看代码和虚拟机的特性是否相符
   查看代码是否有破坏性
   查看是否有违规操作,如越界
   查看类型是否匹配,类型转换是否能正确执行
   
源程序:
 package mypack;  //相当于一个目录
 
 public class HelloWorld{
  public static void main(String[] args){
   System.out.println(“Hello World”);
  }
 }
 注:
  1、文件名必须和public修饰的类名一致,以.java作为文件后缀,如果定义的类不是public的,则文件名与类名可以不同。
  2、一个.java文件中可以有多个class,但是只有一个public修饰的类。
  3、java源代码文件编译后,一个类对应生成一个.class文件
  4、一个java应用程序应该包含一个main()方法,而且其签名是固定的,它是应用程序的入口方法,可以定义在任意一个类中,不一定是public修饰的类
  编译:javac -d . HelloWorld.java
   含有包的类,在编译的时候最好用上面的格式,-d指的是让该类生成的时候按照包结构去生成," . "指的是在当前路径下生成
   如果不用上面的格式,也可以用javac HelloWorld.java,但是需要注意的是包结构就要由自己去建立,然后将生成的.class文件放到该目录下
  执行:java mypack.HelloWorld
   将字节码文件交给Java虚拟机去解释执行
   需要注意的事,必须使用包名.类名去解释执行
   
包(package):把源文件放在目录下
 由于工程的需要,将不同的源文件放在不同的目录下,从而引入了包。
 包可以看作就是一个存放java源文件的目录。
 在源码中声明一个包名:package p;(只能放在第一行,且最多只能是一行)
 如果指定多层包,那么在包名之间我们可以用.作为分隔符:package p1.p2.p3.p4;
 用“javac HelloWorld.java –d 绝对路径”,编译后生成的字节码文件就会放在指定的包结构下
 执行该程序需要用" java 包名.类名 "
 引进包中的某个类:import 包名.类名;
 引进包中的所有类:import 包名.*;
   
注释:
 // 单行注释, 到本行结束的所有字符会被编译器忽略
 /* */ 多行注释,  在/*  */之间的所有字符会被编译器忽略
 /**  */   文档注释, java特有的,在/**  */之间的所有字符会被编译器忽略
 可以用javadoc把java源程序中这种注释抽取出来形成html页面(只有写在包,类,属性,方法,构造器,引入之前的注释才可以进行抽取)
    
标识符:
 命名规则:
  (1) 由字母、数字、下划线、$组成,不能以数字开头
  (2) 大小写敏感
  (3) 不得使用java中的关键字和保留字
 
 关键字:都是小写的,jdk1.2多了strictfp(经准浮点型),关键字 jdk1.4多了assert(断言)关键字,  jdk1.5多了enum(枚举) 关键字
  随着学习进度,会慢慢接触到的
  true、false、null严格说不应该算关键字,应称其为保留字更合适
 
 习惯:
  (1) 标识符要符合语义信息
  (2) 包名所有字母小写
  (3) 类名每个单词首字母大写,其它小写 //TarenaStudent
  (4) 变量和方法:第一个单词小写,从第二个单词开始首字母大写 //tarenaStudent
  (5) 常量:所有字母大写,每个单词之间用" _ "连接
  
基本数据类型:8种
 1) 整型
  byte       1B  8位       -128到127
  short      2B  16位      -2^15到(2^15)-1
  int          4B  32位      -2^31到(2^31)-1
  long        8B  64位      -2^63到(2^63)-1
 2) 浮点类型
  float        4B   32位      
  double     8B   64位
 3) 字符类型
    char       2B 16位  
 4) 布尔型  1B
  boolean    false/true
  
 注:
  1、Java中的自动类型提升问题。
   1)、正向过程:从低字节到高字节可以自动转换。
    byte->short->int->long->float->double
   2)、逆向过程:从高字节到低字节用强制类型转换。
    例:int a = (int)4.562;
    注:逆向转换将丢失精度。
   2、boolean:只有true和false。
   3、char:Java中用" \u四位十六进制的数字 (即使在注释中出现\u,后面如果跟的不是4个数字,也会报错)"表示将字符转换成对应的unicode编码,字符类型要用单引号括起来。
   4、黙认浮点类型为double,float数据类型有一个后缀为" f "或" F "。
   5、long类型有一个后缀,为" l " 或者" L "
 
引用数据类型:
 类、接口、数组
 引用类型 变量名 = new 引用类型名(参数);  //new后面一般跟的都是类的构造器
 成员:写在类体括号里面的
 
内存空间的分配:
 内存分为:
  栈:存放简单数据类型变量(值和变量名都存在栈中),存放引用数据类型的变量名以及它所指向的实例的首地址
  堆:存放引用数据类型的实例

posted @ 2008-10-14 19:44 矿矿 阅读(410) | 评论 (0)编辑 收藏

 

在中国,做软件是当今最时髦的事情,但做软件早已不仅仅是商业,而已经上升为一门艺术;早已经不是真正搞软件的人独占的地盘,而是融入房地产商、硬件厂商、服务商、各类投机者等三教九流无所不包的社会大棋局。  显然,这是一次几十年不遇的政策机遇,其最大价值不在于真正的软件产业本身,不在于软件业务本身。因为真正的中国软件市场现在撑死也就200个亿,而且大部分(2/3以上)由国外软件公司所占有。但是,这次以软件为名义的热潮,其调动和转移的财富和资源,是千亿甚至万亿计的,是软件业本身的1~2个数量级以上,甚至也是几年前互联网热潮的2~3个数量级以上。这是所有试图把握软件机遇的人,必须首先判明的方向性问题。
  我们借用围棋的术语,可以把商机划分为“金角银边草肚皮”,鲜明地分析如下:
  1、金角:最软的高科技和最土的房地产,鲜花插牛粪也好,天造一双地配一对也好,反正今后今年他们都将如胶似漆!以软件的名义,全国各省市,各区县都将有成千上万亩的土地纷纷成为软件园,这无疑是房地产的大好机遇。因此,各地的软件园和软件学院,以及其他以软件名义腾出的地皮,是这场软件热潮的价值核心。
  2、银边:政策效应的最根本特点就是全国上下会争先恐后,一齐跟进。上上下下都会响应号召,出台各种扶持政策。包括税收减免、资金投入以及其他优先政策,都可以形成不菲的政策资源。这些资源利用得当也可以及时转化为真金白银。因此,如果几年之内,全国的硬件公司、IT服务公司甚至其他行业的公司,全部或者大多都转变成软件公司,你也不要大惊小怪。只要真正有利益。软件业全国上下大繁荣,也是可以期待的。当然,这是中国“特色”的软件业,是远远超越了国际上一般标准的软件概念。
  3、草肚皮:大获其利的很少是真正的软件公司。因为那些一门心思搞软件的人,大多笨手笨脚。热潮之下,供需严重失衡,软件人才几年后很可能沦为青菜萝卜一样。不过,那些真正一头扎进软件,真的做成软件公司,也可能不错的。虽然,随着软件公司迅速繁衍,真的假的都来争夺有限的市场,竞争进一步激化,十分辛苦。但是,现在哪一行不辛苦?如果定位准确,真的能够一不留神做成、做大,然后融资上市,也是一步登天。
  由此,所有赶潮软件的人,从高到低,可以分为三类:最上等是“为地皮而软件”,中间是“为政策而软件”,最下等是“为软件而软件”,构成了食物链的金字塔。与国内其他行业的政策造市的基本规律没有本质差异。
  面对软件热潮中的一些不和谐现象,我们没有必要只从消极和负面的角度来评判。毕竟,在这股热潮中,假作真时假也真,软件业之外的庞大资源肯定会有一小部分要转化到软件产业。由于资源总量庞大,有百分之一或者百分之几的转化,对于软件业来说,就是“久旱逢甘雨”,就是极大的支持。比如以国内软件园圈地最为成功的托普为例,它在全国的几十个软件园都是不错的房地产项目,运作得当,利润十分丰厚。拿出一小部分利润来投入软件,补贴软件,几年以后一不留神也会“培育”出真正的软件业务。毕竟,大家打的都是“软件”的旗号,完全没有软件,这个美妙的游戏也是难以为继的。这一切总比那些纯粹的房地产商要好一些!
  因此,吃着房地产的剩饭,软件也可能一点点长大成人。走出过门,走向世界;挑战微软,打败印度,也不是完全没有可能。市场就是一个追逐利益最大化的棋局,消极的批评作用和意义不大。不如,我们正视现实,承认积极、正面的效应,坦然应对这场势不可当的大热潮。
  总之,政策已经为我们布好了巨大的棋盘,至于如何布局和下子,那就是一个各显其能的时候。我们当然真诚希望,那些真正有心推动中国软件业发展的人士,能够认清形势,放开思路。在这场大规模的财富与资源转移中,不要太固守成见,应放开手脚,争取获得尽可能多的利益,使中国软件得到更好的推动。
posted @ 2008-10-09 19:01 矿矿 阅读(194) | 评论 (0)编辑 收藏

ADSL拨号中出现的错误代码
 

 
Error 602 The port is already open

问题:拨号网络网络由于设备安装错误或正在使用,不能进行连接

原因:RasPPPoE没有完全和正确的安装

解决:卸载干净任何PPPoE软件,重新安装

 

Error 605 Cannot set port information

问题:拨号网络网络由于设备安装错误不能设定使用端口

原因:RasPPPoE没有完全和正确的安装

解决:卸载干净任何PPPoE软件,重新安装

 

Error 606 The port is not connected

问题:拨号网络网络不能连接所需的设备端口

原因:RasPPPoE没有完全和正确的安装,连接线故障,ADSL MODEM故障

解决:卸载干净任何PPPoE软件,重新安装,检查网线和 ADSL MODEM

 

Error 608 The device does not exist

问题:拨号网络网络连接的设备不存在

原因:RasPPPoE没有完全和正确的安装

解决:卸载干净任何PPPoE软件,重新安装

 

Error 609 The device type does not exist

问题:拨号网络网络连接的设备其种类不能确定

原因:RasPPPoE没有完全和正确的安装

解决:卸载干净任何PPPoE软件,重新安装

 

Error 611 The route is not available/612 The route is not allocated

问题:拨号网络网络连接路由不正确

原因:RasPPPoE没有完全和正确的安装,ISP服务器故障

解决:卸载干净任何PPPoE软件,重新安装,致电ISP询问

 

Error 617 The port or device is already disconnecting

问题:拨号网络网络连接的设备已经断开

原因:RasPPPoE没有完全和正确的安装,ISP服务器故障,连接线,ADSL MODEM故障

解决:卸载干净任何PPPoE软件,重新安装,致电ISP询问 ,检查网线和 ADSL MODEM

 

Error 619

问题:与ISP服务器不能建立连接

原因:ADSL ISP服务器故障,ADSL电话线故障

解决:检查ADSL信号灯是否能正确同步。致电ISP询问

 

Error 621 Cannot open the phone book file

Error 622 Cannot load the phone book file

Error 623 Cannot find the phone book entry

Error 624 Cannot write the phone book file

Error 625 Invalid information found in the phone book

问题:Windows NT或者Windows 2000 Server网络RAS网络组件故障

原因:软件安装问题

解决:卸载所有PPPoE软件,重新安装RAS网络组件和RasPPPoE

 

Error 630

问题:ADSL MODEM没有没有响应

原因:ADSL电话线故障,ADSL MODEM故障(电源没打开等)

解决:检查ADSL设备

 

Error 633

问题:拨号网络网络由于设备安装错误或正在使用,不能进行连接

原因:RasPPPoE没有完全和正确的安装

解决:卸载干净任何PPPoE软件,重新安装

 

Error 638

问题:过了很长时间,无法连接到ISP的ADSL接入服务器

原因:ISP服务器故障;在RasPPPoE所创建的不好连接中你错误的输入了一个电话号码

解决:运行其创建拨号的Raspppoe.exe检查是否能列出ISP服务,以确定ISP正常;把所使用的拨号连接中的 电话号码清除或者只保留一个0。

 

Error 645

问题:网卡没有正确响应

原因:网卡故障,或者网卡驱动程序故障

解决:检查网卡,重新安装网卡驱动程序

 

Error 650

问题:远程计算机没有响应,断开连接

原因:ADSL ISP服务器故障,网卡故障,非正常关机造成网络协议出错

解决:检查ADSL信号灯是否能正确同步,致电ISP询问;检查网卡,删除所有网络组件重新安装 网络。

 

Error 651

问题:ADSL MODEM报告发生错误

原因:Windows处于安全模式下,或其他错误

解决:出现该错误时,进行重拨,就可以报告出新的具体错误代码

 

Error 691

问题:输入的用户名和密码不对,无法建立连接

原因:用户名和密码错误,ISP服务器故障

解决:使用正确的用户名和密码,并且使用正确的ISP账号格式(name@service),致电ISP询问。

 

Error 718

问题:验证用户名时远程计算机超时没有响应,断开连接

原因:ADSL ISP服务器故障

解决:致电ISP询问

 

Error 720

问题:拨号网络无法协调网络中服务器的协议设置

原因:ADSL ISP服务器故障,非正常关机造成网络协议出错

解决:致电ISP询问,删除所有网络组件重新安装网络。

 

Error 734

问题:PPP连接控制协议中止

原因:ADSL ISP服务器故障,非正常关机造成网络协议出错

解决:致电ISP询问,删除所有网络组件重新安装网络。

 

Error 738

问题:服务器不能分配IP地址

原因:ADSL ISP服务器故障,ADSL用户太多超过ISP所能提供的IP地址

解决:致电ISP询问

 

Error 797

问题:ADSL MODEM连接设备没有找到

原因:ADSL MODEM电源没有打开,网卡和ADSL MODEM的连接线出现问题,软件安装以后相应的协议没有正确邦定,在创立拨号连接时,建立了错误的空连接

解决:检查电源,连接线;检查网络属性,RasPPPoE相关的协议是否正确的安装并正确邦定(相关协议),检查网卡是否出现?号或!号,把它设置为Enable;检查拨号连接的属性,是否连接的设备使用了一个“ISDN channel-Adapter Name(xx)” 的设备,该设备为一个空设备,如果使用了取消它,并选择 正确的PPPoE设备代替它,或者重新创立拨号连接。

posted @ 2008-10-06 13:47 矿矿 阅读(127) | 评论 (0)编辑 收藏
“高效”有时候并不需要什么技巧,很多人在抱怨没有足够时间的时候,其中的潜台词是他们应该更专心。时间对每个人都是公平的,你需要的是不要浪费时间,并且专心。

防止浪费时间的窍门
If the real work that needs doing is offline, disable the internet for an hour at a time.
如果这件事情不需要上网就可以完成,把网断掉。

Turn email checks into an hourly habit, not an “as the box gets mail” habit.
延长查看电子邮件的周期。

Don’t answer your cell phone when working on something important. Call back later.
如果手头的工作很重要,工作期间不要接电话,回头再打过去就是了。

If you can’t work at work, negotiate finding a new place to get things done.
如果你的工作环境让你不能工作,换个没人打扰的地方

Television means: “I don’t need this time and it doesn’t matter to me.” (Almost always. Really.)
看电视意味着“这段时间我浪费了也无所谓”。

Bugdet your entertainment time vs. production time. Never cheat the other.
平衡你的娱乐和工作时间。

Examine every opportunity along the lines of time vs. projects already underway.
时时检查你的时间安排和现在已经进行中的项目。

Try working part of your day in “off-hour” times, to get more done with fewer people around.
以小时为单位划分你的工作时间,用更少的人做更多的事情。

专心的窍门

Write your goals clearly. Post them in eyeball view of where you work most.
清楚的写下你的目标。放在你的眼皮底下。

Spend time with focused people. Meet and befriend those who are where you want to be.
多和专心工作的人在一起。

Consume as much material about your prime focus as you can budget.
尽量把资源用在主要目标上,把时间花在刀刃上。

Analyze your past experiences. Be clear. List your successes. Examine your failures.
回顾总结以往的成功和失败经验。

Stay true to a particular vision of what you want to do.
清楚明白你想要得到的是什么。

Don’t give up too early.
不要太容易放弃。

Envision your success. Write about it. Then read that daily or weekly.
想象一下成功后的样子,写下来,每天读读。

Learn how to “chunk.” Hit each milestone and move to the next. Be methodical.
学会把大事划分为几个阶段,完成一个阶段,再进入下一个。

Develop habits around success and drive.
养成好习惯。

Recharge your batteries with good sleep and food.
吃好睡足。

Develop your relationship with your family. It nourishes the other goals.
维持家庭关系。这是你完成其它工作的保障。
posted @ 2008-09-12 18:24 矿矿 阅读(147) | 评论 (1)编辑 收藏
1、不说“不可能”三个字;

2、凡事第一反应:找方法,而不是找借口;

3、遇到挫折对自己大声说:太棒了;

4、不说消极的话,不落入消极情绪,一旦出现立即正面处理;

5、凡事先订立目标,并且尽量制作“梦想版”;

6、凡事预先作计划,尽量前目标视觉化;

7、六点优先工作制,每一分,每一秒做生产力的事情;

8、随时用零碎的时间(如等人、排队等)做零碎的小活;

9、守时;

10、写下来,不要太依靠脑袋记忆;

11、随时记录灵感;

12、把重要的观念、方法写下来,并贴起来,以随时提示自己;

13、走路比平时快30%。走路时,脚尖稍用力推进;肢体语言健康有力,不懒散;

14、每天出门照镜子,给自己一个自信的笑容;

15、每天自我反省一次;

16、每天坚持一次运动;

17、听心跳1分钟。指在做重要事前,疲劳时,心情烦燥时,紧张时;

18、开会坐在前排;

19、微笑;

20、用心倾听,不打断对方说话;

21、说话时,声音有力。感觉自己声音似乎能产生有感染力的磁场;

22、同理心。说话之前,先考虑一下对方的感觉;

23、每天有意识、真诚地赞美别人三次以上;

24、及时写感谢卡,哪怕是用便条写;

25、不用训斥、指责的口吻跟别人说话;

26、控制住不要让自己做出为自己辩护的第一反应;

27、每天多做一件“分外事”

28、不管任何方面,每天必须至少做一次“进步一点点”;

29、每天提前15分钟上班,推迟30分钟下班;

30、每天在下班前5分钟的时间做一天的整理性工作;

31、定期存钱;

32、节俭;
posted @ 2008-09-12 18:23 矿矿 阅读(117) | 评论 (0)编辑 收藏

新华网北京5月20日电(记者 隋笑飞杨维汉)这次地震前,中国地震局没有作出短临预报,同时也没有收到任何单位、个人或团体提交的有关这次地震的短临预报意见。至于网上发布曾经有人提出过关于这次地震的预报意见的信息,是不符合实际的。中国地震局对于个人或团体的地震短临预报意见,有专门的管理办法和处理程序。中国地震局监测预报司是具体负责这项工作的部门。

20日上午,中国地震局监测预报司副司长车时接受中国地震信息网专访时作上述表示。

车时同时介绍了中国地震局对个人或团体的地震短临预报意见的管理办法。他说,中国地震局监测预报司从20世纪80年代后期开始对个人、学术团体的短临地震预报意见实施管理,具体管理工作由中国地震台网中心统一管理。具体办法是,指定专门的地震预报专家管理个人、学术团体等提出的短临预报意见。由专家收集、整理,并及时在地震部门的周、月会商中,介绍预测意见的主要依据、结论等,供震情跟踪判定时参考。每年年底,对一年中的所有短临预报意见进行评估,对其中预报准确或预报效果较好的给予奖励。

车时还指出,中国防震减灾法和地震预报管理条例中,有关于地震短临预报的明确规定。防震减灾法第十六条规定:国家对地震预报实行统一发布制度。地震短期预报和临震预报,由省、自治区、直辖市人民政府按照国务院规定的程序发布。任何单位或者从事地震工作的专业人员关于短期地震预测或者临震预测的意见,应当报国务院地震行政主管部门或者县级以上地方人民政府负责管理地震工作的部门或者机构按照前款处理,不得擅自向社会扩散。

车时表示,地震预报管理条例规定,国家鼓励和扶持地震预报的科学技术研究。中国地震局监测预报司本着对人民、对国家高度负责的态度,严格遵照该规定,支持地震预报科学研究,高度重视个人和团体提出的短临预测意见,但是对这些预测意见的处理是有严格程序的,要组织专家按照有关规定对预测意见的科学性和可能性进行审定。同时,由于地震预报既具有科学性,又具有社会性,政府发布地震预测意见是非常慎重的。

关于个人或团体有了地震预报意见后应如何提交给地震部门的问题,车时表示,任何单位和个人根据地震观测资料和研究成果,提出了短临地震预测意见,可向所在地或者所预测地区的县级以上地方人民政府负责管理地震工作的机构提出书面报告,也可以直接向国务院地震工作主管部门书面报告。但是,不得向社会散布。并且,任何单位和个人不得向国(境)外提出地震预测意见。个人或团体对地震活动趋势的长期和中期预测研究成果除外,可以进行学术交流讨论。

车时还谈了个人或团体提交的地震短临预报意见的具体情况。他说,现在有很多个人或团体开展地震预报探索,每年都收到几十至上百份的正式短临预报意见。但是,当前地震预报是公认的世界科学难题,总体水平是很低的。准确的短临预报意见是非常少的,2000年以来,中国地震台网中心(前分析预报中心)共收到700多份地震短临预报意见,其中基本上准确的预报意见有7份。2008年以来,共收到26份短临预报意见,尚没有正确预报的短临预报意见。尽管这些意见的准确性非常低,但作为地震主管部门,根据有关法律,欢迎和鼓励个人和团体继续开展地震预报探索。

posted @ 2008-05-21 13:18 矿矿 阅读(106) | 评论 (0)编辑 收藏

package Pro123;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

public class Demo extends JFrame{
    /**
  *
  */
 private static final long serialVersionUID = 1L;
 JOptionPane pane1 = new JOptionPane();
 JFrame frame = new JFrame();
     Container contentPane = frame.getContentPane();
       JLabel Message = new JLabel("请输入邮箱和密码");
       //用户名、密码以及其输入框
       JLabel Name = new JLabel("用户名");
       JLabel Password = new JLabel("密   码");
       JTextField tName = new JTextField(12);
       JPasswordField pPwd = new JPasswordField(12);
       //按扭
       JButton btnDl = new JButton("登陆");
       JButton btnCz = new JButton("重置");
     
      
       JPanel pToppane = new JPanel();
       JPanel pCenterpane = new JPanel();
       JPanel pCenterpaneName = new JPanel();
       JPanel pCenterpanePwd = new JPanel();
       JPanel pButton = new JPanel();
      
       Demo(){
      
       this.setTitle("邮件登陆");//窗口标题
       
       //以下为加入面版
       pCenterpaneName.add(Name);
       pCenterpaneName.add(tName);
      
       pCenterpanePwd.add(Password);
       pCenterpanePwd.add(pPwd);
      
       pCenterpane.add(pCenterpaneName,"North");
       pCenterpane.add(pCenterpanePwd,"South");
      
       pToppane.add(Message);
     
       pButton.add(btnDl);
       pButton.add(btnCz);
       btnDl.addActionListener(new neibu1());
       btnCz.addActionListener(new neibu2());
      
       add(pToppane,"North");
       add(pCenterpane,"Center");
       add(pButton,"South");
      
      
       this.setSize(250,180);//设置大小
       this.setVisible(true);//设置可见
      
       setResizable(false);//禁止拉动窗口大小
       //居中窗口
       Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
    setLocation((screen.width - getSize().width)/2,(screen.height - getSize().height)/2 );
  
      // this.setDefaultCloseOperation(3);//关闭窗口
    this.addWindowListener(new WindowClose());
       }
       //对邮箱的输入格式进行判断
       public boolean validateEmailName(String name){
        String emailName = name.substring(0,name.indexOf('@'));
        boolean booFormat = true;
        int temp = -1;
        for(int i=0;i<emailName.length();i++){
         temp = name.charAt(i);
         A:if(temp<65){
          if(temp>48 && temp<57)
           break A;
          booFormat = false;
          break;
         }
         B:if(temp>90 && temp<97){
          if(temp == 95)
           break B;
          booFormat = false;
          break;
         }
        }
        return booFormat;
       }
       //邮箱检测
       public boolean validateStationName(String name){
        String stationName = name.substring(name.indexOf('@')+1);
        boolean boo = true;
        if(stationName.indexOf('.') == -1){
         boo = false;
        }else if(stationName.indexOf('.') == 0){
         boo = false;
        }
        return boo;
       }
      
       //事件
  
     
      class  neibu1 implements ActionListener {
      public void actionPerformed(ActionEvent e){
       String name = tName.getText().trim();
       String password = new String(pPwd.getPassword()).trim();
       int first = 0;
       @SuppressWarnings("unused")
   boolean booFromat = false;
       boolean boo = false;
      
       boolean booFormat = false;
   if(name.length()>0){
        first = name.charAt(0);
        if(name.indexOf("@")!= -1){
         booFormat = validateEmailName(name);
         boo = validateStationName(name);
        }
       }
       if(name.equals("")){
        Message.setForeground(Color.red);
        Message.setText("请输入邮箱");
       // tName.setText("");//清空输入内容
        pPwd.setText("");//清空输入内容
        tName.grabFocus();
       }else if(name.indexOf("@")== -1){
        Message.setForeground(Color.red);
        Message.setText("您输入邮箱格式错误,不包含“@”");
        //tName.setText("");
        pPwd.setText("");//清空输入内容
        tName.grabFocus();
       }else if(first<65 || (first>90 && first <97)||first>122){
        Message.setForeground(Color.red);
        Message.setText("邮箱首字母应为英文字母");
       // tName.setText("");
        pPwd.setText("");//清空输入内容
        tName.grabFocus();
       }else if(!booFormat){
        Message.setForeground(Color.red);
        Message.setText("邮箱名不和法:只能包含字母、数字、下划线");
        //tName.setText("");
        pPwd.setText("");//清空输入内容
        tName.grabFocus();
       }else if(!boo){
        Message.setForeground(Color.red);
        Message.setText("邮箱后缀不和法");
        //tName.setText("");
        pPwd.setText("");//清空输入内容
        tName.grabFocus();
       }else if(password.equals("")){
        Message.setForeground(Color.red);
        Message.setText("密码不能为空");
        pPwd.setText("");//清空输入内容
        pPwd.grabFocus();
       }else if(password.length()<6){
        Message.setForeground(Color.red);
        Message.setText("密码必须为6位,请检查后重新输入");
        pPwd.setText("");//清空输入内容
        pPwd.grabFocus();
       }else if(name.equals("java@svse.com")&&password.equals("jackrose")){
        Message.setForeground(Color.blue);
        Message.setText("欢迎"+name+"登陆");
       }else{
        Message.setForeground(Color.red);
        Message.setText("邮箱或密码错误!请重新输入!");
        pPwd.setText("");//清空输入内容
        tName.grabFocus();
       }
      }
       }
//    重置键清空输入内容
      class neibu2 implements ActionListener {
    
      public void actionPerformed(ActionEvent e){
       pPwd.setText("");
       tName.setText("");
      }
      }
      class WindowClose extends WindowAdapter{
      public void windowClosing(WindowEvent e){
      
      System.exit(0);
      }
      }
      //MAIN方法
       public static void main(String[]args){
        new Demo();
       }

 
}

posted @ 2008-05-20 18:11 矿矿 阅读(1119) | 评论 (3)编辑 收藏
字符串
1、获取字符串的长度
length()
2 、判断字符串的前缀或后缀与已知字符串是否相同
前缀 startsWith(String s)
后缀 endsWith(String s)
3、比较两个字符串
equals(String s)
4、把字符串转化为相应的数值
int型 Integer.parseInt(字符串)
long型 Long.parseLong(字符串)
float型 Folat.valueOf(字符串).floatValue()
double型 Double.valueOf(字符串).doubleValue()
4、将数值转化为字符串
valueOf(数值)
5、字符串检索
indexOf(Srting s) 从头开始检索
indexOf(String s ,int startpoint) 从startpoint处开始检索
如果没有检索到,将返回-1
6、得到字符串的子字符串
substring(int startpoint) 从startpoint处开始获取
substring(int start,int end) 从start到end中间的字符
7、替换字符串中的字符,去掉字符串前后空格
replace(char old,char new) 用new替换old
trim()
8、分析字符串
StringTokenizer(String s) 构造一个分析器,使用默认分隔字符(空格,换行,回车,Tab,进纸符)
StringTokenizer(String s,String delim) delim是自己定义的分隔符

nextToken() 逐个获取字符串中的语言符号
boolean hasMoreTokens() 只要字符串还有语言符号将返回true,否则返回false
countTokens() 得到一共有多少个语言符号


文本框和文本区

1、文本框
TextField() 构造文本框,一个字符长
TextField(int x) 构造文本框,x个字符长
TextField(String s) 构造文本框,显示s
setText(String s) 设置文本为s
getText() 获取文本
setEchoChar(char c) 设置显示字符为c
setEditable(boolean) 设置文本框是否可以被修改
addActionListener() 添加监视器
removeActionListener() 移去监视器
2、文本区
TextArea() 构造文本区
TextArea(String s) 构造文本区,显示s
TextArea(String s,int x,int y) 构造文本区,x行,y列,显示s
TextArea(int x,int y) 构造文本区,x行,y列
TextArea(String s,int x,ing y,int scrollbar)
scrollbar的值是:
TextArea.SCROLLBARS_BOTH
TextArea.SCROLLBARS_VERTICAL_ONLY
TextArea.SCROLLBARS_HORIZONTAL_ONLY
TextArea.SCROLLBARS_NONE
setText(String s) 设置文本为s
getText() 获取文本
addTextListener() 添加监视器
removeTextListener() 移去监视器
insert(String s,int x) 在x处插入文本s
replaceRange(String s,int x,int y) 用s替换从x到y处的文本
append(String s) 在文本的最后追加文本s
Int getCaretPosition(int n) 获取文本区中光标的位置

按钮

1、按钮
Button() 构造按钮
Button(String s) 构造按钮,标签是s
setLabel(String s) 设置按钮标签是s
getLabel() 获取按钮标签
addActionListener() 添加监视器
removeActionListener() 移去监视器

标签

1、标签
Label() 构造标签
Label(String s) 构造标签,显示s
Label(String s,int x)
x是对齐方式,取值:
Label.LEFT
Label.RIGHT
Label.CENTER
setText(String s) 设置文本s
getText() 获取文本
setBackground(Color c) 设置标签背景颜色
setForeground(Color c) 设置字体颜色


选择框

1、选择框
Checkbox() 构造选择框
Checkbox(String s) 构造选择框,给定标题s
Checkbox(String s,boolean b) b设定初始状态
Checkbox(String s,boolean b,CheckboxGroup g) g设定了所属的组(有了组就成为单选框)
addItemListener() 添加监视器
removeItemListener() 移去监视器
getState() 返回选择框的是否选中状态
setState(boolean b) 设置选择框的状态
getLabel() 获取选择框的标题
setLabel(String s) 设置选择框的标题为s

选择控件和滚动列表

1、选择控件
Choice() 构造选择控件
add(String s) 向选择控件增加一个选项
addItemListener() 添加监视器
removeItemListener() 移去监视器
getSelectedIndex() 返回当前选项的索引
getSelectedItem() 返回当前选项的字符串代表
insert(String s,int n) 在n处插入选项s
remove(int n)
removeAll()
2、滚动列表
List() 构造滚动列表
List(int n) 参数n是可见行数
List(int n,boolean b) 参数b是设置是否可以多项选择
add(String s) 向列表的结尾增加一个选项
add(String s,int n) 在n处增加一个选项
AddActionListener() 滚动列表添加监视器
addItemListener() 滚动列表上的选项添加监视器
remove(int n) 删除n初的选项
remnoveAll() 删除全部选项
getSelectedIndex() 返回当前选项的索引
getSelectedItem() 返回当前选项的字符串代表


3、组件类的一些常用方法
void setBackground(Color c) 设置组件背景颜色
void setForeground(Color c) 设置组件前景颜色
void setFonts(Font f) 设置组件字体
void setBounds(int x,int y,int w,int h) 设置坐标,x,y表示在容器中坐标,w,h表示宽和高
void setLocation(int x,int y) 移动到x,y 处
void setSize(int w,int h) 设置宽和高
void setVisible(boolean b) 设置组建是否可见
int getBounds().wigth 获取宽
int getBounds().height 获取高
int getBounds().x 获取x 坐标
int getBounds().y 获取y 坐标
Toolkit getToolkit() 获取工具包对
void setEnabled(boolean b) 设置是否可以使用(默认可以)

窗口和菜单
1、窗口
Frame() 构造窗口
Frame(String s) 窗口标题是s
setBounds(int x,int y,int w,int h) 窗口位置x,y,宽w,高y
setSize(int w,int h) 设置窗口位置(单位是像素)
setBackground(Color c) 设置背景颜色
setVisible(boolean b) 设置窗口是否可见
pack() 窗口出现时紧凑
setTitle(String s) 设置标题为s
getTitle() 获取标题
setResizable(boolean b) 设置窗口大小是否可以调整
2、菜单条
Menubar() 构造菜单条
setMenubar() 窗口添加菜单条
3、菜单
Menu() 构造菜单
Menu(String s) 构造菜单,标题s
add
add(MenuItem item) 菜单增加菜单选项item
add(String s) 向菜单增加选项s
getItem(int n) 获取n处的选项
getItemCount() 获取选项数目
insert(MenuItem item,int n) 在n处插入菜单选项item
insert(String s,int n) 在n处插入菜单选项
remove(int n) 删除菜单的n处的菜单选项
removeAll() 删除全部
4、菜单项
MenuItem() 构造菜单项
MenuItem(String s) 构造标题是s的菜单项
setEnabled(boolean b) 设置是否可以被选择
getLabel() 得到菜单选项名
addActionListener() 添加监视器
5、有关菜单的技巧
addSeparator() 增加菜单分割线
CheckboxMenuItem() 复选框菜单项
setShortcut(MenuShortcut k) 设置快捷键(k取值KeyEvent.VK_A----KeyEvent.VK_Z)



建立对话框
1、Dialog类
Dialog(Frame f,String s) 构造对话框,初始不可见,s是标题,f是对话框所依赖的窗口
Dialog(Frame f,String s,boolean b) b设置初始是否可见
getTitle() 获取对话框标题
setTitle(String s) 设置对话框标题
setModal(boolean b) 设置对话框模式
setSize(int w,int h) 设置对话框大小
setVisible(boolean b) 显示或隐藏对话框
2、FileDialog类
Filedialog(Frame f,String s,int mode) mode的值是fileDialog.LOAD或者fileDialog.SAVE
public String getDirectory() 获取当前文件对话框中显示的文件所属目录
public String getFile() 获取当前文件对话框中文件的字符串表示,不存在返回null

Java中的鼠标和键盘事件
1、使用MouseListener借口处理鼠标事件
鼠标事件有5种:按下鼠标键,释放鼠标键,点击鼠标键,鼠标进入和鼠标退出
鼠标事件类型是MouseEvent,主要方法有:
getX(),getY() 获取鼠标位置
getModifiers() 获取鼠标左键或者右键
getClickCount() 获取鼠标被点击的次数
getSource() 获取鼠标发生的事件源
事件源获得监视器的方法是addMouseListener(),移去监视器的方法是removeMouseListener()


处理事件源发生的时间的事件的接口是MouseListener 接口中有如下的方法
mousePressed(MouseEvent) 负责处理鼠标按下事件
mouseReleased(MouseEvent) 负责处理鼠标释放事件
mouseEntered(MouseEvent) 负责处理鼠标进入容器事件
mouseExited(MouseEvent) 负责处理鼠标离开事件
mouseClicked(MouseEvent) 负责处理点击事件
2、使用MouseMotionListener接口处理鼠标事件
事件源发生的鼠标事件有2种:拖动鼠标和鼠标移动
鼠标事件的类型是MouseEvent
事件源获得监视器的方法是addMouseMotionListener()
处理事件源发生的事件的接口是MouseMotionListener 接口中有如下的方法
mouseDragged() 负责处理鼠标拖动事件
mouseMoved() 负责处理鼠标移动事件
3、控制鼠标的指针形状
setCursor(Cursor.getPreddfinedCursor(Cursor.鼠标形状定义)) 鼠标形状定义见(书 P 210)
4、键盘事件
键盘事件源使用addKeyListener 方法获得监视器
键盘事件的接口是KeyListener 接口中有3个方法
public void keyPressed(KeyEvent e) 按下键盘按键
public void keyReleased(KeyEvent e) 释放键盘按键
public void keyTypde(KeyEvent e) 按下又释放键盘按键

Java多线程机制
1、Java的线程类与Runnable接口
Thread类
public Thread() 创建线程对象
public Thread(Runnable target) target 称为被创建线程的目标对象,负责实现Runnable接口
线程优先级
Thread类有三个有关线程优先级的静态常量:MIN_PRIORITY,MAX_PRIORITY,NORM_PRIORITY
新建线程将继承创建它的副相承的优先级,用户可以调用Thread类的setPriority(int a)来修改
a的取值:
Thread.MIN_PRIORITY,Thread.MAX_PRIORITY,Thread.NORM_PRIORITY
主要方法
启动线程 start()
定义线程操作 run()
使线程休眠 sleep()
sleep(int millsecond) 以毫秒为单位的休眠时间
sleep(int millsecond,int nanosecond) 以纳秒为单位的休眠时间
currentThread() 判断谁在占用CPU的线程
第二十章 输入输出流
1、FileInputStream类
FileInputStream(String name) 使用给定的文件名name创建一个FileInputStream对象
FileInputStream(File file) 使用File对象创建FileInpuStream对象
File类有两个常用方法:
File(String s) s确定文件名字
File(String directory,String s) directory是文件目录


例如:
File f=new File("Myfile.dat");
FileInputStream istream=new FileInputStream(f);
处理I/O异常
当出现I/O错误的时候,Java生成一个IOException(I/O异常)对象来表示这个错误的信号。
程序必须使用一个catch检测这个异常
例如:
try{
FileInputStream ins= new FileInputStream("Myfile.dat");
}
catch(IOException e){
System.out.println("File read Error:"+e);
}
从输入流中读取字节
int read() 返回0~255之间一个整数,如果到输入流末尾,则返回-1
int read(byte b[]) 读取字节数组
int read(byte b[],int off,int len) off指定把数据存放在b中什么地方,len指定读取的最大字节数
关闭流
close()
2、FileOutputStream类
FileOutputStream(String name) 使用指定的文件名name创建FileOutputStream对象
FileOutputStream(File file) 使用file对象创建FileOutputStream对象
FileOutputStream(FileDescriptor fdobj) 使用FileDescriptor对象创建FileOutputStream对象
3、FileReader类和FileWriter类
FileReader(String filename)


FileWriter(String filename)
处理时需要FileNotFoundException异常
4、RandomAccessFile类
RandomAccessFile不同于FileInputStream和FileOutputStream,不是他们的子类
当我们想对一个文件进行读写操作的时候,创建一个指向该文件的RandomAccessFile流就可以了
RandomAccessFile类有两个构造方法:
RandomAccessFile(String name, String mode) name是文件名,mode取r(只读)或rw(读写)
RandomAccessFile(File file,String mode) file给出创建流的源
seek(long a) 移动RandomAccessFile流指向文件的指针,a确定指针距文件开头的位置
getFilePointer() 获取当前文件的指针位置
close() 关闭文件
getFD() 获取文件的FileDescriptor
length() 获取文件长度
read() 读取一个字节数据
readBoolean() 读取一个布尔值
readByte() 读取一个字节
readChar()
readFloat()
readFully(byte b[])
readInt()
readLine()
readLong()
readUnsignedShort()
readUTF() 读取一个UTF字符串
setLength(long newLength) 设置文件长度
skipByte(int n) 在文件中跳过给定数量的字节
write(byte b[]) 写b.length个字节到文件
writeBoolean(bolean b)
writeByte(int v)
writeChar(char c)
writeChars(String s)
writeDouble(double d)
writeFloat(float v)
writeInt(int i)
writeLong(long l)
writeShort(int i)
writeUTF(String s)
5、管道流
PipedInputStream类
PipedInputStream() 创建一个管道输入流
PipedInputStream(PipedOutputStream a) 连接到输出流a的输入流
read() 从输入流中读取一个字节
read(byte b[],int off,int len) off是在b中的开始位置,len是字节长度
PipedOutputStream类
PipedOutputStream() 创建一个输出流
PipedOutputStream(PipedInputStream a) 连接到输入流a的输出流
write(int b)
write(byte b[],int off,int len)
counnect() 连接输入输出流
close() 关闭流
在使用的时候要捕获IOException异常。
6、数据流
DataInputStream类(数据输入流)
DataInputStream(InputStream in) 将数据输入流指向一个由in指定的输入流
DataOutputStream类(数据输出流)
DataOutputStream(OutputStream out) 将数据输出流指向一个由out指定的输出流
主要方法:
close()
read() 读取一个字节数据
readBoolean() 读取一个布尔值
readByte() 读取一个字节
readChar()
readFloat()
readFully(byte b[])
readInt()
readLine()
readLong()
readUnsignedShort()
readUTF() 读取一个UTF字符串
skipByte(int n) 在文件中跳过给定数量的字节
write(byte b[]) 写b.length个字节到文件
writeBoolean(bolean b)
writeByte(int v)
writeChar(char c)
writeChars(String s)
writeDouble(double d)
writeFloat(float v)
writeInt(int i)
writeLong(long l)
writeShort(int i)
writeUTF(String s)
7、对象流
ObjectInputStream类和ObjectOutputStream类分别是DataInputStream类和DataOutputStream类的子类
8、回压输入流
PushbackInputStream类
PushbackInputStream(InputStream in)
PushbackReader类
PushbackReader(Reader in)
unread(char c) 回压一个字符
unread(char c[]) 回压数组c中全部字符
unread(char c[],offset,int n) 回压c中从offset开始的n个字符

java网络的基本知识
1、使用URL(统一资源定位)
例如:
try
{
url=new URL("http://www.sina.com.cn";
}
catch(MalformedURLException e)
{
System.out.println("Bad URL:"+url);
}
在Applet 中链接向另外的Web页面,使用代码:
getAppletContext().showDocument(url);
2、套接字
客户建立到服务器的套接字(Socket)
Socket(String host,int port) host是服务器的IP地址,port是端口号
建立了套接字后可以使用getInputStream()获得输入流
还可以使用getOutputStream()获得一个输出流
服务器建立接受客户套接字的服务器套接字(ServerSocket)
ServerSocket(int port) port是端口号
建立了套接字连接后可以使用accept()接收客户的套接字
可以使用getOutputStream()获得一个输出流
还可以使用getInputStream()获得一个输入流
3、InetAddress类
getByName(String )
3、InetAddress类
getByName(String s) 获取Internet上主机的地址
getHostName() 获取InetAddress对象所包含的域名
getHostAddress() 获取InetAddress对象所包含的IP地址


getLocalHost() 获取本地地址
4、UDP数据报
发送数据包,即使用DatagramPacket类将数据打包,有两种构造方法
DatagramPacket(byte data[],int length,InetAddress address,int port)
?含有data数组的数据
?该数据包将发送到地质是address,端口是port的主机上
DatagramPacket(byte data[],int offset,int length,InetAddress address,int port)
?含有data数组的从offset开始,length长度的数据
?该数据包将发送到地质是address,端口是port的主机上
接收数据包,即使用DatagramSocket(int port)创建一个对象,port必须和待接收的数据包的端口相同
例如:
如果发送方的数据包端口是5566
DatagramSocket mail=new DatagramSocket(5566);
然后对象mail可以使用方法receive(Datagrampacket pack)接收数据包
在使用参数pack 接收数据包前,必须创建pack
byte data[]=new byte[100];
int length=90;
DatagramPacket pack=new DatagramPataet(data,length);
mail.receive(pack);
该数据包pack将接收长度是length的数据放入data,注意数据长度不要超过8192KB
pack还可以调用方法getPort()获取所接受数据包是从什么端口发出的


调用方法InetAddress getAddress()可以获知数据包来自哪个主机

Java与图像
1、java支持的图像类型:GIF,JPEG,BMP
2、Image类
首先申请一个Image对象
Image img =getImage(URL url,String name) url是图像地址,name是图片名称
通常使用:
Image img =getImage(getCodBase(),String name) getCodBase()获取当前小应用程序的URL,也就是在同一目录下
图像被加载后,就可以在paint()中绘制了
drawImage(Image img,int x,int y,ImageObserver observer)
img是上面获取的图像, x,y是指定图像左上角的位置,observer是加载图像时的图像观察器
Applet类已经实现了ImageObserver接口,所以可以直接使用this作为最后一个参数
drawImage(Image img,int x,int y,int width,int height,ImageObserver observer)
width和height是要绘制的图像的宽和高
可以使用img.getHeight(this)和img.getWidth(this)来获取被加载的图像的宽和高
3、设置Java窗口图标
Frame对象可以使用setIconImage(Image img)方法设置左上角图标,默认图标是咖啡杯

Java数据库连接(JDBC)
1、JDBC-ODBC桥接器
建立JDBC-ODBC桥接器
try
{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
}
catch(ClassNotFoundException e){}
连接到数据库
try
{
Connection con=DriverManager.getConnection("jdbcdbc:数据源名称","数据源的login name",
"数据源的password");
}
catch(SQLException e){}
向数据库发送SQL语句
try
{
Statement sql=con.createStatement();
}
catch(SQLException e){}
处理查询结果
ResultSet rs=sql.executeQuery("SQL语句");
第二十四章 Java与多媒体
1、在小程序中播放声音
java可以播放au,aiff,wav,midi,rfm格式的音频
可以调用Applet的一个静态方法:
newAudioClip(URL url,String name) url是地址,name是音频名称
也可以用Applet类的实例方法:
getAudioClip(URL url,String name)
根据url地址和声音文件name,获得一个用于播放的音频对象,这对象可以使用下面的方法来处理声音:
play() 播放声音文件name
loop() 循环播放name
stop() 停止播放name
2、Java媒体框架(JMF)
创建播放器

try
{
URL url=new URL(getDocumenBase(),视频文件名称);
player player=Manager.createPlayer(url);
}
catch(IOException e){}
向播放器注册控制监视器
player.addControllerListener(监视器);
创建监视器必须使用接口ControllerListener ,该接口中的方法是
public void controllerUpdate(ControllerEvent e)
让播放器对媒体进行预提取
player.prefetch()
启动播放器
player.start();
停止播放器
player.stop();
停止播放器后必须释放内存中的资源
player.deallocate();

Java Swing基础
1、Jcomponent类
Jcomponent类 是所有轻量组件的父类,主要的子类有:
JButton 创建按钮对象,而且可以创建在图标的按钮
JComboBox 创建组合框对象,和Choice相似
JCheckBox 创建复选框对象
JFileChooser 创建文件选择器
JInternalFrame 创建内部窗体
JLabel 创建标签
JMenu 创建菜单对象
JMenuBar 创建菜单条对象
JMenuItem 创建菜单项对象
JPanel 创建面板对象
JPasswordField 创建口令文本对象
JPopupMenu 创建弹出式菜单

JProgressBar 创建进程条
JRadioButton 创建单选按钮
JScrollBar 创建滚动条
JScrollPane 创建滚动窗格
JSlider 创建滚动条
JSplitPane 创建拆分窗格
JTable 创建表格
JTextArea 创建文本区
JTexPane 创建文本窗格
JToolBar 创建工具条
JToolTip 创建工具提示对象
JTree 创建树对象
2、JFrame类
JFrame类及其子类创建的对象是窗体
(1)JFrame类及其子类创建的窗体是swing窗体
(2)不可以把组件直接加到swing窗体中,应该把组件加到内容面板中
(3)不能为swing窗体设置布局,而应当为内容面板设置布局
(4)swing窗体通过调用getContentPane()方法得到它的内容面板
3、JApplet类
(1)不可以把组件直接添加到小程序容器中,也应该添加到内容面板中
(2)不能为小程序设置布局
(3)小程序容器通过调用getContenPane()方法得到内容面板
4、JDialog类
(1)不可以把组件直接添加到对话框容器中,也应该添加到内容面板中
(2)不能为对话框设置布局
(3)对话框容器通过调用getContenPane()方法得到内容面板
5、JPanel面板
JPanel()
JPanel(布局对象)
6、滚动窗口JScrollPane
JScrollPane()
JScrollPane(component c)
7、拆分窗口JSplitPane
JSplitPane(int a,Component b,Component c)
a的取值是HORIZONTAL_SPLIT或者VERTICAL_SPLIT决定水平拆分还是垂直拆分
JSplitPane(int a,boolean b ,Component b,Component c) b的取值决定拆分线移动的时候组件是否连续变化
8、内部窗体JInternalFrame
JInternalFrame(String title,boolean resizable,booleam closable,boolean max,boolean min)
参数的意义分别是窗口名称,是否能调整大小,是否有关闭按钮,最大化按钮,最小化按钮
(1)不能把组件直接加到窗体中,而是加到内容面板中
(2)必须先把内部窗体加到一个容器中(JDesktopPane),该容器是专门为内部窗体服务的
9、按钮(JButton)
JButton() 创建按钮
JButton(String s) s是按钮的名字
JButton(Icon icon) icon是按钮上的图标
JButton(String s,Icon icon)
getText() 获取按钮名字
getIcon() 获取按钮图标
setIcon(Icon icon) 设置按钮图标
setHorizontalTextposition(int a) a确定按钮上图标的位置,取值:
AbstractButton_CENTR,AbstractButton_LEFT,AbstractButton_RIGHT
setVerticalTextposition(int a) a确定按钮上名字相对图标的位置,取值:
AbstractButton.TOP,AbstractButton.BOTTOM,AbstractButton.CENTR
setMnemonic(char c) 设置按钮的键盘操作方式是字符c(Alt+c)
setEnabled(boolean b) b决定按钮是否可以被单击
posted @ 2008-05-16 18:43 矿矿 阅读(4433) | 评论 (1)编辑 收藏
17.你需要学习企业级JavaBeans(EJB)以及它们的不同组件模式:Stateless/StatefulSessionBeans,EntityBeans(包含Bean- ManagedPersistence[BMP]或者Container-ManagedPersistence[CMP]和它的EJB-QL),或者 Message-DrivenBeans(MDB)。

  18.你需要学习如何管理与配置一个J2EE应用程序服务器,如WebLogic,JBoss等,并且利用它的附加服务,例如簇类,连接池以及分布式处理支援。你还需要了解如何在它上面封装和配置应用程序并且能够监控、调整它的性能。

  19.你需要熟悉面向方面的程序设计以及面向属性的程序设计(这两个都被很容易混淆的缩写为AOP),以及他们的主流JAVA规格和执行。例如AspectJ和AspectWerkz。

  20.你需要熟悉对不同有用的API和framework等来为你服务。例如Log4J(logging/tracing),Quartz (scheduling),JGroups(networkgroupcommunication),JCache(distributedcaching), Lucene(full-textsearch),JakartaCommons等等。

21.如果你将要对接或者正和旧的系统或者本地平台,你需要学习JNI (JavaNativeInterface) and JCA (JavaConnectorArchitecture)。

  22.你需要熟悉JINI技术以及与它相关的分布式系统,比如掌握CROBA。

  23.你需要JavaCommunityProcess(JCP)以及他的不同JavaSpecificationRequests(JSRs),例如Portlets(168),JOLAP(69),DataMiningAPI(73),等等。

  24.你应该熟练掌握一种JAVAIDE例如sunOne,netBeans,IntelliJIDEA或者Eclipse。(有些人更喜欢VI或EMACS来编写文件。随便你用什么了:)

  25.JAVA(精确的说是有些配置)是冗长的,它需要很多的人工代码(例如EJB),所以你需要熟悉代码生成工具,例如XDoclet。

  26.你需要熟悉一种单元测试体系(JNunit),并且学习不同的生成、部署工具(Ant,Maven)。

  27.你需要熟悉一些在JAVA开发中经常用到的软件工程过程。例如RUP(RationalUnifiedProcess)andAgilemethodologies。

  28.你需要能够深入了解加熟练操作和配置不同的操作系统,比如GNU/linux,sunsolaris,macOS等,做为跨平台软件的开发者。

  29.你还需要紧跟java发展的步伐,比如现在可以深入的学习javaME,以及各种java新规范,技术的运用,如新起的web富客户端技术。

  30.你必需要对opensource有所了解,因为至少java的很多技术直接是靠开源来驱动发展的,如java3D技术。

posted @ 2008-05-08 15:08 矿矿 阅读(907) | 评论 (0)编辑 收藏
17.你需要学习企业级JavaBeans(EJB)以及它们的不同组件模式:Stateless/StatefulSessionBeans,EntityBeans(包含Bean- ManagedPersistence[BMP]或者Container-ManagedPersistence[CMP]和它的EJB-QL),或者 Message-DrivenBeans(MDB)。

  18.你需要学习如何管理与配置一个J2EE应用程序服务器,如WebLogic,JBoss等,并且利用它的附加服务,例如簇类,连接池以及分布式处理支援。你还需要了解如何在它上面封装和配置应用程序并且能够监控、调整它的性能。

  19.你需要熟悉面向方面的程序设计以及面向属性的程序设计(这两个都被很容易混淆的缩写为AOP),以及他们的主流JAVA规格和执行。例如AspectJ和AspectWerkz。

  20.你需要熟悉对不同有用的API和framework等来为你服务。例如Log4J(logging/tracing),Quartz (scheduling),JGroups(networkgroupcommunication),JCache(distributedcaching), Lucene(full-textsearch),JakartaCommons等等。

21.如果你将要对接或者正和旧的系统或者本地平台,你需要学习JNI (JavaNativeInterface) and JCA (JavaConnectorArchitecture)。

  22.你需要熟悉JINI技术以及与它相关的分布式系统,比如掌握CROBA。

  23.你需要JavaCommunityProcess(JCP)以及他的不同JavaSpecificationRequests(JSRs),例如Portlets(168),JOLAP(69),DataMiningAPI(73),等等。

  24.你应该熟练掌握一种JAVAIDE例如sunOne,netBeans,IntelliJIDEA或者Eclipse。(有些人更喜欢VI或EMACS来编写文件。随便你用什么了:)

  25.JAVA(精确的说是有些配置)是冗长的,它需要很多的人工代码(例如EJB),所以你需要熟悉代码生成工具,例如XDoclet。

  26.你需要熟悉一种单元测试体系(JNunit),并且学习不同的生成、部署工具(Ant,Maven)。

  27.你需要熟悉一些在JAVA开发中经常用到的软件工程过程。例如RUP(RationalUnifiedProcess)andAgilemethodologies。

  28.你需要能够深入了解加熟练操作和配置不同的操作系统,比如GNU/linux,sunsolaris,macOS等,做为跨平台软件的开发者。

  29.你还需要紧跟java发展的步伐,比如现在可以深入的学习javaME,以及各种java新规范,技术的运用,如新起的web富客户端技术。

  30.你必需要对opensource有所了解,因为至少java的很多技术直接是靠开源来驱动发展的,如java3D技术。

posted @ 2008-05-08 15:08 矿矿 阅读(1148) | 评论 (3)编辑 收藏
封装数据库操作,目的就是为了隐藏java.sql包内的类,在编码中去掉核心的数据库操作代码。以杜绝直接数据库操作容易带来的资源未释放问题。同时也减少了数据库操作的编码量。

  但是很多网友在封装时,却喜欢返回结果集(ResultSet对象),那么这个封装就没有意义了。

  1. 又是直接操作核心数据库类,跟封装前几乎没什么变化。

  2. 结果集总是依赖于它使用的连接(Connection)对象。因此当连接对象在方法内被关闭后,你返回的ResultSet就没有用了。

  如果真的要获得查询数据库的结果集,就把结果集对象内的所有数据,转储到以Map为元素的List对象内。

  当然,这种方式,不能适应大数据量的查询,不过如果真的碰到大数据量的查询,那用什么封装都不好,还是得直接数据库操作. :)))

  下面是简单的数据库操作Javabean的代码

  DbWrapper.java

  import java.sql.*;

  import java.util.*;

  public class DbWrapper

  {

  // 定义连接池对象为静态变量,将一直存在,直到工作目录关闭。

  private static DataSource ds = null;

  // 1.用连接池的方式获得连接

  // 如果不是做多数据库程序,推荐使用此方法

  // 相关内容:在tomcat管理界面配置连接池

  public static Connection openConnection() throws Exception

  {

  // 只需要初始化1次

  if ( ds == null )

  {

  Context initContext = new InitialContext();

  Context envContext = (Context) initContext.lookup("java:/comp/env");

  DataSource ds = (DataSource) envContext.lookup("jdbc/MyDataSource");

  }

  return ds.getConnection();

  }

  // 2.用jdbc驱动获得连接

  // 相关内容:JSP数据库连接大全

  public static Connection openConnection(

  String driver,

  String url,

  String username,

  String password)

  throws Exception

  {

  Class.forName(driver).newInstance();

  return DriverManager.getConnection(url, username, password);

  }

  public static void closeConnection(Connection conn) throws Exception

  {

  if ( conn != null )

  {

  conn.close();

  }

  }

  public static int executeUpdate(String sql) throws Exception

  {

  int count = 0;

  Connection conn = null;

  Statement stmt = null;

  try

  {

  conn = openConnection();

  stmt = conn.createStatement();

  count = stmt.executeUpdate(sql);

  }

  catch ( Exception e )

  {

  throw e;

  }

  finally

  {

  closeConnection(conn);

  }

  return count;

  }

  public static List executeQuery(String sql) throws Exception

  {

  List list = new ArrayList();

  Connection conn = null;

  Statement stmt = null;

  ResultSet rs = null;

  try

  {

  conn = openConnection();

  stmt = conn.createStatement();

  rs = stmt.executeQuery(sql);

  ResultSetMetaData rsmd = rs.getMetaData();

  while ( rs.next() )

  {

  Map map = new HashMap();

  for ( int i = 1; i < = rsmd.getColumnCount(); i++ )

  {

  map.put(rsmd.getColumnName(i), rs.getObject(i));

  }

  list.add(map);

  } }

  catch ( Exception e )

  {

  e.printStackTrace();

  }

  finally

  {

  if ( rs != null ) rs.close();

  closeConnection(conn);

  }

  return list; }

  }

  使用示例:

  // 1.对于insert, update, delete语句int count = DbWrapper.executeUpdate(sql);

  // 2.对于selete语句

  java.util.List list = DbWrapper.executeQuery(sql);

  // 方法一:按名字取值,注意大小写是严格区分的

  for ( int i = 0; i < list.size(); i++ )

  {

  java.util.Map map = (java.util.Map)list.get(i);

  out.println(mag.get("column_name").toString());

  }

  // 方法二:遍历取值

  for ( int i = 0; i < list.size(); i++ )

  {

  java.util.Map map = (java.util.Map)list.get(i);

  for (java.util.Iterator it = map.keySet().iterator(); it.hasNext();)

  {

  String column_name = it.next().toString()); // 取值时注意null判断

  out.println(column_name + " = " + map.get(column_name) == null ? "" : map.get(column_name).toString());

  }

  }

posted @ 2008-05-07 18:52 矿矿 阅读(132) | 评论 (0)编辑 收藏
封装数据库操作,目的就是为了隐藏java.sql包内的类,在编码中去掉核心的数据库操作代码。以杜绝直接数据库操作容易带来的资源未释放问题。同时也减少了数据库操作的编码量。

  但是很多网友在封装时,却喜欢返回结果集(ResultSet对象),那么这个封装就没有意义了。

  1. 又是直接操作核心数据库类,跟封装前几乎没什么变化。

  2. 结果集总是依赖于它使用的连接(Connection)对象。因此当连接对象在方法内被关闭后,你返回的ResultSet就没有用了。

  如果真的要获得查询数据库的结果集,就把结果集对象内的所有数据,转储到以Map为元素的List对象内。

  当然,这种方式,不能适应大数据量的查询,不过如果真的碰到大数据量的查询,那用什么封装都不好,还是得直接数据库操作. :)))

  下面是简单的数据库操作Javabean的代码

  DbWrapper.java

  import java.sql.*;

  import java.util.*;

  public class DbWrapper

  {

  // 定义连接池对象为静态变量,将一直存在,直到工作目录关闭。

  private static DataSource ds = null;

  // 1.用连接池的方式获得连接

  // 如果不是做多数据库程序,推荐使用此方法

  // 相关内容:在tomcat管理界面配置连接池

  public static Connection openConnection() throws Exception

  {

  // 只需要初始化1次

  if ( ds == null )

  {

  Context initContext = new InitialContext();

  Context envContext = (Context) initContext.lookup("java:/comp/env");

  DataSource ds = (DataSource) envContext.lookup("jdbc/MyDataSource");

  }

  return ds.getConnection();

  }

  // 2.用jdbc驱动获得连接

  // 相关内容:JSP数据库连接大全

  public static Connection openConnection(

  String driver,

  String url,

  String username,

  String password)

  throws Exception

  {

  Class.forName(driver).newInstance();

  return DriverManager.getConnection(url, username, password);

  }

  public static void closeConnection(Connection conn) throws Exception

  {

  if ( conn != null )

  {

  conn.close();

  }

  }

  public static int executeUpdate(String sql) throws Exception

  {

  int count = 0;

  Connection conn = null;

  Statement stmt = null;

  try

  {

  conn = openConnection();

  stmt = conn.createStatement();

  count = stmt.executeUpdate(sql);

  }

  catch ( Exception e )

  {

  throw e;

  }

  finally

  {

  closeConnection(conn);

  }

  return count;

  }

  public static List executeQuery(String sql) throws Exception

  {

  List list = new ArrayList();

  Connection conn = null;

  Statement stmt = null;

  ResultSet rs = null;

  try

  {

  conn = openConnection();

  stmt = conn.createStatement();

  rs = stmt.executeQuery(sql);

  ResultSetMetaData rsmd = rs.getMetaData();

  while ( rs.next() )

  {

  Map map = new HashMap();

  for ( int i = 1; i < = rsmd.getColumnCount(); i++ )

  {

  map.put(rsmd.getColumnName(i), rs.getObject(i));

  }

  list.add(map);

  } }

  catch ( Exception e )

  {

  e.printStackTrace();

  }

  finally

  {

  if ( rs != null ) rs.close();

  closeConnection(conn);

  }

  return list; }

  }

  使用示例:

  // 1.对于insert, update, delete语句int count = DbWrapper.executeUpdate(sql);

  // 2.对于selete语句

  java.util.List list = DbWrapper.executeQuery(sql);

  // 方法一:按名字取值,注意大小写是严格区分的

  for ( int i = 0; i < list.size(); i++ )

  {

  java.util.Map map = (java.util.Map)list.get(i);

  out.println(mag.get("column_name").toString());

  }

  // 方法二:遍历取值

  for ( int i = 0; i < list.size(); i++ )

  {

  java.util.Map map = (java.util.Map)list.get(i);

  for (java.util.Iterator it = map.keySet().iterator(); it.hasNext();)

  {

  String column_name = it.next().toString()); // 取值时注意null判断

  out.println(column_name + " = " + map.get(column_name) == null ? "" : map.get(column_name).toString());

  }

  }

posted @ 2008-05-07 18:52 矿矿 阅读(141) | 评论 (0)编辑 收藏
XML是eXtensible Markup Language的缩写。扩展标记语言XML是一种简单的数据存储语言,使用一系列简单的标记描述数据,而这些标记可以用方便的方式建立,虽然XML占用的空间比二进制数据要占用更多的空间,但XML极其简单易于掌握和使用。

XML与Access,Oracle和SQL Server等数据库不同,数据库提供了更强有力的数据存储和分析能力,例如:数据索引、排序、查找、相关一致性等,XML仅仅是展示数据。事实上XML与其他数据表现形式最大的不同是:他极其简单。这是一个看上去有点琐细的优点,但正是这点使XML与众不同。

XML的简单使其易于在任何应用程序中读写数据,这使XML很快成为数据交换的唯一公共语言,虽然不同的应用软件也支持其它的数据交换格式,但不久之后他们都将支持XML,那就意味着程序可以更容易的与Windows、Mac OS, Linux以及其他平台下产生的信息结合,然后可以很容易加载XML数据到程序中并分析他,并以XML格式输出结果。

XML的前身是SGML(The Standard Generalized Markup Language),是自IBM从60年代就开始发展的GML(Generalized Markup Language)

HTML一样, XML (可扩展标识语言)是通用标识语言标准(SGML)的一个子集,它是描述网络上的数据内容和结构的标准。尽管如此,XML不象HTML,HTML仅仅提供了在页面上显示信息的通用方法(没有上下文相关和动态功能) ,XML则对数据赋予上下文相关功能,它继承了SGML的大部分功能,却使用了不太复杂的技术。.

为了使得SGML显得用户友好,XML重新定义了SGML的一些内部值和参数,去掉了大量的很少用到的功能,这些繁杂的功能使得SGML在设计网站时显得复杂化。XML保留了SGML的结构化功能,这样就使得网站设计者可以定义自己的文档类型,XML同时也推出一种新型文档类型,使得开发者也可以不必定义文档类型。

因为XML是W3C制定的,XML的标准化工作由W3C的XML工作组负责,该小组成员由来自各个地方和行业的专家组成,他们通过email交流对XML标准的意见,并提出自己的看法 (www.w3.org/TR/WD-xml)。因为XML 是个公共格式, (它不专属于任何一家公司),你不必担心XML技术会成为少数公司的盈利工具,XML不是一个依附于特定浏览器的语言

XML(可扩展标记语言)是从称为SGML(标准通用标记语言)的更加古老的语言派生出来的。SGML的主要目的是定义使用标签来表示数据的标记语言的语法。

标签由包围在一个小于号(<)和一个大于号(>)之间的文本组成,例如<tag>。起始标签(start tag)表示一个特定区域的开始,例如<start>;结束标签(end tag)定义了一个区域的结束,除了在小于号之后紧跟着一个斜线(/)外,和起始标签基本一样,例如</end>。SGML还定义了标签的特性(attribute),它们是定义在小于号和大于号之间的值,例如<img src="picture.jpg">中的src特性。如果你觉得它看起来很熟悉的话,应该知道,基于SGML的语言的最著名实现就是原始的HTML。

SGML常用来定义针对HTML的文档类型定义(DTD),同时它也常用于编写XML的DTD。SGML的问题就在于,它允许出现一些奇怪的语法,这让创建HTML的解析器成为一个大难题:

1  某些起始标签不允许出现结束标签,例如HTML中<img>标签。包含了结束标签就会出现错误。

2  某些起始标签可以选择性出现结束标签或者隐含了结束标签,例如HTML中<p>标签,当出现另一个<p>标签或者某些其他标签时,便假设在这之前有一个结束标签。

3  某些起始标签要求必须出现结束标签,例如HTML中<script>标签。

4  标签可以以任何顺序嵌套。即使结束标签不按照起始标签的逆序出现也是允许的,例如,<b>This is a <i> sample </b> string</i>是正确的。

5  某些特性要求必须包含值,例如<img src="picture.jpg">中的src特性。

6  某些特性不要求一定有值,例如<td nowrap>中的nowrap特性。

7  定义特性的两边有没有加上双引号都是可以的,所以<img src="picture.jpg">和<img src=picture.jpg>都是允许的。

      这些问题使建立一个SGML语言的解析器变成了一项艰巨的任务。判断何时应用以上规则的困难导致了SGML语言的定义一直停滞不前。以这些问题作为出发点,XML逐渐步入我们的视野。

      XML去掉了之前令许多开发人员头疼的SGML的随意语法。在XML中,采用了如下的语法:

8  任何的起始标签都必须有一个结束标签。

9  可以采用另一种简化语法,可以在一个标签中同时表示起始和结束标签。这种语法是在大于符号之前紧跟一个斜线(/),例如<tag />。XML解析器会将其翻译成<tag></tag>。

10  标签必须按合适的顺序进行嵌套,所以结束标签必须按镜像顺序匹配起始标签,例如<b>this is a <i>sample</i> string</b>。这好比是将起始和结束标签看作是数学中的左右括号:在没有关闭所有的内部括号之前,是不能关闭外面的括号的。

11  所有的特性都必须有值。

12  所有的特性都必须在值的周围加上双引号。

这些规则使得开发一个XML解析器要简便得多,而且也除去了解析SGML中花在判断何时何地应用那些奇怪语法规则上的工作。仅仅在XML出现后的前六年就衍生出多种不同的语言,包括MathML、SVG、RDF、RSS、SOAP、XSLT、XSL-FO,而同时也将HTML改进为XHTML。

如果需要关于SGML和XML具体技术上的对比,请查看W3C的注解,位于:http://www.w3. org/TR/NOTE-sgml-xml.html

如今,XML已经是世界上发展最快的技术之一。它的主要目的是使用文本以结构化的方式来表示数据。在某些方面,XML文件也类似于数据库,提供数据的结构化视图。这里是一个XML文件的例子:


每个XML文档都由XML序言开始,在前面的代码中的第一行便是XML序言,<?xml version="1.0"?>。这一行代码会告诉解析器和浏览器,这个文件应该按照前面讨论过的XML规则进行解析。第二行代码,<books>,则是文档元素(document element),它是文件中最外面的标签(我们认为元素(element)是起始标签和结束标签之间的内容)。所有其他的标签必须包含在这个标签之内来组成一个有效的XML文件。XML文件的第二行并不一定要包含文档元素;如果有注释或者其他内容,文档元素可以迟些出现。

范例文件中的第三行代码是注释,你会发现它与HTML中使用的注释风格是一样的。这是XML从SGML中继承的语法元素之一。

页面再往下的一些地方,可以发现<desc>标签里有一些特殊的语法。<![CDATA[ ]]>代码用于表示无需进行解析的文本,允许诸如大于号和小于号之类的特殊字符包含在文本中,而无需担心破坏XML的语法。文本必须出现在<![CDATA[和]]>之间才能合适地避免被解析。这样的文本称为Character Data Section,简称CData Section。

下面的一行就是在第二本书的定义之前的:

<?page render multiple authors ?>

虽然它看上去很像XML序言,但实际上是一种称为处理指令(processing instruction)的不同类型的语法。处理指令(以下简称PI)的目的是为了给处理页面的程序(例如XML解析器)提供额外的信息。PI通常情况下是没有固定格式的,唯一的要求是紧随第一个问号必须至少有一个字母。在此之后,PI可以包含除了小于号和大于号之外的任何字符串序列。

最常见的PI是用来指定XML文件的样式表:



这个PI一般会直接放在XML序言之后,通常由Web浏览器使用,来将XML数据以特殊的样式显示出来。
posted @ 2008-05-06 14:09 矿矿 阅读(280) | 评论 (0)编辑 收藏
XML是eXtensible Markup Language的缩写。扩展标记语言XML是一种简单的数据存储语言,使用一系列简单的标记描述数据,而这些标记可以用方便的方式建立,虽然XML占用的空间比二进制数据要占用更多的空间,但XML极其简单易于掌握和使用。

XML与Access,Oracle和SQL Server等数据库不同,数据库提供了更强有力的数据存储和分析能力,例如:数据索引、排序、查找、相关一致性等,XML仅仅是展示数据。事实上XML与其他数据表现形式最大的不同是:他极其简单。这是一个看上去有点琐细的优点,但正是这点使XML与众不同。

XML的简单使其易于在任何应用程序中读写数据,这使XML很快成为数据交换的唯一公共语言,虽然不同的应用软件也支持其它的数据交换格式,但不久之后他们都将支持XML,那就意味着程序可以更容易的与Windows、Mac OS, Linux以及其他平台下产生的信息结合,然后可以很容易加载XML数据到程序中并分析他,并以XML格式输出结果。

XML的前身是SGML(The Standard Generalized Markup Language),是自IBM从60年代就开始发展的GML(Generalized Markup Language)

HTML一样, XML (可扩展标识语言)是通用标识语言标准(SGML)的一个子集,它是描述网络上的数据内容和结构的标准。尽管如此,XML不象HTML,HTML仅仅提供了在页面上显示信息的通用方法(没有上下文相关和动态功能) ,XML则对数据赋予上下文相关功能,它继承了SGML的大部分功能,却使用了不太复杂的技术。.

为了使得SGML显得用户友好,XML重新定义了SGML的一些内部值和参数,去掉了大量的很少用到的功能,这些繁杂的功能使得SGML在设计网站时显得复杂化。XML保留了SGML的结构化功能,这样就使得网站设计者可以定义自己的文档类型,XML同时也推出一种新型文档类型,使得开发者也可以不必定义文档类型。

因为XML是W3C制定的,XML的标准化工作由W3C的XML工作组负责,该小组成员由来自各个地方和行业的专家组成,他们通过email交流对XML标准的意见,并提出自己的看法 (www.w3.org/TR/WD-xml)。因为XML 是个公共格式, (它不专属于任何一家公司),你不必担心XML技术会成为少数公司的盈利工具,XML不是一个依附于特定浏览器的语言

XML(可扩展标记语言)是从称为SGML(标准通用标记语言)的更加古老的语言派生出来的。SGML的主要目的是定义使用标签来表示数据的标记语言的语法。

标签由包围在一个小于号(<)和一个大于号(>)之间的文本组成,例如<tag>。起始标签(start tag)表示一个特定区域的开始,例如<start>;结束标签(end tag)定义了一个区域的结束,除了在小于号之后紧跟着一个斜线(/)外,和起始标签基本一样,例如</end>。SGML还定义了标签的特性(attribute),它们是定义在小于号和大于号之间的值,例如<img src="picture.jpg">中的src特性。如果你觉得它看起来很熟悉的话,应该知道,基于SGML的语言的最著名实现就是原始的HTML。

SGML常用来定义针对HTML的文档类型定义(DTD),同时它也常用于编写XML的DTD。SGML的问题就在于,它允许出现一些奇怪的语法,这让创建HTML的解析器成为一个大难题:

1  某些起始标签不允许出现结束标签,例如HTML中<img>标签。包含了结束标签就会出现错误。

2  某些起始标签可以选择性出现结束标签或者隐含了结束标签,例如HTML中<p>标签,当出现另一个<p>标签或者某些其他标签时,便假设在这之前有一个结束标签。

3  某些起始标签要求必须出现结束标签,例如HTML中<script>标签。

4  标签可以以任何顺序嵌套。即使结束标签不按照起始标签的逆序出现也是允许的,例如,<b>This is a <i> sample </b> string</i>是正确的。

5  某些特性要求必须包含值,例如<img src="picture.jpg">中的src特性。

6  某些特性不要求一定有值,例如<td nowrap>中的nowrap特性。

7  定义特性的两边有没有加上双引号都是可以的,所以<img src="picture.jpg">和<img src=picture.jpg>都是允许的。

      这些问题使建立一个SGML语言的解析器变成了一项艰巨的任务。判断何时应用以上规则的困难导致了SGML语言的定义一直停滞不前。以这些问题作为出发点,XML逐渐步入我们的视野。

      XML去掉了之前令许多开发人员头疼的SGML的随意语法。在XML中,采用了如下的语法:

8  任何的起始标签都必须有一个结束标签。

9  可以采用另一种简化语法,可以在一个标签中同时表示起始和结束标签。这种语法是在大于符号之前紧跟一个斜线(/),例如<tag />。XML解析器会将其翻译成<tag></tag>。

10  标签必须按合适的顺序进行嵌套,所以结束标签必须按镜像顺序匹配起始标签,例如<b>this is a <i>sample</i> string</b>。这好比是将起始和结束标签看作是数学中的左右括号:在没有关闭所有的内部括号之前,是不能关闭外面的括号的。

11  所有的特性都必须有值。

12  所有的特性都必须在值的周围加上双引号。

这些规则使得开发一个XML解析器要简便得多,而且也除去了解析SGML中花在判断何时何地应用那些奇怪语法规则上的工作。仅仅在XML出现后的前六年就衍生出多种不同的语言,包括MathML、SVG、RDF、RSS、SOAP、XSLT、XSL-FO,而同时也将HTML改进为XHTML。

如果需要关于SGML和XML具体技术上的对比,请查看W3C的注解,位于:http://www.w3. org/TR/NOTE-sgml-xml.html

如今,XML已经是世界上发展最快的技术之一。它的主要目的是使用文本以结构化的方式来表示数据。在某些方面,XML文件也类似于数据库,提供数据的结构化视图。这里是一个XML文件的例子:


每个XML文档都由XML序言开始,在前面的代码中的第一行便是XML序言,<?xml version="1.0"?>。这一行代码会告诉解析器和浏览器,这个文件应该按照前面讨论过的XML规则进行解析。第二行代码,<books>,则是文档元素(document element),它是文件中最外面的标签(我们认为元素(element)是起始标签和结束标签之间的内容)。所有其他的标签必须包含在这个标签之内来组成一个有效的XML文件。XML文件的第二行并不一定要包含文档元素;如果有注释或者其他内容,文档元素可以迟些出现。

范例文件中的第三行代码是注释,你会发现它与HTML中使用的注释风格是一样的。这是XML从SGML中继承的语法元素之一。

页面再往下的一些地方,可以发现<desc>标签里有一些特殊的语法。<![CDATA[ ]]>代码用于表示无需进行解析的文本,允许诸如大于号和小于号之类的特殊字符包含在文本中,而无需担心破坏XML的语法。文本必须出现在<![CDATA[和]]>之间才能合适地避免被解析。这样的文本称为Character Data Section,简称CData Section。

下面的一行就是在第二本书的定义之前的:

<?page render multiple authors ?>

虽然它看上去很像XML序言,但实际上是一种称为处理指令(processing instruction)的不同类型的语法。处理指令(以下简称PI)的目的是为了给处理页面的程序(例如XML解析器)提供额外的信息。PI通常情况下是没有固定格式的,唯一的要求是紧随第一个问号必须至少有一个字母。在此之后,PI可以包含除了小于号和大于号之外的任何字符串序列。

最常见的PI是用来指定XML文件的样式表:



这个PI一般会直接放在XML序言之后,通常由Web浏览器使用,来将XML数据以特殊的样式显示出来。
posted @ 2008-05-06 14:09 矿矿 阅读(269) | 评论 (0)编辑 收藏
//frame版程序源代码如下,疏漏之处,望批评指正。
//数字分组没有编写,科学型计算器没有编写,其他已经完善。
import java.awt.*;
import java.lang.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.event.*;
import java.text.DecimalFormat;
public class Calculator
implements ActionListener { //导入动作监听接口
//设计面板中的单位
JFrame frame;
JTextField textAnswer;
JPanel panel, panel1, panel2, panel3;
JMenuBar mainMenu;
JTextField textMemory;
JLabel labelMemSpace; //labelMemSpace单纯做摆设,控制面板的形状
JButton buttonBk, buttonCe, buttonC;
JButton button[];
JButton buttonMC, buttonMR, buttonMS, buttonMAdd;
JButton buttonDot, buttonAddAndSub, buttonAdd, buttonSub, buttonMul,
buttonDiv, buttonMod;
JButton buttonSqrt, buttonDao, buttonEqual;
JMenu editMenu, viewMenu, helpMenu;
JMenuItem copyItem, pasteItem, tItem, sItem, numberGroup, topHelp, aboutCal;
DecimalFormat df; //设置数据输出精度
boolean clickable; //控制当前能否按键
double memoryd; //使用内存中存储的数字
int memoryi;
double vard, answerd; //用来保存double型数据的中间值(vard)和最后结果(answerd)
short key = -1, prekey = -1; //key用来保存当前进行何种运算,prekey用来保存前次进行何种运算
String copy; //做复制用
JTextArea help; //帮助
JScrollPane scrollHelp;
//构造函数
public Calculator() {
clickable = true;
answerd = 0;
frame = new JFrame("计算器");
df = new DecimalFormat("0.##############"); //设置数据输出精度(对于double型值)
textAnswer = new JTextField(15);
textAnswer.setText("");
textAnswer.setEditable(false);
textAnswer.setBackground(new Color(255, 255, 255));
panel = new JPanel();
frame.getContentPane().add(panel);
panel1 = new JPanel();
panel2 = new JPanel();
panel.setLayout(new BorderLayout());
//设计整个面板
mainMenu = new JMenuBar();
editMenu = new JMenu("编辑(E)");
viewMenu = new JMenu("查看(V)");
helpMenu = new JMenu("帮助(H)");
copyItem = new JMenuItem(" 复制(C) Ctrl+C");
copyItem.addActionListener(this);
pasteItem = new JMenuItem(" 粘贴(V) Ctrl+V");
pasteItem.addActionListener(this);
editMenu.add(copyItem);
editMenu.add(pasteItem);
tItem = new JMenuItem("●标准型(T)");
tItem.addActionListener(this);
sItem = new JMenuItem(" 科学型(S)");
sItem.addActionListener(this);
numberGroup = new JMenuItem(" 数字分组(I)");
numberGroup.addActionListener(this);
viewMenu.add(tItem);
viewMenu.add(sItem);
viewMenu.add(numberGroup);
topHelp = new JMenuItem(" 帮助主题(H)");
topHelp.addActionListener(this);
help = new JTextArea(5, 20);
scrollHelp = new JScrollPane(help);
help.setEditable(false);
help.append("执行简单计算\n");
help.append("1. 键入计算的第一个数字。\n");
help.append("2. 单击“+”执行加、“-”执行减、“*”执行乘或“/”执行除。\n");
help.append("3. 键入计算的下一个数字。\n");
help.append("4. 输入所有剩余的运算符和数字。\n");
help.append("5. 单击“=”。\n");
aboutCal = new JMenuItem(" 关于计算器(A)");
aboutCal.addActionListener(this);
helpMenu.add(topHelp);
helpMenu.add(aboutCal);
mainMenu.add(editMenu);
mainMenu.add(viewMenu);
mainMenu.add(helpMenu);
panel.add(mainMenu, BorderLayout.NORTH);
panel.add(textAnswer, BorderLayout.CENTER);
panel.add(panel1, BorderLayout.SOUTH);
panel1.setLayout(new BorderLayout());
textMemory = new JTextField(3);
textMemory.setEditable(false);
textMemory.setBackground(new Color(217, 217, 217));
labelMemSpace = new JLabel(" ");
buttonBk = new JButton("Backspace");
buttonBk.setForeground(new Color(255, 0, 0));
buttonCe = new JButton("CE");
buttonCe.setForeground(new Color(255, 0, 0));
buttonC = new JButton("C");
buttonC.setForeground(new Color(255, 0, 0));
buttonBk.addActionListener(this);
buttonCe.addActionListener(this);
buttonC.addActionListener(this);
panel1.add(panel2, BorderLayout.NORTH);
panel2.setLayout(new FlowLayout(FlowLayout.RIGHT));
panel2.add(textMemory);
panel2.add(labelMemSpace);
panel2.add(buttonBk);
panel2.add(buttonCe);
panel2.add(buttonC);
panel3 = new JPanel();
panel1.add(panel3, BorderLayout.CENTER);
button = new JButton[10];
for (int i = 0; i < button.length; i++) {
button[i] = new JButton(Integer.toString(i));
button[i].setForeground(new Color(0, 0, 255));
}
buttonMC = new JButton("MC");
buttonMC.setForeground(new Color(255, 0, 0));
buttonMR = new JButton("MR");
buttonMR.setForeground(new Color(255, 0, 0));
buttonMS = new JButton("MS");
buttonMS.setForeground(new Color(255, 0, 0));
buttonMAdd = new JButton("M+");
buttonMAdd.setForeground(new Color(255, 0, 0));
buttonDot = new JButton(".");
buttonDot.setForeground(new Color(0, 0, 255));
buttonAddAndSub = new JButton("+/-");
buttonAddAndSub.setForeground(new Color(0, 0, 255));
buttonAdd = new JButton("+");
buttonAdd.setForeground(new Color(255, 0, 0));
buttonSub = new JButton("-");
buttonSub.setForeground(new Color(255, 0, 0));
buttonMul = new JButton("*");
buttonMul.setForeground(new Color(255, 0, 0));
buttonDiv = new JButton("/");
buttonDiv.setForeground(new Color(255, 0, 0));
buttonMod = new JButton("%");
buttonMod.setForeground(new Color(0, 0, 255));
buttonSqrt = new JButton("sqrt");
buttonSqrt.setForeground(new Color(0, 0, 255));
buttonDao = new JButton("1/x");
buttonDao.setForeground(new Color(0, 0, 255));
buttonEqual = new JButton("=");
buttonEqual.setForeground(new Color(255, 0, 0));
//将所有行为与监听绑定
panel3.setLayout(new GridLayout(4, 6));
panel3.add(buttonMC);
buttonMC.addActionListener(this);
panel3.add(button[7]);
button[7].addActionListener(this);
panel3.add(button[8]);
button[8].addActionListener(this);
panel3.add(button[9]);
button[9].addActionListener(this);
panel3.add(buttonDiv);
buttonDiv.addActionListener(this);
panel3.add(buttonSqrt);
buttonSqrt.addActionListener(this);
panel3.add(buttonMR);
buttonMR.addActionListener(this);
panel3.add(button[4]);
button[4].addActionListener(this);
panel3.add(button[5]);
button[5].addActionListener(this);
panel3.add(button[6]);
button[6].addActionListener(this);
panel3.add(buttonMul);
buttonMul.addActionListener(this);
panel3.add(buttonMod);
buttonMod.addActionListener(this);
panel3.add(buttonMS);
buttonMS.addActionListener(this);
panel3.add(button[1]);
button[1].addActionListener(this);
panel3.add(button[2]);
button[2].addActionListener(this);
panel3.add(button[3]);
button[3].addActionListener(this);
panel3.add(buttonSub);
buttonSub.addActionListener(this);
panel3.add(buttonDao);
buttonDao.addActionListener(this);
panel3.add(buttonMAdd);
buttonMAdd.addActionListener(this);
panel3.add(button[0]);
button[0].addActionListener(this);
panel3.add(buttonAddAndSub);
buttonAddAndSub.addActionListener(this);
panel3.add(buttonDot);
buttonDot.addActionListener(this);
panel3.add(buttonAdd);
buttonAdd.addActionListener(this);
panel3.add(buttonEqual);
buttonEqual.addActionListener(this);
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.pack();
frame.show();
}
//设置各个按钮行为
public void actionPerformed(ActionEvent event) {
boolean sign = false; //判断是否是double型数参与运算,是为true,不是为false
Object temp = event.getSource();
try {
//如果按下数据按钮,将按下的按钮代表的数据插入的当前文本框字符串之后
for (int i = 0; i <= 9; i++)
if (temp == button[i] && clickable == true)
textAnswer.setText(textAnswer.getText() + Integer.toString(i));
//按下'.'按钮时,判断当前文本框内字符串中含不含'.',如果已含,则不允许再插入'.'
if (temp == buttonDot && clickable == true) {
boolean isDot = false;
if (textAnswer.getText().length() == 0)
isDot = true;
for (int i = 0; i < textAnswer.getText().length(); i++)
if ('.' == textAnswer.getText().charAt(i)) {
isDot = true;
break;
}
if (isDot == false)
textAnswer.setText(textAnswer.getText() + ".");
}
if ( (temp == buttonAdd || temp == buttonSub || temp == buttonMul ||
temp == buttonDiv) && clickable == true) {
//'+'操作
if (temp == buttonAdd) {
switch (prekey) {
case 0:
answerd += Double.parseDouble(textAnswer.getText());
break;
case 1:
answerd -= Double.parseDouble(textAnswer.getText());
break;
case 2:
answerd *= Double.parseDouble(textAnswer.getText());
break;
case 3:
if (Double.parseDouble(textAnswer.getText()) == 0) {
textAnswer.setText("除数不能为零");
clickable = false;
}
else
answerd /= Double.parseDouble(textAnswer.getText());
break;
default:
answerd = Double.parseDouble(textAnswer.getText());
}
textAnswer.setText("");
prekey = key = 0;
}
//'-'操作
if (temp == buttonSub) {
switch (prekey) {
case 0:
answerd += Double.parseDouble(textAnswer.getText());
break;
case 1:
answerd -= Double.parseDouble(textAnswer.getText());
break;
case 2:
answerd *= Double.parseDouble(textAnswer.getText());
break;
case 3:
if (Double.parseDouble(textAnswer.getText()) == 0) {
textAnswer.setText("除数不能为零");
clickable = false;
}
else
answerd /= Double.parseDouble(textAnswer.getText());
break;
default:
answerd = Double.parseDouble(textAnswer.getText());
}
textAnswer.setText("");
prekey = key = 1;
}
//'*'操作
if (temp == buttonMul) {
switch (prekey) {
case 0:
answerd += Double.parseDouble(textAnswer.getText());
break;
case 1:
answerd -= Double.parseDouble(textAnswer.getText());
break;
case 2:
answerd *= Double.parseDouble(textAnswer.getText());
break;
case 3:
if (Double.parseDouble(textAnswer.getText()) == 0) {
textAnswer.setText("除数不能为零");
clickable = false;
}
else
answerd /= Double.parseDouble(textAnswer.getText());
break;
default:
answerd = Double.parseDouble(textAnswer.getText());
}
textAnswer.setText("");
prekey = key = 2;
}
//'/'操作
if (temp == buttonDiv) {
switch (prekey) {
case 0:
answerd += Double.parseDouble(textAnswer.getText());
break;
case 1:
answerd -= Double.parseDouble(textAnswer.getText());
break;
case 2:
answerd *= Double.parseDouble(textAnswer.getText());
break;
case 3:
if (Double.parseDouble(textAnswer.getText()) == 0) {
textAnswer.setText("除数不能为零");
clickable = false;
}
else
answerd /= Double.parseDouble(textAnswer.getText());
break;
default:
answerd = Double.parseDouble(textAnswer.getText());
}
textAnswer.setText("");
prekey = key = 3;
}
}
//'='操作
if (temp == buttonEqual && clickable == true) {
//如果连续按'=',则进行连续运算
if (prekey == 5) {
if (key == 0) {
answerd += vard;
textAnswer.setText(df.format(answerd));
}
if (key == 1) {
answerd -= vard;
textAnswer.setText(df.format(answerd));
}
if (key == 2) {
answerd *= vard;
textAnswer.setText(df.format(answerd));
}
if (key == 3) {
if (Double.parseDouble(textAnswer.getText()) == 0) {
textAnswer.setText("除数不能为零");
clickable = false;
}
else {
answerd /= vard;
textAnswer.setText(df.format(answerd));
}
}
}
else {
vard = Double.parseDouble(textAnswer.getText());
if (key == 0) {
prekey = -1;
answerd += Double.parseDouble(textAnswer.getText());
textAnswer.setText(df.format(answerd));
}
if (key == 1) {
prekey = -1;
answerd -= Double.parseDouble(textAnswer.getText());
textAnswer.setText(df.format(answerd));
}
if (key == 2) {
prekey = -1;
answerd *= Double.parseDouble(textAnswer.getText());
textAnswer.setText(df.format(answerd));
}
if (key == 3) {
prekey = -1;
if (Double.parseDouble(textAnswer.getText()) == 0) {
textAnswer.setText("除数不能为零");
clickable = false;
}
else {
answerd /= Double.parseDouble(textAnswer.getText());
textAnswer.setText(df.format(answerd));
}
}
}
prekey = 5;
}
//'%'操作,对第二个操作数除以100
if (temp == buttonMod && clickable == true) {
if (answerd == 0) {
String s = textAnswer.getText();
textAnswer.setText(s);
}
else {
boolean isDot = false;
for (int i = 0; i < textAnswer.getText().length(); i++)
if ('.' == textAnswer.getText().charAt(i)) {
isDot = true;
break;
}
//如果是double数,除100
if (isDot == true) {
double dtemp = Double.parseDouble(textAnswer.getText());
dtemp = dtemp / 100.0;
textAnswer.setText(Double.toString(dtemp));
}
else {
//如果是int数但能被100整除,则去掉末尾两个零
if (Integer.parseInt(textAnswer.getText()) % 100 == 0) {
int itemp = Integer.parseInt(textAnswer.getText());
itemp /= 100;
textAnswer.setText(Integer.toString(itemp));
}
//如果是int数,但不能被100整除,则按double数处理
else {
double dtemp = Double.parseDouble(textAnswer.getText());
dtemp = dtemp / 100.0;
textAnswer.setText(Double.toString(dtemp));
}
}
}
}
//开根号运算
if (temp == buttonSqrt && clickable == true) {
String s = textAnswer.getText();
if (s.charAt(0) == '-') {
textAnswer.setText("负数不能开根号");
clickable = false;
}
else
textAnswer.setText(Double.toString(java.lang.Math.sqrt(Double.
parseDouble(textAnswer.getText()))));
}
//倒数运算
if (temp == buttonDao && clickable == true) {
if (textAnswer.getText().charAt(0) == '0' &&
textAnswer.getText().length() == 1) {
textAnswer.setText("零不能求倒数");
clickable = false;
}
else {
boolean isDec = true;
int i, j, k;
String s = Double.toString(1 / Double.parseDouble(textAnswer.getText()));
for (i = 0; i < s.length(); i++)
if (s.charAt(i) == '.')
break;
for (j = i + 1; j < s.length(); j++)
if (s.charAt(j) != '0') {
isDec = false;
break;
}
if (isDec == true) {
String stemp = "";
for (k = 0; k < i; k++)
stemp += s.charAt(k);
textAnswer.setText(stemp);
}
else
textAnswer.setText(s);
}
}
//按下'+/-'按钮时处理
if (temp == buttonAddAndSub && clickable == true) {
boolean isNumber = true;
String s = textAnswer.getText();
for (int i = 0; i < s.length(); i++)
if (! (s.charAt(i) >= '0' && s.charAt(i) <= '9' || s.charAt(i) == '.' ||
s.charAt(i) == '-')) {
isNumber = false;
break;
}
if (isNumber == true) {
//如果当前字符串首字母有'-'号,代表现在是个负数,再按下时,则将首符号去掉
if (s.charAt(0) == '-') {
textAnswer.setText("");
for (int i = 1; i < s.length(); i++) {
char a = s.charAt(i);
textAnswer.setText(textAnswer.getText() + a);
}
}
//如果当前字符串第一个字符不是符号,则添加一个符号在首字母处
else
textAnswer.setText('-' + s);
}
}
//计算器有关内存操作
//'MC'的操作,将内存清0
if (temp == buttonMC && clickable == true) {
memoryd = memoryi = 0;
textMemory.setText("");
}
//'MS'的操作,将当前文本框内容保存入内存,显示'M'
if (temp == buttonMS && clickable == true) {
boolean isDot = false;
textMemory.setText(" M");
for (int i = 0; i < textAnswer.getText().length(); i++)
if ('.' == textAnswer.getText().charAt(i)) {
isDot = true;
break;
}
//如果是double,则存入memoryd(double存储器)
if (isDot == true) {
memoryd = Double.parseDouble(textAnswer.getText());
memoryi = 0; //保证存储器中存放最新的值
}
//如果是int,则存入memoryi(int存储器)
else {
memoryi = Integer.parseInt(textAnswer.getText());
memoryd = 0; //保证存储器中存放最新的值
}
}
//'MR'的操作,将存储器中的信息输出
if (temp == buttonMR && clickable == true) {
if (memoryd != 0)
textAnswer.setText(Double.toString(memoryd));
if (memoryi != 0)
textAnswer.setText(Integer.toString(memoryi));
}
//'M+'的功能,将当前文本框里的数据和存储器中数据相加后,再存入存储器
if (temp == buttonMAdd && clickable == true) {
boolean isDot = false;
for (int i = 0; i < textAnswer.getText().length(); i++)
if ('.' == textAnswer.getText().charAt(i)) {
isDot = true;
break;
}
if (memoryi != 0) { //存储中是一个int型数
if (isDot == false) //被加数是一个int型数
memoryi += Integer.parseInt(textAnswer.getText());
else { //被加数是一个double型数,则将int存储器中数传入double存储器与当前数相加,int存储器清零
memoryd = memoryi + Double.parseDouble(textAnswer.getText());
memoryi = 0;
}
}
else
memoryd += Double.parseDouble(textAnswer.getText());
}
//按下'Backspace'键,利用循环将当前字符串中的最后一个字母删除
if (temp == buttonBk && clickable == true) {
String s = textAnswer.getText();
textAnswer.setText("");
for (int i = 0; i < s.length() - 1; i++) {
char a = s.charAt(i);
textAnswer.setText(textAnswer.getText() + a);
}
}
//按下'CE'按钮,将当前文本框内数据清除
if (temp == buttonCe) {
textAnswer.setText("");
clickable = true;
}
//按下'C'按钮,文本框内数据清除,同时var,answer清0
if (temp == buttonC) {
vard = answerd = 0;
textAnswer.setText("");
clickable = true;
}
//按下'复制'菜单栏
if (temp == copyItem) {
copy = textAnswer.getText();
}
//按下'粘贴'菜单栏
if (temp == pasteItem) {
textAnswer.setText(copy);
}
if (temp == sItem) {
JOptionPane.showMessageDialog(panel, "当前是标准型计算器,\n科学型计算器有待更新。");
}
//按下'帮助主题'菜单栏
if (temp == topHelp) {
JOptionPane.showMessageDialog(panel, scrollHelp);
}
//按下'数字分组'菜单栏
if (temp == numberGroup) {
if (numberGroup.getText().compareTo(" 数字分组(I)") == 0)
numberGroup.setText("√数字分组(I)");
else
numberGroup.setText(" 数字分组(I)");
}
//按下'关于'菜单栏
if (temp == aboutCal) {
JOptionPane.showMessageDialog(panel, "计算器1.00版\n开发者:矿矿");
}
}
//输入中如果有操作非法,比如按下两次'+',捕获异常
catch (Exception e) {
textAnswer.setText("操作非法");
clickable = false;
}
}
//主函数
public static void main(String args[]) {
new Calculator();
}
}
posted @ 2008-04-21 20:44 矿矿 阅读(3302) | 评论 (3)编辑 收藏
package t06;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Toolkit;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

public class Demo extends JFrame{

    Container contentPane;
    ImageIcon img = new ImageIcon("002.jpg");
   
    JPanel paneTop = new JPanel();
    JPanel paneMid = new JPanel();
    JPanel paneBut = new JPanel();
    JPanel paneAll = new JPanel();
   
    JLabel lblTop = new JLabel();
    JLabel lblName = new JLabel();
    JLabel lblPwd = new JLabel();
    JLabel lblApply = new JLabel();
    JLabel lblForget = new JLabel();
    JLabel lblModel = new JLabel();
    JLabel lblNull = new JLabel();
   
    JTextField txtName = new JTextField(15);
    JPasswordField txtPwd = new JPasswordField(15);
   
    JComboBox cmb = new JComboBox();
   
    JCheckBox chk = new JCheckBox();
   
    JButton btnKill = new JButton("查杀木马");
    JButton btnSet = new JButton("设置");
    JButton btnLogin = new JButton("登录");
   
   
   
    Demo(){
        lblTop.setIcon(img);
        paneTop.add(lblTop);
       
        lblName.setText("QQ帐号:");
        lblApply.setText("申请帐号   ");
        lblPwd.setText("QQ密码:");
        lblForget.setText("忘记密码?");
        lblModel.setText("状态:");
       
        String[] s1 = {"隐身","在线","忙碌"};
        cmb.addItem(s1[0]);
        cmb.addItem(s1[1]);
        cmb.addItem(s1[2]);
       
        chk.setText("自动登录");
       
        paneMid.add(lblName);
        paneMid.add(txtName);
        paneMid.add(lblApply);
       
        paneMid.add(lblPwd);
        paneMid.add(txtPwd);
        paneMid.add(lblForget);
       
        paneMid.add(lblModel);
        paneMid.add(cmb);
        paneMid.add(chk);
       
        paneBut.add(btnKill);
        paneBut.add(btnSet);
        paneBut.add(btnLogin);
       
        contentPane = this.getContentPane();
       
        contentPane.add(paneTop,BorderLayout.NORTH);
        contentPane.add(paneMid,BorderLayout.CENTER);
        contentPane.add(paneBut,BorderLayout.SOUTH);
       
       
       
        setTitle("欢迎使用QQ");
        setSize(330,240);
        Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
        setLocation((screen.width - getSize().width)/2,(screen.height - getSize().height)/2 );
        setVisible(true);
        setResizable(false);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);       
    }
   
    public static void main(String args[]){
        Demo d = new Demo();
    }
   
}


posted @ 2008-04-18 21:42 矿矿 阅读(5418) | 评论 (17)编辑 收藏
Java语言中, abstract class 和在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协作完成的。在这种情况下,各个对象内部是如何实现自己的对系统设计人员来讲就不那么重要了;而各个对象之间的协作关系则成为系统设计的关键。小到不同类之间的通信,大到各模块之间的交互,在系统设计之初都是要着重考虑的,这也是系统设计的主要工作内容。面向接口编程我想就是指按照这种思想来编程吧!实际上,在日常工作中,你已经按照接口编程了,只不过如果你没有这方面的意识,那么你只是在被动的实现这一思想;表现在频繁的抱怨别人改的代码影响了你(接口没有设计到),表现在某个模块的改动引起其他模块的大规模调整(模块接口没有很好的设计)等等。

  Booch先生那天谈到Interaction Designer,它就是指做这类设计的人,只不过层次更高一些。我想目前我们的软件设计队伍中,这类人是最缺乏的人才之一。

  非接口编程?是不是就是面向过程的编程思想?

  1.关于接口的理解。

  接口从更深层次的理解,应是定义(规范,约束)与实现(名实分离的原则)的分离。

  我们在一般实现一个系统的时候,通常是将定义与实现合为一体,不加分离的,我认为最为理解的系统设计规范应是所有的定义与实现分离,尽管这可能对系统中的某些情况有点繁烦。

  接口的本身反映了系统设计人员对系统的抽象理解。

  接口应有两类:第一类是对一个体的抽象,它可对应为一个抽象体(abstract class);

  第二类是对一个体某一方面的抽象,即形成一个抽象面(interface);

  一个体有可能有多个抽象面。

  抽象体与抽象面是有区别的。

  2.设计接口的另一个不可忽视的因素是接口所处的环境(context,environment),系统论的观点:环境是系统要素所处的空间与外部影响因素的总和。任何接口都是在一定的环境中产生的。因此环境的定义及环境的变化对接口的影响是不容忽视的,脱离原先的环境,所有的接口将失去原有的意义。

  3.按照组件的开发模型(3C),它们三者相辅相成,各司一面,浑然一体,缺一不可。

  面向对象是指,我们考虑问题时,以对象为单位,考虑它的属性及方法

  面向过程是指,我们考虑问题时,以一个具体的流程(事务过程)为单位,考虑它的实现

  接口设计与非接口设计是针对复用技术而言的,与面向对象(过程)不是一个问题

  我认为:UML里面所说的interface是协议的另一种说法。并不是指com的interface,CORBA的interface,Java的interface,Delphi的interface,人机界面的interface或NIC的interface。

  在具体实现中,是可以把UML的interface实现为语言的interface,分布式对象环境的interface或其它什么interface,但就理解UML的interface而言,指的是系统每部分的实现和实现之间,通过interface所确定的协议来共同工作。

  所以我认为,面向interface编程,原意是指面向抽象协议编程,实现者在实现时要严格按协议来办。也就是Bill Joy同志说的,一边翻rfc,一边写代码的意思。面向对象编程是指面向抽象和具象。抽象和具象是矛盾的统一体,不可能只有抽象没有具象。一般懂得抽象的人都明白这个道理。 但有的人只知具象却不知抽象为何物。

  所以只有interface没有实现,或只有实现而没有interface者是没有用的,反OO的。

  所以还是老老实实面向对象编程,面向协议编程,或者什么都不面向,老老实实编程。

是支持抽象类定义的两种机制。正是由于这两种机制的存在,才赋予了Java强大的 面向对象能力。abstract class和interface之间在对于抽象类定义的支持方面具有很大的相似性,甚至可以相互替换,因此很多开发者在进 行抽象类定义时对于abstract class和interface的选择显得比较随意。其实,两者之间还是有很大的区别的,对于它们的选择甚至反映出对 于问题领域本质的理解、对于设计意图的理解是否正确、合理。本文将对它们之间的区别进行一番剖析,试图给开发者提供一个在二者之间进行选择的依据。

  理解抽象类

  abstract class和interface在Java语言中都是用来进行抽象类(本文 中的抽象类并非从abstract class翻译而来,它表示的是一个抽象体,而abstract class为Java语言中用于定义抽象类的一种方法, 请读者注意区分)定义的,那么什么是抽象类,使用抽象类能为我们带来什么好处呢?

  在 面向对象的概念中,我们知道所有的对象都是通过类来描绘的,但是反过来却不是这样。并不是 所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。抽象类往往用来表征我们在对问题领域进行分析、 设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。比如:如果我们进行一个图形编辑软件的开发,就会发现问题领域存在着圆、 三角形这样一些具体概念,它们是不同的,但是它们又都属于形状这样一个概念,形状这个概念在问题领域是不存在的,它就是一个抽象概念。正是因为抽象的概念 在问题领域没有对应的具体概念,所以用以表征抽象概念的抽象类是不能够实例化的。

  在面向对象领域,抽象类主要用来进行类型隐藏。 我们可以构造出一个固定的一组行为的抽象描 述,但是这组行为却能够有任意个可能的具体实现方式。这个抽象描述就是抽象类,而这一组任意个可能的具体实现则表现为所有可能的派生类。模块可以操作一个 抽象体。由于模块依赖于一个固定的抽象体,因此它可以是不允许修改的;同时,通过从这个抽象体派生,也可扩展此模块的行为功能。熟悉OCP的读者一定知 道,为了能够实现面向对象设计的一个最核心的原则OCP(Open-Closed Principle),抽象类是其中的关键所在。

  从语法定义层面看abstract class 和 interface

  在语法层面,Java语言对于abstract class和interface给出了不同的定义方式,下面以定义一个名为Demo的抽象类为例来说明这种不同。

  使用abstract class的方式定义Demo抽象类的方式如下:

abstract class Demo{
abstract void method1();
abstract void method2();


  使用interface的方式定义Demo抽象类的方式如下:

interface Demo{
void method1();
void method2();

}

  在abstract class方式中,Demo可以有自己的数据成员,也可以有非 abstract的成员方法,而在interface方式的实现中,Demo只能够有静态的不能被修改的数据成员(也就是必须是static final 的,不过在interface中一般不定义数据成员),所有的成员方法都是abstract的。从某种意义上说,interface是一种特殊形式的 abstract class。

  从编程的角度来看,abstract class和interface都可以用来实现 "design by contract" 的思想。但是在具体的使用上面还是有一些区别的。

  首先,abstract class 在 Java 语言中表示的是一种继承关系,一个类只能使用一次继承关系(因为Java不支持多继承 -- 转注)。但是,一个类却可以实现多个interface。也许,这是Java语言的设计者在考虑Java对于多重继承的支持方面的一种折中考虑吧。

  其次,在abstract class的定义中,我们可以赋予方法的默认行为。但是在interface的定义中,方法却不能拥有默认行为,为了绕过这个限制,必须使用委托,但是这会增加一些复杂性,有时会造成很大的麻烦。

  在 抽象类中不能定义默认行为还存在另一个比较严重的问题,那就是可能会造成维护上的麻烦。因 为如果后来想修改类的界面(一般通过 abstract class 或者interface来表示)以适应新的情况(比如,添加新的方法或者给已用的方法中添 加新的参数)时,就会非常的麻烦,可能要花费很多的时间(对于派生类很多的情况,尤为如此)。但是如果界面是通过abstract class来实现的,那 么可能就只需要修改定义在abstract class中的默认行为就可以了。

  同样,如果不能在抽象类中定义默认行为,就会导致同样的方法实现出现在该抽象类的每一个派生类中,违反了 "one rule,one place" 原则,造成代码重复,同样不利于以后的维护。因此,在abstract class和interface间进行选择时要非常的小心。

  从设计理念层面看 abstract class 和 interface

  上面主要从语法定义和编程的角度论述了abstract class和interface的区 别,这些层面的区别是比较低层次的、非本质的。本小节将从另一个层面:abstract class和interface所反映出的设计理念,来分析一下二者的区别。作者认为,从这个层面进行分析才能理解二者概念的本质所在。

  前面已经提到过,abstract class在Java语言中体现了一种继承关系,要想使得 继承关系合理,父类和派生类之间必须存在"is-a"关系,即父类和派生类在概念本质上应该是相同的。对于interface来说则不然,并不要求interface的实现者和interface定义在概念本质上是一致的, 仅仅是实现了interface定义的契约而已。为了使论述便于理解,下面将通过一个简单的实例进行说明。

  考虑这样一个例子,假设在我们的问题领域中有一个关于Door的抽象概念,该Door具有执行两个动作open和close,此时我们可以通过abstract class或者interface来定义一个表示该抽象概念的类型,定义方式分别如下所示:

  使用abstract class方式定义Door:

abstract class Door{
abstract void open();
abstract void close();
}

  使用interface方式定义Door:

interface Door{
void open();
void close();
}

  其他具体的Door类型可以extends使用abstract class方式定义的Door或者implements使用interface方式定义的Door。看起来好像使用abstract class和interface没有大的区别。

  如果现在要求Door还要具有报警的功能。我们该如何设计针对该例子的类结构呢(在本例中, 主要是为了展示 abstract class 和interface 反映在设计理念上的区别,其他方面无关的问题都做了简化或者忽略)?下面将罗列出可能的解 决方案,并从设计理念层面对这些不同的方案进行分析。

  解决方案一:

  简单的在Door的定义中增加一个alarm方法,如下:

abstract class Door{
abstract void open();
abstract void close();
abstract void alarm();
}

  或者

interface Door{
void open();
void close();
void alarm();
}

  那么具有报警功能的AlarmDoor的定义方式如下:

class AlarmDoor extends Door{
void open(){…}
void close(){…}
void alarm(){…}
}

  或者

class AlarmDoor implements Door{
void open(){…}
void close(){…}
void alarm(){…}

  这种方法违反了面向对象设计中的一个核心原则 ISP (Interface Segregation Principle),在Door的定义中把Door概念本身固有的行为方法和另外一个概念"报警器"的行为方 法混在了一起。这样引起的一个问题是那些仅仅依赖于Door这个概念的模块会因为"报警器"这个概念的改变(比如:修改alarm方法的参数)而改变,反 之依然。

  解决方案二:

  既然open、close和alarm属于两个不同的概念,根据ISP原则应该把它们分别定 义在代表这两个概念的抽象类中。定义方式有:这两个概念都使用 abstract class 方式定义;两个概念都使用interface方式定义;一个概念 使用 abstract class 方式定义,另一个概念使用interface方式定义。

  显然,由于Java语言不支持多重继承,所以两个概念都使用abstract class方式定义是不可行的。后面两种方式都是可行的,但是对于它们的选择却反映出对于问题领域中的概念本质的理解、对于设计意图的反映是否正确、合理。我们一一来分析、说明。

  如果两个概念都使用interface方式来定义,那么就反映出两个问题:1、我们可能没有 理解清楚问题领域,AlarmDoor在概念本质上到底是Door还是报警器?2、如果我们对于问题领域的理解没有问题,比如:我们通过对于问题领域的分 析发现AlarmDoor在概念本质上和Door是一致的,那么我们在实现时就没有能够正确的揭示我们的设计意图,因为在这两个概念的定义上(均使用 interface方式定义)反映不出上述含义。

  如果我们对于问题领域的理解是:AlarmDoor在概念本质上是Door,同时它有具有报 警的功能。我们该如何来设计、实现来明确的反映出我们的意思呢?前面已经说过,abstract class在Java语言中表示一种继承关系,而继承关系 在本质上是"is-a"关系。所以对于Door这个概念,我们应该使用abstarct class方式来定义。另外,AlarmDoor又具有报警功能,说 明它又能够完成报警概念中定义的行为,所以报警概念可以通过interface方式定义。如下所示:

abstract class Door{
abstract void open();
abstract void close();
}
interface Alarm{
void alarm();
}
class Alarm Door extends Door implements Alarm{
void open(){…}
void close(){…}
void alarm(){…}
}

  这种实现方式基本上能够明确的反映出我们对于问题领域的理解,正确的揭示我们的设计意图。其 实abstract class表示的是"is-a"关系,interface表示的是"like-a"关系,大家在选择时可以作为一个依据,当然这是建立在对问题领域的理解上的,比如:如果我们认为AlarmDoor在概念本质上是报警器,同时又具有Door的功能,那么上述的定义方式就要反过来了。

  小结

  1.abstract class 在 Java 语言中表示的是一种继承关系,一个类只能使用一次继承关系。但是,一个类却可以实现多个interface。

  2.在abstract class 中可以有自己的数据成员,也可以有非abstarct的成员方法,而在interface中,只能够有静态的不能被修改的数据成员(也就是必须是static final的,不过在 interface中一般不定义数据成员),所有的成员方法都是abstract的。

  3.abstract class和interface所反映出的设计理念不同。其实abstract class表示的是"is-a"关系,interface表示的是"like-a"关系。

  4.实现抽象类和接口的类必须实现其中的所有方法。抽象类中可以有非抽象方法。接口中则不能有实现方法。

  5.接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能重新定义,也不能改变其值。

  6.抽象类中的变量默认是 friendly 型,其值可以在子类中重新定义,也可以重新赋值。

  7.接口中的方法默认都是 public,abstract 类型的。

  结论

  abstract class 和 interface 是 Java语言中的两种定义抽象类的方式,它们之间有很大的相似性。但是对于它们的选择却又往往反映出对于问题领域中的概 念本质的理解、对于设计意图的反映是否正确、合理,因为它们表现了概念间的不同的关系(虽然都能够实现需求的功能)。这其实也是语言的一种的惯用法,希望读者朋友能够细细体会。
jack jones/杰克琼斯/马克华菲
posted @ 2008-04-08 15:14 矿矿 阅读(712) | 评论 (0)编辑 收藏
在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协作完成的。在这种情况下,各个对象内部是如何实现自己的对系统设计人员来讲就不那么重要了;而各个对象之间的协作关系则成为系统设计的关键。小到不同类之间的通信,大到各模块之间的交互,在系统设计之初都是要着重考虑的,这也是系统设计的主要工作内容。面向接口编程我想就是指按照这种思想来编程吧!实际上,在日常工作中,你已经按照接口编程了,只不过如果你没有这方面的意识,那么你只是在被动的实现这一思想;表现在频繁的抱怨别人改的代码影响了你(接口没有设计到),表现在某个模块的改动引起其他模块的大规模调整(模块接口没有很好的设计)等等。

  Booch先生那天谈到Interaction Designer,它就是指做这类设计的人,只不过层次更高一些。我想目前我们的软件设计队伍中,这类人是最缺乏的人才之一。

  非接口编程?是不是就是面向过程的编程思想?

  1.关于接口的理解。

  接口从更深层次的理解,应是定义(规范,约束)与实现(名实分离的原则)的分离。

  我们在一般实现一个系统的时候,通常是将定义与实现合为一体,不加分离的,我认为最为理解的系统设计规范应是所有的定义与实现分离,尽管这可能对系统中的某些情况有点繁烦。

  接口的本身反映了系统设计人员对系统的抽象理解。

  接口应有两类:第一类是对一个体的抽象,它可对应为一个抽象体(abstract class);

  第二类是对一个体某一方面的抽象,即形成一个抽象面(interface);

  一个体有可能有多个抽象面。

  抽象体与抽象面是有区别的。

  2.设计接口的另一个不可忽视的因素是接口所处的环境(context,environment),系统论的观点:环境是系统要素所处的空间与外部影响因素的总和。任何接口都是在一定的环境中产生的。因此环境的定义及环境的变化对接口的影响是不容忽视的,脱离原先的环境,所有的接口将失去原有的意义。

  3.按照组件的开发模型(3C),它们三者相辅相成,各司一面,浑然一体,缺一不可。

  面向对象是指,我们考虑问题时,以对象为单位,考虑它的属性及方法

  面向过程是指,我们考虑问题时,以一个具体的流程(事务过程)为单位,考虑它的实现

  接口设计与非接口设计是针对复用技术而言的,与面向对象(过程)不是一个问题

  我认为:UML里面所说的interface是协议的另一种说法。并不是指com的interface,CORBA的interface,Java的interface,Delphi的interface,人机界面的interface或NIC的interface。

  在具体实现中,是可以把UML的interface实现为语言的interface,分布式对象环境的interface或其它什么interface,但就理解UML的interface而言,指的是系统每部分的实现和实现之间,通过interface所确定的协议来共同工作。

  所以我认为,面向interface编程,原意是指面向抽象协议编程,实现者在实现时要严格按协议来办。也就是Bill Joy同志说的,一边翻rfc,一边写代码的意思。面向对象编程是指面向抽象和具象。抽象和具象是矛盾的统一体,不可能只有抽象没有具象。一般懂得抽象的人都明白这个道理。 但有的人只知具象却不知抽象为何物。

  所以只有interface没有实现,或只有实现而没有interface者是没有用的,反OO的。

  所以还是老老实实面向对象编程,面向协议编程,或者什么都不面向,老老实实编程。

posted @ 2008-04-08 15:07 矿矿 阅读(202) | 评论 (0)编辑 收藏
一.谁在做Garbage Collection?

  一种流行的说法:在C++里,是系统在做垃圾回收;而在Java里,是Java自身在做。

  在C++里,释放内存是手动处理的,要用delete运算符来释放分配的内存。这是流行的说法。确切地说,是应用认为不需要某实体时,就需用delete告诉系统,可以回收这块空间了。这个要求,对编码者来说,是件很麻烦、很难做到的事。随便上哪个BBS,在C/C++版块里总是有一大堆关于内存泄漏的话题。

  Java采用一种不同的,很方便的方法:Garbage Collection。垃圾回收机制放在JVM里。JVM完全负责垃圾回收事宜,应用只在需要时申请空间,而在抛弃对象时不必关心空间回收问题。

  二.对象在啥时被丢弃?

  在C++里,当对象离开其作用域时,该对象即被应用抛弃。

  是对象的生命期不再与其作用域有关,而仅仅与引用有关。

  Java的垃圾回收机制一般包含近十种算法。对这些算法中的多数,我们不必予以关心。只有其中最简单的一个:引用计数法,与编码有关。

  一个对象,可以有一个或多个引用变量指向它。当一个对象不再有任何一个引用变量指向它时,这个对象就被应用抛弃了。或者说,这个对象可以被垃圾回收机制回收了。

  这就是说,当不存在对某对象的任何引用时,就意味着,应用告诉JVM:我不要这个对象,你可以回收了。

  JVM的垃圾回收机制对堆空间做实时检测。当发现某对象的引用计数为0时,就将该对象列入待回收列表中。但是,并不是马上予以销毁。

  三.丢弃就被回收?

  该对象被认定为没有存在的必要了,那么它所占用的内存就可以被释放。被回收的内存可以用于后续的再分配。

  但是,并不是对象被抛弃后当即被回收的。JVM进程做空间回收有较大的系统开销。如果每当某应用进程丢弃一个对象,就立即回收它的空间,势必会使整个系统的运转效率非常低下。

  前面说过,JVM的垃圾回收机制有多个算法。除了引用计数法是用来判断对象是否已被抛弃外,其它算法是用来确定何时及如何做回收。JVM的垃圾回收机制要在时间和空间之间做个平衡。

  因此,为了提高系统效率,垃圾回收器通常只在满足两个条件时才运行:即有对象要回收且系统需要回收。切记垃圾回收要占用时间,因此,Java运行时系统只在需要的时候才使用它。因此你无法知道垃圾回收发生的精确时间。

  四.没有引用变量指向的对象有用吗?

  前面说了,没挂上引用变量的对象是被应用丢弃的,这意味着,它在堆空间里是个垃圾,随时可能被JVM回收。

  不过,这里有个不是例外的例外。对于一次性使用的对象(有些书称之为临时对象),可以不用引用变量指向它。举个最简单也最常见的例子:

  System.out.println(“I am Java!”);

  就是创建了一个字符串对象后,直接传递给println()方法。

  五.应用能干预垃圾回收吗?

  许多人对Java的垃圾回收不放心,希望在应用代码里控制JVM的垃圾回收运作。这是不可能的事。对垃圾回收机制来说,应用只有两个途径发消息给JVM。第一个前面已经说了,就是将指向某对象的所有引用变量全部移走。这就相当于向JVM发了一个消息:这个对象不要了。第二个是调用库方法System.gc(),多数书里说调用它让Java做垃圾回收。

  第一个是一个告知,而调用System.gc()也仅仅是一个请求。JVM接受这个消息后,并不是立即做垃圾回收,而只是对几个垃圾回收算法做了加权,使垃圾回收操作容易发生,或提早发生,或回收较多而已。

  希望JVM及时回收垃圾,是一种需求。其实,还有相反的一种需要:在某段时间内最好不要回收垃圾。要求运行速度最快的实时系统,特别是嵌入式系统,往往希望如此。

  Java的垃圾回收机制是为所有Java应用进程服务的,而不是为某个特定的进程服务的。因此,任何一个进程都不能命令垃圾回收机制做什么、怎么做或做多少。

  六.对象被回收时要做的事

  一个对象在运行时,可能会有一些东西与其关连。因此,当对象即将被销毁时,有时需要做一些善后工作。可以把这些操作写在finalize()方法(常称之为终止器)里。

  protected void finalize()

  {

  // finalization code here

  }

  这个终止器的用途类似于C++里的析构函数,而且都是自动调用的。但是,两者的调用时机不一样,使两者的表现行为有重大区别。C++的析构函数总是当对象离开作用域时被调用。这就是说,C++析构函数的调用时机是确定的,且是可被应用判知的。但是,Java终止器却是在对象被销毁时。由上所知,被丢弃的对象何时被销毁,应用是无法获知的。而且,对于大多数场合,被丢弃对象在应用终止后仍未销毁。

  在编码时,考虑到这一点。譬如,某对象在运作时打开了某个文件,在对象被丢弃时不关闭它,而是把文件关闭语句写在终止器里。这样做对文件操作会造成问题。如果文件是独占打开的,则其它对象将无法访问这个文件。如果文件是共享打开的,则另一访问该文件的对象直至应用终结仍不能读到被丢弃对象写入该文件的新内容。

  至少对于文件操作,编码者应认清Java终止器与C++析构函数之间的差异。

  那么,当应用终止,会不会执行应用中的所有finalize()呢?据Bruce Eckel在Thinking in Java里的观点:“到程序结束的时候,并非所有收尾模块都会得到调用”。这还仅仅是指应用正常终止的场合,非正常终止呢?

  因此,哪些收尾操作可以放在finalize()里,是需要酌酎的。

posted @ 2008-04-08 14:55 矿矿 阅读(300) | 评论 (0)编辑 收藏
重要知识点总结如下:

  1,抽象,封装,继承,多态是面向对象程序设计中得四个特点.

  2,面向对象得软件开发大体分为:面向对象的分析,面向对象的设计,面向对象的实现.

  可概括为如下过程:分析用户需求,从问题中抽取对象模型;细化模型,设计类,包括类的属性和类间的

  相互关系,同时观察是否有可以直接引用的已有类或部件;选定一种面向对象的编程语言,具体编码实现

  上一阶段类的设计,并在开发过程中引入测试,完善整个解决方案.

  3,面向对象程序设计方法的优点是:可重用性,可扩展性,可管理性.

  4,类的定义:class前的修饰符分为访问控制符和非访问控制符两大类.访问控制符包括public和private.

  非访问控制符包括abstract(抽象),final(最终).

  5,final类是最终类,是不能有子类的类.abstract和final不能同时修饰一个类,因为抽象类本身没有具体对象,

  需要派生出子类后在创建子类的对象.而最终类不可能有子类.

  6,创建对象的格式为: 类名 对象名=new 构造方法(参数);注意前面是类名后面是构造方法.

  注意构造方法没有返回类型,也不能写void,主要用于完成类对象的初始化工作,一般不能直接由编程

  直接调用,而是用new运算符来调用.

  7,如果class前面由public修饰符,则默认构造方法的前面也应该有public修饰符.

  8,类中有static修饰的域或方法,可用类名或对象名访问,否则只能用对象名访问.

  9,修饰域的访问控制符可以是:public,private,protected,private protected.非访问控制符可以是:

  static,final,volatile(易失域)

  10,类变量的最本质的特点是:他们是类的域,不属于任何一个类的具体对象实例.不是保存在某个对象实例的内存空间中,而是保存在类的内存区域的公共存储单元中.

        11,局部变量是在方法体内声明的,只有当方法被调用时他们才存在,因而只能在本方法内使用,不存在访问控制符,也不能声明为静态变量(static),但可以声明为final变量.局部变量必须初始化.

  12,修饰方法的访问控制符可以是:public,private,protected,private protected,修饰方法的非访问控制符可以是:static,final,abstract,native(本地方法),synchronized(同步方法)。

  13,用static修饰的变量或方法都为类成员,类成员可以用类名或实例名访问,实例成员只能用实例名来访问。

  14,如果一个类中含有抽象方法,则此类必须为抽象类,如果抽象类的子类不为抽象类,则子类必须实现父类的所有抽象方法。抽象方法不能用静态方法和最终方法。抽想方法只有函数头的声明,而用分号来替代方法体,没有大括号。如abstract void abstractmethod();

  15,this变量用在一个方法的内部,指向当前对象,当前对象指的是调用当前正在执行的方法的那个对象。super变量是直接指向父类的构造方法,用来引用父类种的变量和方法。(由于他们指的是对象,所以不能通过它来引用类变量和类方法)

  16,如果要引用一个包中的多个类,可以用星号来代替。使用星号只能表示本层次的所有类,而不包括子层次下的类。所以经常需要用两条语句来引入两个层次的类:import java.awt.*;import java.awt.event.*;

  17,访问修饰符:

  --类中限定为public的成员可以被所有的类访问。

  --类中先定位private的成员只能被这个类本身访问。同一个类的不同对象可以访问对方的private域变量或调用对方的域方法,这是因为访问保护控制在类的级别上,而不是对象的级别上。

  --类中限定为protected的成员可以被这个类本身,它的子类(包括同一个包中和不同包中的子类),以及同一个包中的其他类访问。

  --用private protected修饰的成员可以被该类本身访问,也可以被该类的所有子类访问。

  --默认访问控制符规定只能被同一个包中的类访问和引用,而不能被其他包的类访问。即他的访问权限是friendly。

  18,注意:

  ----abstract和private,static,final,native不能并列修饰同一个方法。

  ----abstract类中不能有private修饰的域和方法

  ----static方法不能处理非static的域。

  19,重载方法的参数必须不同,或者是参数个数不同,或者是参数类型不同。重载的多个方法必须返回相同的数据类型。

  20,在java中,一个类获取某一接口定义的功能并不是通过直接继承这个接口的属性和方法来实现的。因为接口中的属性都是常量,接口的方法都是没有方法体的抽象方法,没有具体定义操作。

posted @ 2008-04-08 14:42 矿矿 阅读(2409) | 评论 (0)编辑 收藏
不走弯路,就是捷径

可以这么说吧,学习JAVA没有什么捷径,学习什么语言都没有什么捷径

最好的方法就是,多看书,多写代码,多思考

没有程序基础没有关系,成事开头难,我相信你会学好的,加油吧!

对于风接触JAVA的人,可以按照下面的路线开始学(仅供参考)

基本数据类型-操作符-流程控制语句(这些是所有编程语言的基础)

然后上面这些掌握了之后,看面向对象(这个是重点)

在这个过程中可以先搞明白public,private,protected,static等关键词的用法,什么时候用,什么时候不用,这些对于你以后的学习很有帮助

然后就是仔细研究面向对象了,这个是重点 !

当上面这些你都搞明白后,就不用我说了,你自己就会有一定的自学的经验了,就知道自己该看什么,不看什么了

推荐两本书

java2 核心技术卷(基础篇)、java编程思想(也就是Thinking in java) 后者在你有了一定的基础后再看,不然不容易明白的
posted @ 2008-04-02 22:36 矿矿 阅读(131) | 评论 (0)编辑 收藏

1.public class Calculator{
 static int sum=0;
 static void add(int a,int b){
 // int sum=0;
  sum =a+b;
  System.out.println (sum);
 }
 static void sub(int a,int b){
    //int sum=0;
  sum=a-b;
  System.out.println (sum);
 }
 static void mul(int a,int b){
 // int sum=0;
  sum=a*b;
  System.out.println (sum);
 }
 static void div(int a,int b){
 // int sum=0;
  sum=a/b;
  System.out.println (sum);
 }
 public static void main(String[] args){
  add(1,2);
  sub(2,1);
  mul(1,2);
  div(2,1);
 }
}


2.public class Polygon{
 void printRec(int height,int width){
  for(int a=0;a<=height;a++){
   for(int j=0;j<=width;j++){
   System.out.print ("*");
   }
   System.out.println ();
  } 
 }
 void printTri(int height){
  for(int a=0;a<=height;a++){
   for(int j=a;j<height;j++){
    System.out.print("*");
   }
   System.out.println ();
  }
 }
  public static void main(String[] args){
   Polygon p=new Polygon();
   p.printRec(5,4);
   System.out.println ();
   p.printTri(5);
  }
}


3.public class Worker{
 String name;
 int price;
 int num;
 String place;
 Worker(String name,int price,int num,String place){
  this.name=name;
  this.price=price;
  this.num=num;
  this.place=place; 
 }
 void dispaly(){
  System.out.println ("姓名:"+name);
  System.out.println ("工资:"+price);
  System.out.println ("工号:"+num);
  System.out.println ("工作地:"+place);
 }
 

 public static void main(String[] args){
  Worker w=new Worker("DK",1000,99,"wuhan");
  w.dispaly();
 
 }
}

 

 

4.public class Compare{
 int num1,num2,num3;
 void max(){
  if(num1>num2){
   if(num1>num3){
    System.out.println (num1);
   }else{
    System.out.println (num3);
   }
  }else{
   if(num2>num3){
    System.out.println (num2);
   }else{
    System.out.println (num3);
   }
  }
 }
 void min(){
  if(num1>num2){
   if(num2>num3){
    System.out.println (num3);
   }else{
    System.out.println (num2);
   }
  }else{
   if(num1>num3){
    System.out.println (num3);
   }else{
    System.out.println (num1);
   }
  }
 }
 void avg(){
 
   System.out.println ((num1+num2+num3)/3);
 }
  public static void main(String[] args){
   Compare c=new Compare();
   c.num1=1;
   c.num2=2;
   c.num3=3;
   c.max();
   c.min();
   c.avg();
  }
}

 

 

5.public class User{
 String 用户名;
 String 密码;
 String 用户权限;
 User(String name,String password,String quanxian){
  用户名=name;
  密码=password;
  用户权限=quanxian;
 }
 void login(){
  if(用户名=="admin"&&密码=="123"){
   System.out.println ("登陆成功");
   System.out.println (用户权限="administrator");
  }else{
   if(用户名=="snake"&&密码=="123456"){
    System.out.println ("登陆失败");
    System.out.println (用户权限="user");
   }
  }
 }
 public static void main(String[] args){
  User u= new User("snake","123456"," ");
  u.login();
 }
}

 

 

posted @ 2008-04-01 19:51 矿矿 阅读(1427) | 评论 (7)编辑 收藏
关于RSS

RSS是站点用来和其他站点之间共享内容的一种简易方式(也叫聚合内容)

在门户网站大行其道,人们已经习惯通过搜索引擎来获取新闻资讯的今天,一种全新的资讯传播方式已经悄悄地来到我们身边,仔细观察一些网站,你可能注意到一些被标记为"XML"或"RSS"的橙色图标。

面对扑面而来的新闻,不用再花费大量的时间冲浪和从新闻网站下载,只要通过下载或购买一种小程序,这种技术被称为简易信息聚合(RSS:Really Simple Syndication)。RSS会收集和组织定制的新闻,按照你希望的格式、地点、时间和方式,直接传送到你的计算机上。新闻网站和那些在线日记作者已体会到了RSS提要带来的乐趣,这也使读者可以更容易跟踪RSS提要

RSS是一个缩写的英文术语,在英文中被认为有几个不同的源头,并被不同的技术团体做不同的解释。它既可以是"Rich Site Summary"(丰富站点摘要),或"RDF Site Summary"(RDF站点摘要),也可以是"Really Simple Syndication"(真正简易聚合)。现在已有的有Netscape, 1.0 (RSS-DEV版本),和 0.9x and 2.0 (UserLand Software版本) 0.9x和2.0。不过几乎所有能支持RSS的程序都可以浏览不同版本的RSS。

RSS是基于文本的格式。它是XML(可扩展标识语言)的一种形式。通常RSS文件都是标为XML,RSS files(通常也被称为RSS feeds或者channels)通常只包含简单的项目列表。一般而言,每一个项目都含有一个标题,一段简单的介绍,还有一个URL链接(比如是一个网页的地址)。其他的信息,例如日期,创建者的名字等等,都是可以选择的。

RSS是站点用来和其他站点之间共享内容的一种简易方式(也叫聚合内容),通常被用于新闻和其他按顺序排列的网站,例如Blog。一段项目的介绍可能包含新闻的全部介绍,Blog post等等。或者仅仅是额外的内容或者简短的介绍。这些项目的链接通常都能链接到全部的内容。网络用户可以在客户端借助于支持RSS的新闻聚合工具软件(例如NewzCrawler、FeedDemon),在不打开网站内容页面的情况下阅读支持RSS输出的网站内容。网站提供RSS输出,有利于让用户发现网站内容的更新。

RSS如何工作?首先您一般需要下载和安装一个RSS阅读器,然后从网站提供的聚合新闻目录列表中订阅您感兴趣的新闻栏目的内容。订阅后,您将会及时获得所订阅新闻频道的最新内容。 对于一般用户来说,用RSS订阅新闻可以像使用Outlook Express收取订阅的邮件一样简单;而对于Web应用程序的开发者而言,RSS的工作过程也不是那么复杂,至少比大多数其他常见的Web技术都更容易被理解和被实现。 有人认为,RSS的初衷似乎是为了给邮件列表订阅服务以致命的打击,若从RSS的应用方式来看,这几乎是不可避免的。但从实际效果来看,RSS最火爆的应用并非是商业信息的集中订阅,而是个人通过Web实现的信息聚合,一个典型的例子就是各国的网志作者(Blogger)首先成为最普遍的RSS应用人群。
posted @ 2008-04-01 19:42 矿矿 阅读(103) | 评论 (0)编辑 收藏
create database hy
on primary --默认就属于primary主文件组
(
--主数据文件的具体描述
 name='hy_data', --主数据文件的逻辑名
 filename='E:\temp1\hy_data.mdf', --主数据文件的物理名
size=3mb,--主数据文件的初始大小
maxsize=100mb,--主数据文件的增长最大值
filegrowth=10%--主数据文件的增长率
),(
  --次数据文件的具体描述,具体参数含义同主数据文件的含义
 name='hyn_data',
 filename='E:\temp1\hyn_data.ndf',
size=3mb,
maxsize=100mb,
filegrowth=10%
)
log on
(
--日志文件的具体描述,各参数的含义同主数据文件各参数含义
 name='hylog_log1',
 filename='E:\temp1\hylog1_log.ldf',
size=1mb,
filegrowth=10%
),(
--次日志文件的具体描述,具体各参数含义同上
name='hylog_log2',
 filename='E:\temp1\hylog2_log.ldf',
size=1mb,
filegrowth=10%
)
use hy
go
create table 忍者派别表   --创建忍者派别表
(
  编号 int,--编号
  称号 Nvarchar(20) not null --称号
)
go
 create table 师傅表--创建师傅表
(
 编号 int,--编号
 姓名 Nvarchar(20) not null,--姓名
 称号 int--称号
)
go
create table 忍者信息表--创建忍者信息表
(
编号 int identity(1,1),--编号
姓名 Nvarchar(20) not null,--姓名
性别 char(2),--性别
攻击力 int,--攻击力
派别 int not null,--派别
师傅 int not null--师傅
)
go
 --为忍者派别表添加约束
alter table 忍者派别表
add constraint pk_编号 primary key (编号)
go
--为师傅表添加约束
alter table 师傅表
add constraint pk_ 编号 primary key (编号)
称号 int not null
go
--为忍者信息表添加约束
alter table 忍者信息表
add constraint pk_ 编号 primary key (编号)
add constraint df_性别
default ('男') for 性别
攻击力 int check(攻击力>0)
派别 int references 忍者派别表(编号)
师傅 int not null references 师傅表(编号)
go
--为忍者派别表添加数据
insert into 忍者派别表(编号,称号)values(1,'木叶下忍')
insert into 忍者派别表(编号,称号)values(2,'木叶中忍')
insert into 忍者派别表(编号,称号)values(3,'木叶上忍')
insert into 忍者派别表(编号,称号)values(4,'砂隐下忍')
insert into 忍者派别表(编号,称号)values(5,'砂隐中忍')
insert into 忍者派别表(编号,称号)values(6,'砂隐上忍')
insert into 忍者派别表(编号,称号)values(7,'雨隐下忍')
insert into 忍者派别表(编号,称号)values(8,'雨隐中忍')
insert into 忍者派别表(编号,称号)values(9,'雨隐上忍')
insert into 忍者派别表(编号,称号)values(10,'音隐下忍')
insert into 忍者派别表(编号,称号)values(11,'音隐中忍')
insert into 忍者派别表(编号,称号)values(12,'音隐上忍')
insert into 忍者派别表(编号,称号)values(13,'岩隐下忍')
insert into 忍者派别表(编号,称号)values(14,'岩隐中忍')
insert into 忍者派别表(编号,称号)values(15,'岩隐上忍')
insert into 忍者派别表(编号,称号)values(16',云隐下忍')
insert into 忍者派别表(编号,称号)values(17',云隐中忍')
insert into 忍者派别表(编号,称号)values(18',云隐上忍')
insert into 忍者派别表(编号,称号)values(19',雾隐下忍')
insert into 忍者派别表(编号,称号)values(20',雾隐中忍 ')
insert into 忍者派别表(编号,称号)values(21',雾隐上忍')
insert into 忍者派别表(编号,称号)values(22',晓')
insert into 忍者派别表(编号,称号)values(23',逃之忍')
insert into 忍者派别表(编号,称号)values(24',火影 ')
insert into 忍者派别表(编号,称号)values(25',风影 ')
insert into 忍者派别表(编号,称号)values(26',雨影')
insert into 忍者派别表(编号,称号)values(27',音影')
insert into 忍者派别表(编号,称号)values(28',岩影')
insert into 忍者派别表(编号,称号)values(29',未知')
insert into 忍者派别表(编号,称号)values(99',三忍')
go
--为师傅表添加数据
insert into 师傅表(编号,姓名,称号)values(1,'旗木卡卡西',3)
insert into 师傅表(编号,姓名,称号)values(2,'依鲁卡',2)
insert into 师傅表(编号,姓名,称号)values(3,'自来也',99)
insert into 师傅表(编号,姓名,称号)values(4,'夕日红',3)
insert into 师傅表(编号,姓名,称号)values(5,'阿斯玛',3)
insert into 师傅表(编号,姓名,称号)values(6,'阿凯',3)
insert into 师傅表(编号,姓名,称号)values(7,'猿飞',24)
insert into 师傅表(编号,姓名,称号)values(8,'马基',6)
insert into 师傅表(编号,姓名,称号)values(9,'未知',29)
go
--为忍者信息表添加约束
insert into 忍者信息表(编号,姓名,性别,攻击力,派别,师傅)values('漩涡鸣人','男',100,1,1)
insert into 忍者信息表(编号,姓名,性别,攻击力,派别,师傅)values('日向雏田','男',100,1,5)
insert into 忍者信息表(编号,姓名,性别,攻击力,派别,师傅)values('春野樱','女',60,1,1)
insert into 忍者信息表(编号,姓名,性别,攻击力,派别,师傅)values('犬冢牙','男',100,1,4)
insert into 忍者信息表(编号,姓名,性别,攻击力,派别,师傅)values('犬冢牙','男',100,1,4)
insert into 忍者信息表(编号,姓名,性别,攻击力,派别,师傅)values('山中井野','女',100,1,4 )
insert into 忍者信息表(编号,姓名,性别,攻击力,派别,师傅)values('奈良鹿丸','男',150,2,5)
insert into 忍者信息表(编号,姓名,性别,攻击力,派别,师傅)values('宇智波佐助','男',200,1,1)
insert into 忍者信息表(编号,姓名,性别,攻击力,派别,师傅)values('秋道丁次','男',100,1,5)
insert into 忍者信息表(编号,姓名,性别,攻击力,派别,师傅)values('我爱罗','男',160,25,9)
insert into 忍者信息表(编号,姓名,性别,攻击力,派别,师傅)values('勘九郎','男',100,4,9)
insert into 忍者信息表(编号,姓名,性别,攻击力,派别,师傅)values('手鞠','女',110,4,9)
insert into 忍者信息表(编号,姓名,性别,攻击力,派别,师傅)values('白','男',120,20,9)
insert into 忍者信息表(编号,姓名,性别,攻击力,派别,师傅)values('桃地再不斩','男',180,23,9)
insert into 忍者信息表(编号,姓名,性别,攻击力,派别,师傅)values('干柿鬼鲛','男',250,22,9)
insert into 忍者信息表(编号,姓名,性别,攻击力,派别,师傅)values('药师兜','男',120,11,9)
go
--查询数据
select * from 忍者派别表
select * from 师傅表
select * from 忍者信息表



posted @ 2008-03-23 21:02 矿矿 阅读(148) | 评论 (0)编辑 收藏

一、三层体系架构

1.表示层(USL):主要表示Web方式,也可以表示成WINFORM方式。如果逻辑层相当强大和完善,无论表现层如何定义和更改,逻辑层都能完善地提供服务。

2.业务逻辑层(BLL):主要是针对具体的问题的操作,也可以理解成对数据层的操作,对数据业务逻辑处理。如果说数据层是积木,那逻辑层就是对这些积木的搭建。

3.数据访问层(DAL):主要是对原始数据(数据库或者文本文件等存放数据的形式)的操作层,而不是指原始数据,也就是说,是对数据的操作,而不是数据库,具体为业务逻辑层或表示层提供数据服务。



二、具体区分

1.表示层:主要对用户的请求接受,以及数据的返回,为客户端提供应用程序的访问。

2.业务逻辑层:主要负责对数据层的操作,也就是说把一些数据层的操作进行组合。

3.数据访问层:主要看你的数据层里面有没有包含逻辑处理,实际上他的各个函数主要完成各个对数据文件的操作,而不必管其他操作。


三、总结

三层结构是一种严格分层方法,即数据访问层只能被业务逻辑层访问,业务逻辑层只能被表示层访问,用户通过表示层将请求传送给业务逻辑层,业务逻辑层完成相关业务规则和逻辑,并通过数据访问层访问数据库获得数据,然后按照相反的顺序依次返回将数据显示在表示层。

posted @ 2008-01-20 01:51 矿矿 阅读(151) | 评论 (0)编辑 收藏

 

一、 引言

  JMX(Java管理扩展)提供了一组工具用来管理本地和远程应用程序、系统对象、设备等。本文将解释如何使用JMX(JSR 160)来远程控制Web应用程序,并将解释应用程序中可用于JMX客户的代码,同时将展示使用如MC4J和jManage等的不同客户如何连接到支持JMX的应用程序。此外,我们还将详细地讨论使用RMI协议和JNDI来保护通讯层。
       首先我们要分析一个简单的web应用程序,它监控已经登陆的用户数目并通过一个安全的JMX服务来显示该项统计。我们还将运行这个应用程序的多个实例并且从所有的运行实例中跟踪这个统计数字。当然,你可以下载这个示例web应用程序。它需要你安装J2SE 5.0 SDK并且你的JAVA_HOME环境变量指向基安装目录。J2SE 5.0实现了1.2版本的JMX API和JMX 1.0版本的Remote API。同时还需要一个支持Servlet的容器;我使用的是Apache Tomcat 5.5.12。另外,我还使用Apache Ant来构建这一示例应用程序。

  二、 建立示例应用程序

  首先,你要下载示例应用程序并且使用ant war(更多的细节见build.XML中的注释)来创建一个WAR文件。把jmxapp.war复制到Tomcat的webapps目录。假定Tomcat正在运行于你的本地机器的端口8080,那么该应用程序的URL将是:

http://localhost:8080/jmxapp

  如果你看到一个提示你输入名字和口令的登陆屏幕,那么一切已经就绪了。

  三、 跟踪一些有意义的数据

  本文中的应用程序使用Struts框架来提交登录表单。一旦提交结束,即执行LoginAction.execute(..)方法-它将简单地检查是否用户的ID为"hello"以及是否其口令为"world"。如果二者都正确,那么登录成功并且控制被导向login_success.JSP;如果不正确,那么我们返回到登录表单。根据登录成功与否决定调用incrementSuccessLogins(HttpServletRequest)方法还是incrementFailedLogins(HttpServletRequest)方法。现在,让我们先分析一下incrementFailedLogins(HttpServletRequest):

private void incrementFailedLogins(HttpServletRequest request) {
 HttpSession session = request.getSession();
 ServletContext context =session.getServletContext();
 Integer num = (Integer) context.getAttribute( Constants.FAILED_LOGINS_KEY);
 int newValue = 1;
 if (num != null) { newValue = num.intValue() + 1; }
 context.setAttribute( Constants.FAILED_LOGINS_KEY, new Integer(newValue));
}

  这个方法增加一个在应用程序范围存储的FAILED_LOGINS_KEY变量。这个incrementSuccessLogins(HttpServletRequest)方法是以相似的方法实现的。该应用程序追踪有多少人成功地登录和有多少人认证失败。这真不错,但是我们该如何存取这些数据?这就是引入JMX的原因。

  四、 创建JMX MBeans

  MBeans基础知识及其适于JMX架构的方面超出了本文所讨论的范围。我们将为我们的应用程序简单地创建、实现、暴露和保护一个MBean。我们所感兴趣的是暴露相应与下列两个方法的两种数据。下面是我们的简单MBean接口:

public interface LoginStatsMBean {
 public int getFailedLogins();
 public int getSuccessLogins();
}

  这两个方法简单地返回成功和失败登陆的数目。LoginStatsMBean的实现-LoginStats,为上面两种方法提供了一种具体的实现。让我们分析一下getFailedLogins()实现:

public int getFailedLogins() {
 ServletContext context = Config.getServletContext();
 Integer val = (Integer) context.getAttribute( Constants.FAILED_LOGINS_KEY);
 return (val == null) ? 0 : val.intValue();
}

  该方法返回一个存储在ServletContext中的值。getSuccessLogins()方法是以相似的方式实现的。

  五、 创建和保护一个JMX代理

  管理应用程序的JMX相关方面的JMXAgent类有以下几个责任:

  1. 创建一个MBeanServer。

  2. 用MBeanServer注册LoginStatsMBean。

  3. 创建一个JMXConnector以允许远程客户进行连接。

   o 包含对JNDI的使用。

   o 也必须有一个RMI注册运行。

  4. 使用一个用户名和口令保护JMXConnector。

  5. 分别在应用程序启动和停止时,启动和停止JMXConnector。

  JMXAgent的类轮廓是:

public class JMXAgent {
public JMXAgent() {
//初始化JMX服务器
}
public void start() {
//启动JMX服务器
}
//在应用程序结束时调用
public void stop() {
//停止JMX服务器
}
}

  让我们理解在该构造器的这部分代码-它能够使得客户远程地监控该应用程序。

  用MBeans创建一个MBeanServer

  我们首先创建一个MBeanServer对象。它是JMX基础结构的核心组件,它允许我们暴露我们的MBeans作为可管理的对象。MBeanServerFactory.createMBeanServer(String)方法使得这一任务极为轻松。所提供的参数是服务器的域。可以把它当作这个MBeanServer的唯一的名字。然后,我们用MbeanServe来注册LoginStatsMBean。MBeanServer.reGISterMBean(Object,ObjectName)方法使用的参数有两个:一个是MBean实现的一个实例;另一个是类型ObjectName的一个对象-它用于唯一地标识该MBean;在这种情况下,DOMAIN+":name=LoginStats"就足够了。

MBeanServer server = MBeanServerFactory.createMBeanServer(DOMAIN);
server.registerMBean(new LoginStats(),new ObjectName(DOMAIN+ ":name=LoginStats"));
六、 创建JMXServiceURL

  到现在为止,我们已经创建了一个MBeanServer并且用它注册了LoginStatsMBean。下一步是使得该服务器对客户可用。为此,我们必须创建一个JMXServiceURL-它描述了客户将用来存取该JMX服务的URL:

JMXServiceURL url = new JMXServiceURL("rmi",null,
Constants.MBEAN_SERVER_PORT,
"/jndi/rmi://localhost:" +Constants.RMI_REGISTRY_PORT +"/jmxapp");

  让我们细致地分析一下上面一行代码。该JMXServiceURL构造器使用了四个参数:

  1. 在连接时使用的协议(rmi,jmxmp,iiop,等等)。

  2. JMX服务的主机。用localhost作为参数就足够了。然而,提供null强制JMXServiceURL找到可能是最好的主机名。例如,在这种情况下,它将把null翻译成zarar-这是我的计算机的名字。

  3. JMX服务使用的端口。

  4. 最后,我们必须提供URL路径-它指示怎样找到JMX服务。在这种情况下,它会是/jndi/rmi://localhost:1099/jmxapp。

  其中,/jndi部分是指,客户必须为JMX服务做一下JNDI查询。rmi://localhost:1099指示,存在一个运行于本机的端口1099的RMI注册。这里的jmxapp是在RMI注册中唯一标识这个JMX服务的。在JMXServiceURL对象上的一个toString()产生下列结果:

service:jmx:rmi://zarar:9589/jndi/rmi://localhost:1100/jmxapp

  上面是客户将最终使用来连接到该JMX服务的URL。J2SE 5.0文档有关于这个URL结构的更为详细的解释。

  (一) 保护服务

  J2SE 5.0提供了一种有利于JMX用一种容易的方式进行用户认证的机制。我创建了一个简单的文本文件-它存储用户名和口令信息。文件的内容是:

zarar siddiqi
fyodor dostoevsky

  用户zarar和fyodor被分别通过口令siddiqi和dostoevsky认证。下一步是创建并保护一个JMXConnectorServer,它暴露了该MbeanServer。username/password文件的路径被存储在该键下的一个映射中-jmx.remote.x.password.file。这个映射在以后创建JMXConnectorServer时使用。

ServletContext context = Config.getServletContext();
//得到存储jmx用户信息的文件
String userFile =context.getRealPath("/")+"/Web-INF/classes/"+Constants.JMX_USERS_FILE;
//创建authenticator并且初始化RMI服务器
Map<string> env = new HashMap<string>();
env.put("jmx.remote.x.password.file", userFile);
现在,让我们创建JMXConnectorServer。下面一行代码完成这一功能:
connectorServer = JMXConnectorServerFactory.
newJMXConnectorServer(url, env, server);

  这个JMXConnectorServerFactory.newJMXConnectorServer(JMXServiceURL,Map,MBeanServer)方法使用我们刚创建的三个对象作为参数-它们是JMXServiceURL,存储认证信息的映射和MBeanServer。其中,connectorServer实例变量允许我们分别在应用程序启动和停止时,分别用start()和stop()来启动和停止JMXConnectorServer。

  提示 尽管JSR 160的J2SE 5.0实现相当有力;但是另外的实现,例如MX4J,也提供了一些类-它们提供了方便的特性,例如口令混淆,也就是PasswordAuthenticator类。

  七、 启动RMI注册

  在早些时候,我提到RMI注册并且指出当访问服务时执行一个JNDI查询。然而,现在我们没有一个正运行的RMI注册,因此一个JNDI查询将失败。一个RMI注册的启动可以用手工方式或编程方式来实现。

  (一) 使用命令行

  在你的WindowsLinux命令行上,输入下列一名来启动一个RMI注册:

rmiregistry &

  这将启动你的默认主机和端口(分别是localhost和1109)的RMI注册。然而,对于我们的web应用程序来说,我们不可能依赖一个在应用程序启动时可用的RMI而宁愿用编程方式来实现之。

  (二) 以编程方式启动RMI注册

  为了以编程方式启动RMI注册,你可以使用LocateRegistry.createRegistry(int port)方法。该方法返回类型注册的一个对象。当我们想在应用程序一端终止这个注册时,我们保存这个参考。就在我们启动我们的在JMXAgent.start()中的JMXConnectorServer之前,我们首先启动RMI注册,使用下列代码行:

registry = LocateRegistry.createRegistry(Constants.RMI_REGISTRY_PORT);

  在应用程序一端,在JMXAgent.stop()中停止JMXConnectorServer之后,调用下列方法来终止该注册:

UnicastRemoteObject.unexportObject(registry,true);

  注意,StartupListener类触发了应用程序开始和结束任务。
八、 访问我们的JMX服务

  我们可以有好几种方法来存取JSR 160服务。为此,我们可以通过编程或通过使用一个GUI来实现。

  (一) 使用MC4J连接

  通过把jmxapp.war复制到Tomcat的Webapps目录来发布该应用程序。下载并且安装MC4J。一旦安装完,创建一新的类型JSR 160的服务器连接并且指定该服务器URL-它在应用程序启动时在应用程序服务器日志中打印。在我的示例中,它是:

service:jmx:rmi://zarar:9589/jndi/rmi://localhost:1100/jmxapp

  提供用户名和口令,MC4J分别把它们参考为"Principle"和"Credentials"。点击Next将把你带到一个屏幕-在此你可以定制你的classpath。默认设置应该工作正常,并且你可以点击"Finish"来连接到该JMX服务。一旦建立连接,浏览如图1所示的MC4J树结构,直到你找到LoginStats MBean实现的"Properties"选项。


图1.MC4J视图

  点击Properties显示统计,如图2所示:


图2.属性窗口

  (二) 使用jManage连接到一个"簇"

  通过把jmxapp.war复制到Tomcat的webapps目录发布该应用程序。请注意一下在应用程序启动时所打印的URL。接下来,发布这个应用程序的另一个实例-通过改变Constants类中的RMI_REGISTRY_PORT并且MBEAN_SERVER_PORT变量,这样该应用程序的第二个实例就不会试图使用已经在使用的端口了。改变在build.XML文件中的app.name属性,以便新的实例将被发布到一个不同的上下文(例如,jmxapp2)。用ant创建一个清理的war文件-它将在其目录下创建jmxapp2.war。把jmxapp2.war复制到Tomcat的webapps目录。该应用程序将要发布,而且现在你有相同应用程序的两个实例在运行了。我再次提醒你注意在启动时所打印的URL。

  下载和安装jManage。一旦安装了,使用jManage的web接口来创建一个JSR 160应用程序-通过使用主页中的"添加新应用程序"链接。"添加应用程序"页面显示在图3中:


图3."添加应用程序"页面

  为要发布的第二个应用程序重复前面的步骤并再次使用适当的用户名、口令和URL。。一旦你创建了这两个应用程序,你必须通过遵循在主页中找到的"添加新应用程序簇"链接来创建一个簇。现在,把这两个已经创建的应用程序添加到你的簇上,如图4所示:


图4.添加应用程序簇页面


  好了,我们已经完成了!从主页上,点击簇中的一个应用程序,然后点击"Find More Objects"按钮。你将看到name=LoginStats MBean;点击它,则你就会看到我们已经暴露的FailedLogins和SuccessLogins属性。点击在该同一页面上的"Cluster View"链接将显示与图5相类似的一个页面-其中,你可以看到两个应用程序的运行计数统计:


图5.针对jmxapp和jmxapp2的簇视图

  试着登录到两个应用程序(http://localhost:8080/jmxapp和http://localhost:8080/jmxapp2)并且观察这些数字是怎样改变的。

  九、 结论

  现在你已经知道了怎样使你的新的和现有web应用程序支持JMX并且安全地管理它们-使用MC4J和jManage。尽管J2SE 5.0提供了JMX说明书的一个有力的实现,但是另外的开源工程例如XMOJO和MX4J还提供了另外的特征,例如经由web接口甚至更多的方式的连接。如果有兴趣的读者想了解更多地有关JMX的知识,你可以看一下J. Steven Perry写的《Java Management Extensions》一书。如果你对远程应用程序管理感兴趣的话,Jeff Hanson写的《Connecting JMX客户and Servers》将是很有阅读价值的,其中提供了许多真实世界的例子。

posted @ 2008-01-20 01:47 矿矿 阅读(231) | 评论 (0)编辑 收藏
          J2SE 5.0中的Java.util.concurrent程序包提供了一个新的线程框架组件,这个框架组件处理了与建立、执行和管理线程相关的很多低层细节信息。在本文中我们将细致地了解一下它的重要特性。

  如果你使用C、C++或Java先前的版本进行多线程编程,就知道在代码中管理线程是多么头疼的事情。在单线程程序中,代码中引起应用程序失败的bug每次都在同一个点出现。但是在多线程程序中,只有某些原因遇到一起的时候才会出现失败。由于预见可能引发应用程序失败的所有条件是非常困难的,所以多线程编程是有挑战性的。有些程序员从根本上避免这种挑战,而另外一些--聪明的解决问题的人员--则一直坐在他们的计算机面前直到问题解决。

  J2SE 5.0平台包含了一个新的并发工具程序包。这个程序包中的类替并发类(concurrent classe)或并发设计中使用的应用程序建立阻塞(blocking)。该并发工具包含下面一些内容:

  · 高性能的、灵活的线程池

  · 异步执行事务的框架组件

  · 为并发访问优化过的集合类宿主(host)

  本文介绍了J2SE 5.0框架组件类和它们的重要特性。本文的下载代码提供了一些简单的、容易使用的示例,它演示了所有的新线程框架组件类。你在阅读文章内容之后运行这些示例可以使自己对这些特性有更好的理解。

  Executor(执行器)框架组件

  Executor框架组件提供了一个简单的、标准的、可扩充的类,它提供了一些有用的功能,如果没有这些功能,我们要手工实现这些它们,会觉得十分单调和困难。该框架组件使调用、调度和执行的操作标准化了。它通过一组执行策略为控制异步事务提供了支持。

  Executor接口执行已提交的可以运行的事务。它提供了一条途径,允许我们把事务提交从事务执行机制中分离出来。程序员通常使用Executor代替显式地(explicitly)建立线程。Executor接口也提供事务的同步和异步执行。

  对于同步执行,使用下面的命令:

Class MySynExecutor implements Executor{
 public void execute(Runnable r) {
  r.run();
 } 
}

  对于异步执行,使用下面的命令:

Class MyASynExecutor implements Executor{
 public void execute(Runnable r) {
  new Thread(r).start();
 }
}

  ExecutorService(执行器服务)类

  ExecutorService类为管理一个或多个异步事务的终止和跟踪事务执行的过程提供了方法。代码下载中的MyExecutorService.java文件演示了管理事务终止的过程。它初始化了大小为三个的线程池,然后依次添加了线程。当线程的数量达到线程池的大小限制时,它调用关闭(shutdown)方法。在调用shutdown()方法之后,这个线程池不再接受新事务的执行。在等待十秒以后,该线程池调用shutDownNow()。这个方法会尽最大的努力来终止所有运行中的事务。在示例中,应用程序试图终止运行中的线程失败了。

  ScheduledExecutorService(调度执行器服务)

  ScheduledExecutorService类是我的最喜欢的类。它对于调度那些周期性执行的事务非常方便,而周期性执行的事务对于清除工作(例如清除你的应用程序建立的临时文件等等)尤其有用。下载代码中的MyScheduledExecutorService.java文件通过每五秒钟发出"嘟嘟"一声演示了调度的过程:

final Runnable beeper = new Runnable() {
 public void run() { System.out.println("beep"); }
};
final ScheduledFuture beeperHandle =scheduler.scheduleAtFixedRate(beeper, 1, 5, SECONDS);
posted @ 2008-01-20 01:43 矿矿 阅读(2379) | 评论 (3)编辑 收藏
        首先说一说进入计算机专业的目的,我个人是因为十分喜欢IT业,很喜欢折腾电脑,所以在填报志愿是毫不犹豫的在报了的所有的学校都填写的计算机专业,梦想着进入计算机专业后能遇见很多高手,能交到几个知己,谁之进来后却大失所望。计算机专业的学生有很多以前对计算机不怎么了解,而且还有部分人进大学前连计算机摸都没摸过,对计算机很熟悉的很少,高手更是凤毛麟角,大多数人是服从了父母之命,显而易见,目前社会最热的行业是IT业,工资最高的也是IT业,抱着这个因素,大多数考生的父母都让自己的孩子进入了计算机专业,而大多数学生也天真的认为从计算机专业毕业后就能够像电视里演的大多数白领一样每天只用坐在办公室里和同事们聊聊天,和老板吃吃饭,每天签几个字然后就有高工资等着你去拿。

   进校后他们发现其实他们在专业课方面什么都听不懂,自己也一点兴趣都没有,没有兴趣那就没有学习的动力,而且这个专业是要靠悟性的,而兴趣是培养悟性的第一步,然后他们会发现越往后学专业课越难,也越听不懂,好一点的就会狠下心来,硬着头皮苦学一通,有可能也就能走出一片路来,而不好的就会就此放弃,只需要混着考试通过,混毕业,找个单位安心上班。有些人上了几年学连自己上哪些课都不知道;拿个程序他分不清是用C语言写的还是用PASCAL写的;不小心进了DOS不知道怎么再回到WINDOWS。但说起游戏来头头是道,好像每个都是职业玩家一样,有的每天只知道泡在网吧。这就是中国计算机人才下一代的悲哀!

   再说现在计算机专业大学生的学习和生活。大多数计算机专业的学生对本专业的发展及前景一无所知,每天都是看小说、玩游戏、看电影、打牌、喝酒、睡觉等等很有"前途"的事情。偶尔看见一两个同学看看与计算机专业有关的书,跑去拿来一看,全是什么"游戏攻略"、"黑客秘技"等此类书籍。还有的人连C语言和C++谁是谁都还没搞清楚,就拿本VC的书"刻苦钻研",真不知他们看懂了没有。好多学生都买了电脑,但用处都是游戏机+碟机+音响,每天都在用电脑玩着各种流行的游戏、看着最新的大片、听着时尚的音乐,就是不用电脑学习。有的学生甚至问我电脑除了玩游戏还能干什么,我问他你为什么这么问,他告诉我他觉得电脑只能用来玩游戏,不知道还能不能干干别的什么。据我了解,近几年在国内好几所高校的计算机专业的毕业生的毕业设计竟然是做网页,在大学了四年,学完了《数据结构》、《软件工程》、《C语言》等专业课后,竟然交了一个没有学过计算机的人自学一两天就能做好的东西!

  这就是大多数计算机专业的学生,在我在大学玩了两年之后,我突然明白该为自己的未来打算打算了,但还有许多人仍然还什么都不明白,所以就有了这篇文章。
如果你是以上我说的那种受父母之命来学计算机的学生,如果你看了《计算机应用文摘》第15期的《写给想当程序员的朋友》一文后,发现自己没有当程序员的欲望,那么我这里有几条路给你选择:
1、**页制作,将来去网站工作!
2、学习3D MAX等软件,去作动画!
3、学习美术设计!
4、网络,将来考个CCNA,去专业组网!
5、在保证能顺利毕业的前提下,去疯狂玩游戏,做个职业玩家或做一个或几个网络游戏的GM。(我身边就有这样的人)
6、以上五条都与计算机有关,要有一定的专业知识,但比起你的专业课简单多了。如果你看到这里还不觉得有适合你干的,那这条最适合你:在你们学校去修双学位,修一个自己感兴趣的专业,计算机真的不适合你!
如果以上几条有适合你的,那么你就努力去做适合你的那一片天地,去看杂志的下一篇文章,下面的文字你看了只会浪费你的时间。


   如果你是计算机专业的在校大学生,而且想当软件设计师,那么请往下看:
1、大学生活丰富多彩,会令你一生都难忘,但难忘有很多种,你可以学了很多东西而难忘,也会因为什么都没学到而难忘!
2、计算机专业是一个很枯燥的专业,但即来之、则安之,只要你努力学,也会发现其中的乐趣的。
3、记住:万丈高楼平地起!基础很重要,尤其是专业基础课,只有打好基础才能学得更深。
4、C语言是基础,很重要,如果你不学好C语言,那么什么高级语言你都学不好。
5、C语言与C++语言是两回事。就象大熊猫和小熊猫一样,只是名字很像!
6、请先学习专业课《数据结构》、《计算机组成原理》,不要刚开始就拿着一本VC在看,你连面向对象都搞不清楚,看VC没有任何用处。
7、对编程有一定的认识后,就可以学习C++了。(是C++而不是VC,这两个也是两码事!C++是一门语言,而VC教程则是讲解如何使用MFC类库,学习VC应建立在充分了解C++的基础之上。看VC的书,是学不了C++语言的。)
8、学习编程的秘诀是:编程,编程,再编程;
9、认真学习每一门专业课,那是你的吃饭碗。
10、在学校的实验室就算你做错一万次程序都不会有人骂你,如果你在公司你试试看!所以多去实验室上机,现在错的多了,毕业后就错的少了。
11、从现在开始,在写程序时就要养成良好的习惯。
12、不要漏掉书中任何一个练习题--请全部做完并记录下解题思路。
13、你会买好多参考书,那么请把书上的程序例子亲手输入到电脑上实践,即使配套光盘中有源代码。
14、VC、C#、.NET这些东西都会过时,不会过时的是数据结构和优秀的算法!
15、记住:书到用时方恨少。不要让这种事发生在你身上,在学校你有充足的时间和条件读书,多读书,如果有条件多读原版书,你要知道,当一个翻译者翻译一本书时,他会不知不觉把他的理念写进书中,那本书就会变得像鸡肋!
16、我还是强调认真听专业课,因为有些课像《数据结构》、《编译原理》、《操作系统》等等,这种课老师讲一分钟能让你明白的内容,你自己看要看好几个月,有的甚至看了好几年都看不明白。
17、抓住在学校里的各种实践的机会,要为自己积累经验,就业时经验比什么都有用。
18、多去图书馆,每个学校的图书馆都有很多好书等你去看!
19、编程不是技术活,而是体力活。
20、如果你决定了要当一个好的软件设计师,那么请你放弃游戏,除非你是那种每天只要玩游戏就能写出好程序的天才!
21、你要有足够的韧性和毅力!有个高手出了一道题测试你的韧性和毅力:找个10000以内的素数表,把它们全都抄下来,然后再检查三遍,如果能够不间断地完成这一工作,你就可以满足这一条。
22、找到只属于你自己的学习方法!不要盲目的追随别人的方法,适合自己的才是最好的!
23、请热爱软件设计这项工作!
以上的话有些是我的经验,有些是我从高手那里直接COPY来的,但他们都很有用,记住他们,并遵守他们,那你们一定会成功!

   对于大多数初学者来说,好多人有这种问题存在:我到底先学什么?学C/C++?还是学VC?还是学Borland C++ Builder呢?还是Delphi?哪一个更好呢?学习程序设计和学习程序设计语言究竟是怎么一个关系?初学者究竟应该如何取舍呢?就这些问题,我从一个高手那里看了一下的这段话,可以帮助在这方面有问题的人:学习程序设计就好比学习射击,而程序设计语言就对应射击中的气枪、手枪、步枪等各种枪械。学习射击必须要选择一种枪械,不可能没有枪还能学好射击的,也不可能同时学会使用所有的枪械。但是,如果掌握一种枪械的射击,再学别的也就触类旁通了。因为在熟悉一种枪械的同时,也学习了射击技术本身。再学其他的,自然事半功倍。学习程序设计也是一样,必然要从学习一门程序设计语言开始入手。在学会系统的编程理念之后,用什么工具都一样!

   之所以写这篇文章呢是因为自己眼看身边那么多的同学一个个都"不务正业",荒废了学业,心急如焚,自己也荒废了好几年,眼看微软的Windows从3.X到现在的2003 Server,而中国的软件业还是在原地踏步,难道我们真要每年等微软给他的操作系统换一次名字,我们给他交一次钱吗?这么大的利润为什么不留给我们自己,为什么不让别的国家给我们交钱呢?这是广大中国软件工程师的一个共同的梦,要实现这个梦的人是现在还在大学里的"软件设计师"们,他们是中国软件明天的希望!希望广大计算机业的大学生看到这篇文章后,睡觉的能醒来,玩游戏的能停下来,在网吧的能出来,一起拿起课本,坐在电脑前,用程序写出中国软件业明天的辉煌!

附: 虽然非常的现实,对有些同学来说有点残酷,但是的是一针见血!!!!! 
posted @ 2008-01-20 01:38 矿矿 阅读(453) | 评论 (1)编辑 收藏
前段时间考过了SUN CERTIFIED JAVA PROGRAMMER ,考完后一直很忙,现在闲下来,和大家分享一下考试的经验 。

  1 ) JAVA 2 PLAT FORM 考试科目是310-025 ,有59题,及格线是61%,即答对36题。考试时间是90 分钟。特别令人厌恶的是考试前有个AGREEMENT,连你读它的时间也被计算在内。小弟开始不知道,还在慢慢读,突然发现已经用了3分钟,赶紧开始作题。估计 AGREEMENT 没有什么重要的东西,可以直接跳过。时间勉强够用,我大概花了60分钟作完题,剩下20多分钟检查,居然又给我发现了3-5 题错误,都是一时疏忽,落入题目设下的圈套,所以一定要留时间检查。可惜我剩下10 题左右没有时间检查 。

  2)考试范围非常窄。基本上都是基本语言知识,象SWING,JSP,SERVLET,JDBC,BEANS等等都不涉及。大家可以到SUN 网站上下载考试大纲。考试范围窄不意味着容易,相反,一些很基本的东西被翻来覆去,变着花样考,反而更难 。

  3)考试只有选择题,包括单选和复选。多数复选题明确指明有几个答案,不会搞错。

  4)印象中几乎所有的考题都涉及2-3个以上的知识点,几乎没有可以一眼就看出答案的题目。70%的考题是给你一段程序,然后问运行结果变量的值。这种题目非常容易落入陷阱,一不小心就被费了。还有20%的题目是给你几个陈述句,选正确的。这些陈述句都是考很偏很偏的东西,也不太好答。基本上我的经验是:如果一个题目马上能看出答案,请你在仔细研究一下题目,多数情况是你落入陷阱了。如果一个题目你能很明确的看出来他要考你什么知识点,那这个题目就完成一半了。最惨的是知道题目要考你什么,但是忘记了或没有复习相关知识细节,只好胡猜答案了。

  5)考试的一个重点是INNER CLASS。印象中一半以上的题目和他有关。都是大CLASS套小CLASS 等。我复习时花了很多时间在这上面,以为自己很懂了,结果考试是还是有问题。一定要透彻理解相关定义,语法,特别是各种各样的MODIFIER 的用法。有很多很特殊的MODIFER 规则。这些规则一定要熟练掌握并牢记在心。

  6)考试的另一个重点是循环语句。我考,我自以为对循环控制语句很熟悉了,结果考试考一些很偏很特别的用法,虽然慢慢作都能作出来,但浪费太多时间在这上面,实在可惜。大家好好看看书。

  7)其它的象:CASTING ,IO ,LAYOUT ,EVEN HANDLING,AWT,THREAD,GARBAGECOLLECTION,MATH CLASS 等等,都有若干考题。

  8)考试题目几乎完全不体现实际应用。如果我有一个JAVA 编译器在身边,几乎所有的考题都可以轻松解决。我感觉SUN 希望考生能象JAVA 编译器一样熟悉JAVA 的特殊语法和特殊规则。这实际是完全没有必要的。

  9)我收集了很多模拟考题和BRAINDUMP ,有近千题。奇怪的是只有不到10 题出现在考试中,看来SUN 的考试题库实行的可能是动态题库,考背BRAINDUMP 是没有什么希望通过了。而且程序考题只有稍微改动一个符号,结果就完全不同,BRAINDUMP 很多题目靠不住。所以大家一定要在一定实际经验的基础上,好好看透一本辅导书,多作题,多分析题,多思考,才能比较容易通过考试。

  10)不管大家如何评价认证考试,反正考多几个证书不是坏事。起码加薪找工比较方便。 I have:SCJP, MCSE, MCSD, MCDBA, MCSE+Internet.haha...It is better than nothing.Don't trust the people who sell SCJP questions online!It is very useless and a lot of errors!Work on your own experience!

posted @ 2008-01-20 01:32 矿矿 阅读(338) | 评论 (1)编辑 收藏