各种jdk版本下载:http://www.oracle.com/technetwork/java/archive-139210.html
http://tianya23.blog.51cto.com/1081650/305251
- Java核心API需要掌握的程度
- Java的核心API是非常庞大的,这给开发者来说带来了很大的方便,经常人有评论,java让程序员变傻。
- 但是一些内容我认为是必须掌握的,否则不可以熟练运用java,也不会使用就很难办了。
- 1、java.lang包下的80%以上的类的功能的灵活运用。
- 2、java.util包下的80%以上的类的灵活运用,特别是集合类体系、正规表达式、时间、属性、和Timer.
- 3、java.io包下的60%以上的类的使用,理解IO体系的基于管道模型的设计思路以及常用IO类的特性和使用场合。
- 4、java.math包下的100%的内容。
- 5、java.net包下的60%以上的内容,对各个类的功能比较熟悉。
- 6、java.text包下的60%以上的内容,特别是各种格式化类。
- 7、熟练运用JDBC.
- 8、java.security包下40%以上的内容,如果对于安全没有接触的话根本就不可能掌握java.
- 9、AWT的基本内容,包括各种组件事件、监听器、布局管理器、常用组件、打印。
- 10、Swing的基本内容,和AWT的要求类似。
- 11、XML处理,熟悉SAX、DOM以及JDOM的优缺点并且能够使用其中的一种完成XML的解析及内容处理
Apache下面的重要内容:
commons:http://commons.apache.org/
jakarta:http://jakarta.apache.org/
- commons-pool-1.3.jar
- commons-logging-1.1.1.jar
- commons-lang-2.5.jar
- commons-io-1.4.jar
- commons-dbcp-1.2.2.jar
- commons-collections-3.1.jar
- commons-beanutils-1.7.0.jar
1、可变参数与foreach
- public class Demo01{
- public static void main(String args[]){
- System.out.print("不传递参数(fun()):") ;
- fun() ; // 不传递参数
- System.out.print("\n传递一个参数(fun(1)):") ;
- fun(1) ; // 传递一个参数
- System.out.print("\n传递五个参数(fun(1,2,3,4,5)):") ;
- fun(1,2,3,4,5) ;
- }
- public static void fun(int ... arg){ // 可变参数
- for(int x:arg){ // 使用foreach输出输出
- System.out.print(x + "、") ;
- }
- }
- };
2、多线程程序
(1)继承Thread类
- class MyThread extends Thread{ // 继承Thread类,作为线程的实现类
- private String name ; // 表示线程的名称
- public MyThread(String name){
- this.name = name ; // 通过构造方法配置name属性
- }
- public void run(){ // 覆写run()方法,作为线程 的操作主体
- for(int i=0;i<10;i++){
- System.out.println(name + "运行,i = " + i) ;
- }
- }
- };
- public class ThreadDemo02{
- public static void main(String args[]){
- MyThread mt1 = new MyThread("线程A ") ; // 实例化对象
- MyThread mt2 = new MyThread("线程B ") ; // 实例化对象
- mt1.start() ; // 调用线程主体
- mt2.start() ; // 调用线程主体
- }
- };
(2)实现Runnable接口
- class MyThread implements Runnable{ // 实现Runnable接口,作为线程的实现类
- private String name ; // 表示线程的名称
- public MyThread(String name){
- this.name = name ; // 通过构造方法配置name属性
- }
- public void run(){ // 覆写run()方法,作为线程 的操作主体
- for(int i=0;i<10;i++){
- System.out.println(name + "运行,i = " + i) ;
- }
- }
- };
- public class RunnableDemo01{
- public static void main(String args[]){
- MyThread mt1 = new MyThread("线程A ") ; // 实例化对象
- MyThread mt2 = new MyThread("线程B ") ; // 实例化对象
- Thread t1 = new Thread(mt1) ; // 实例化Thread类对象
- Thread t2 = new Thread(mt2) ; // 实例化Thread类对象
- t1.start() ; // 启动多线程
- t2.start() ; // 启动多线程
- }
- };
[注意]在资源共享时,比如100张票,使用
- MyThread mt1 = new MyThread("线程A ") ; // 实例化对象
- Thread t1 = new Thread(mt1) ; // 实例化Thread类对象
- Thread t2 = new Thread(mt1) ; // 实例化Thread类对象
- t1.start() ; // 启动多线程
- t2.start() ; // 启动多线程
3、计划任务类:Timer、TimerTask
- // 完成具体的任务操作
- import java.util.TimerTask ;
- import java.util.Date ;
- import java.text.SimpleDateFormat ;
- class MyTask extends TimerTask{ // 任务调度类都要继承TimerTask
- public void run(){
- SimpleDateFormat sdf = null ;
- sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS") ;
- System.out.println("当前系统时间为:" + sdf.format(new Date())) ;
- }
- };
测试类,进行调度执行:
- import java.util.Timer ;
- public class TestTask{
- public static void main(String args[]){
- Timer t = new Timer() ; // 建立Timer类对象
- MyTask mytask = new MyTask() ; // 定义任务
- t.schedule(mytask,1000,2000) ; // 设置任务的执行,1秒后开始,每2秒重复
- }
- };
【注意】
执行计划任务是使用后台多线程实现的,如果主线程退出,则无法继续执行该计划任务。例如在单元测试中使用,需要将测试方法Thread.sleep(10000000);休眠主线程,保证其不退出方可达到预期的目的。
4、观察着模式实现
- import java.util.* ;
- class House extends Observable{ // 表示房子可以被观察
- private float price ;// 价钱
- public House(float price){
- this.price = price ;
- }
- public float getPrice(){
- return this.price ;
- }
- public void setPrice(float price){
- // 每一次修改的时候都应该引起观察者的注意
- super.setChanged() ; // 设置变化点
- super.notifyObservers(price) ;// 价格被改变
- this.price = price ;
- }
- public String toString(){
- return "房子价格为:" + this.price ;
- }
- };
- class HousePriceObserver implements Observer{
- private String name ;
- public HousePriceObserver(String name){ // 设置每一个购房者的名字
- this.name = name ;
- }
- public void update(Observable o,Object arg){
- if(arg instanceof Float){
- System.out.print(this.name + "观察到价格更改为:") ;
- System.out.println(((Float)arg).floatValue()) ;
- }
- }
- };
- public class ObserDemo01{
- public static void main(String args[]){
- House h = new House(1000000) ;
- HousePriceObserver hpo1 = new HousePriceObserver("购房者A") ;
- HousePriceObserver hpo2 = new HousePriceObserver("购房者B") ;
- HousePriceObserver hpo3 = new HousePriceObserver("购房者C") ;
- h.addObserver(hpo1) ;
- h.addObserver(hpo2) ;
- h.addObserver(hpo3) ;
- System.out.println(h) ; // 输出房子价格
- h.setPrice(666666) ; // 修改房子价格
- System.out.println(h) ; // 输出房子价格
- }
- };
5、本机字符编码
- public class CharSetDemo01{
- public static void main(String args[]){
- System.out.println("系统默认编码:" +
- System.getProperty("file.encoding")) ; // 获取当前系统编码
- }
- };
6、妙用异或运算2个整数数组的差集
异或=a`b+b`a
true ^true = false
false^false = flase
true^false = true
false^true =true
从这个关系上,我们可以看到 按位异或,同样的整数异或的结果为0。这样我们可以把 N整数和N-1的整数做异或运算,就知道最后一个数,就是2个数组差集。
代码如下:
- var a=[5,2,3,4,9]
- var b=[9,2,3,4]
- c=0
- for(var i=0;i<a.length;i++){
- c ^=a[i]
- }
- for(var j=0;j<b.length;j++){
- c ^=b[j]
- }
- alert(c)
7、NIO(新IO)解决IO吞吐慢的问题: Selector
- import java.net.InetSocketAddress ;
- import java.net.ServerSocket ;
- import java.util.Set ;
- import java.util.Iterator ;
- import java.util.Date ;
- import java.nio.channels.ServerSocketChannel ;
- import java.nio.ByteBuffer ;
- import java.nio.channels.SocketChannel ;
- import java.nio.channels.Selector ;
- import java.nio.channels.SelectionKey ;
- public class DateServer{
- public static void main(String args[]) throws Exception {
- int ports[] = {8000,8001,8002,8003,8005,8006} ; // 表示五个监听端口
- Selector selector = Selector.open() ; // 通过open()方法找到Selector
- for(int i=0;i<ports.length;i++){
- ServerSocketChannel initSer = null ;
- initSer = ServerSocketChannel.open() ; // 打开服务器的通道
- initSer.configureBlocking(false) ; // 服务器配置为非阻塞
- ServerSocket initSock = initSer.socket() ;
- InetSocketAddress address = null ;
- address = new InetSocketAddress(ports[i]) ; // 实例化绑定地址
- initSock.bind(address) ; // 进行服务的绑定
- initSer.register(selector,SelectionKey.OP_ACCEPT) ; // 等待连接
- System.out.println("服务器运行,在" + ports[i] + "端口监听。") ;
- }
- // 要接收全部生成的key,并通过连接进行判断是否获取客户端的输出
- int keysAdd = 0 ;
- while((keysAdd=selector.select())>0){ // 选择一组键,并且相应的通道已经准备就绪
- Set<SelectionKey> selectedKeys = selector.selectedKeys() ;// 取出全部生成的key
- Iterator<SelectionKey> iter = selectedKeys.iterator() ;
- while(iter.hasNext()){
- SelectionKey key = iter.next() ; // 取出每一个key
- if(key.isAcceptable()){
- ServerSocketChannel server = (ServerSocketChannel)key.channel() ;
- SocketChannel client = server.accept() ; // 接收新连接
- client.configureBlocking(false) ;// 配置为非阻塞
- ByteBuffer outBuf = ByteBuffer.allocateDirect(1024) ; //
- outBuf.put(("当前的时间为:" + new Date()).getBytes()) ; // 向缓冲区中设置内容
- outBuf.flip() ;
- client.write(outBuf) ; // 输出内容
- client.close() ; // 关闭
- }
- }
- selectedKeys.clear() ; // 清楚全部的key
- }
- }
- }
可以通过telnet连接该端口,进行同时的(即异步)接收数据。
8、switch case中使用enum类型
- public enum Position {
- BOSS, ENGINEER, SALES;
- }
在switch、case语句中使用定义的枚举Postilion;【注意】case语句中不能出现Postilion这个枚举类型
- public class SalaryImpl implements Salary {
- @Override
- public float getSalary(Position position) {
- float salary = 0.0f;
- switch (position) {
- case BOSS:
- salary = 7000f;
- break;
- case ENGINEER:
- salary = 5000f;
- break;
- case SALES:
- salary = 3000f;
- break;
- default:
- salary = 1000f;
- }
- return salary;
- }
- }
9、将JSON格式转换为Set
- import java.io.File;
- import java.io.IOException;
- import java.util.HashSet;
- import java.util.Set;
- import net.sf.json.JSONArray;
- import net.sf.json.JsonConfig;
- import org.apache.commons.io.FileUtils;
- public class JsonFile {
- @SuppressWarnings("unchecked")
- public static Set<String> load(String fileName) throws Exception {
- try {
- File newBackup = new File(fileName);
- String jsonStr = FileUtils.readFileToString(newBackup);
- JsonConfig config = new JsonConfig();
- config.setRootClass(String.class);// 序列化前的元素类型
- config.setCollectionType(Set.class);// 序列化前的集合类型
- return (HashSet<String>) JSONArray.toCollection(JSONArray
- .fromObject(jsonStr), config);
- } catch (IOException e) {
- throw new RuntimeException("load backup fail,path:" + fileName, e);
- }
- }
- }
10、通过URL取得链接的内容(html文档)
- public class GetURLContent {
- public static String getContent(String urlname) {
- String message = "";
- try {
- URL url = new URL(urlname);
- HttpURLConnection connect = (HttpURLConnection) url
- .openConnection();
- connect.setDoInput(true);
- connect.setDoOutput(true);
- BufferedReader in = new BufferedReader(new InputStreamReader(
- connect.getInputStream()));
- String line = null;
- StringBuffer content = new StringBuffer();
- while ((line = in.readLine()) != null) {// line为返回值,这就可以判断是否成功、
- content.append(line);
- }
- in.close();
- in = null;
- url = null;
- message = content.toString();
- //System.err.println(message);
- } catch (IOException ex) {
- ex.printStackTrace();
- } catch (Exception e) {
- System.out.println("出现错误" + e.getStackTrace());
- }
- return message;
- }
- public static void main(String[] args) {
- System.out
- .println(GetURLContent
- .getContent("http://10.20.136.29/r/aHR0cDovL3d3dy50YW9iYW8uY29t"));
- }
- }
11、Junit4的断言加强:放弃旧的断言,使用hamcrest断言
1. assertThat
2. 使用hamcrest的匹配方法
a) 更自然
3. 示例
- a)
- assertThat( n, allOf( greaterThan(1), lessThan(15) ) );
- assertThat( n, anyOf( greaterThan(16), lessThan(8) ) );
- assertThat( n, anything() );
- assertThat( str, is( "bjsxt" ) );
- assertThat( str, not( "bjxxt" ) );
- b)
- assertThat( str, containsString( "bjsxt" ) );
- assertThat( str, endsWith("bjsxt" ) );
- assertThat( str, startsWith( "bjsxt" ) );
- assertThat( n, equalTo( nExpected ) );
- assertThat( str, equalToIgnoringCase( "bjsxt" ) );
- assertThat( str, equalToIgnoringWhiteSpace( "bjsxt" ) );
- c)
- assertThat( d, closeTo( 3.0, 0.3 ) );
- assertThat( d, greaterThan(3.0) );
- assertThat( d, lessThan (10.0) );
- assertThat( d, greaterThanOrEqualTo (5.0) );
- assertThat( d, lessThanOrEqualTo (16.0) );
- d)
- assertThat( map, hasEntry( "bjsxt", "bjsxt" ) );
- assertThat( iterable, hasItem ( "bjsxt" ) );
- assertThat( map, hasKey ( "bjsxt" ) );
- assertThat( map, hasValue ( "bjsxt" ) );
12、oracle一个该死的BUG,后来查它的文档说叫限制.
from:http://blog.csdn.net/axman/archive/2006/07/07/887973.aspx
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- public class OracleBug {
- public static void main(String[] args) throws Exception {
- Class.forName("oracle.jdbc.driver.OracleDriver");
- Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@10.20.136.24:1521:orcl","scott","tiger");
- PreparedStatement ps = conn.prepareStatement("select * from tb_test",
- ResultSet.TYPE_SCROLL_SENSITIVE,
- ResultSet.CONCUR_UPDATABLE);
- ResultSet rs = ps.executeQuery();
- rs.moveToInsertRow();
- rs.updateString("name","axmannn1111");
- rs.insertRow();
- }
- }
会告诉你不能对只读结果集更新.竟然不能得到可更新结果集.
可是如果你"select col1,col2..... from tb_test",就可以,
13、运行时异常的设计和使用
好处:不用改变接口(即向外声明的标准);运行时异常不用显示的捕获,也可以捕获,根据调用者的能力
1、实现:继承自java.lang.RuntimeException, 且选中“Constructors from superclass”, 再补充完整serialVersionUID即可, 代码如下:
- public class ServiceException extends RuntimeException {
- private static final long serialVersionUID = 1L;
- public ServiceException() {
- // TODO Auto-generated constructor stub
- }
- public ServiceException(String message) {
- super(message);
- // TODO Auto-generated constructor stub
- }
- public ServiceException(Throwable cause) {
- super(cause);
- // TODO Auto-generated constructor stub
- }
- public ServiceException(String message, Throwable cause) {
- super(message, cause);
- // TODO Auto-generated constructor stub
- }
- }
调用方在catch中添加如下代码:throw new ServiceException(e.getMessage(),e);
2、初始化时出现异常,特别是加载文件的时候,直接抛出初始化异常:throw new ExceptionInInitializerError(e);
14、JSON到集合类型的转换
- String jsonStr = "[\"bac\",\"def\",\"him\"]";
- System.out.println(jsonStr);
- Collection<String> list = JSONArray.toCollection(JSONArray.fromObject(jsonStr), String.class);
- for(String str : list){
- System.out.println(str);
- }
输出结果:
- ["bac","def","him"]
- bac
- def
- him
15、 JDK自带命令native2ascii的用法
native2ascii是sun java sdk提供的一个工具。用来将别的文本类文件(比如*.txt,*.ini,*.properties,*.java等等)编码转为Unicode编码。为什么要进行转码,原因在于程序的国际化。
用法:native2ascii [-reverse] [-encoding 编码] [输入文件 [输出文件]]
-[options]:表示命令开关,有两个选项可供选择
-reverse:将Unicode编码转为本地或者指定编码,不指定编码情况下,将转为本地编码。
-encoding encoding_name:转换为指定编码,encoding_name为编码名称。
[inputfile [outputfile]]
inputfile:表示输入文件全名。
outputfile:输出文件名。如果缺少此参数,将输出到控制台
JDK中自带的native2ascii功能还是比较强的。简单做以下介绍。
1、只转换特定字符
在控制台中可以输入汉字回车后,就可以看到转移后的字符了。
Ctrl+C退出。
2、转换properties文件
将文件allMessages_zh_CN.input.properties编码后输出为allMessages_zh_CN.properties。
为了方便properties文件的管理,建议纯中文的配置文件用input命名。
3、反向单一properties文件
注意-reverse参数
4、批量反向所有的properties文件
使用工具UncodeReverse.exe
详见:批量转换Uncode编码的文件,地址 http://blog.csdn.net/z3h/archive/2008/01/25/2065912.aspx
native2ascii相关链接:
http://hi.baidu.com/suofang/blog/item/b38bb5019b6b0e03728da562.html
http://www.chinaitpower.com/A200507/2005-07-24/165716.html
16、IdentityHashMap使用
允许key相同,而value不同
- Map<Person, String> map = new IdentityHashMap<Person, String>();
- map.put(new Person("zhangsan",30), "zhangsan1");
- map.put(new Person("zhangsan",30), "zhangsan2");
- map.put(new Person("lisi",30), "lisi1");
- Set<Person> set = map.keySet();
- for(Person person : set){
- System.out.println(person + ": " + map.get(person));
- }
运行结果:
- Person [age=30, name=zhangsan]: zhangsan1
- Person [age=30, name=zhangsan]: zhangsan2
- Person [age=30, name=lisi]: lisi1
17、System类介绍
(1)得到系统的各种资源属性:System.getProperties();
- Properties pro = System.getProperties();
- pro.list(System.out);
18、setter方法的优雅处理
- public static final String DEFAULT_PATH_SEPARATOR = "/";
- private String pathSeparator = DEFAULT_PATH_SEPARATOR;
- public void setPathSeparator(String pathSeparator) {
- this.pathSeparator = (pathSeparator != null ? pathSeparator : DEFAULT_PATH_SEPARATOR);
- }
19、 CAS
1、CAS: CPU指令 和 程序并发原语中存在 CAS 概念, Compare and Set, 就是修改一个寄存器区域或变量值时,先检查 old value, old value相同再进行修改,否则放弃。
例如:
已知 int a = 1;
CAS 赋值为 compareAndSet( 1, 10);
这样,在多线程并发操作时,最终 a 将被原子性的修改,而不会发生冲突的结果。
而数据库的事务中并发冲突的场景与之非常类似,都是对共享资源竞争访问时的突出问题。
2. 基于CAS机制的数据库update操作
由CAS的原理,可以考虑以类似的方式处理数据库的update操作。
假定订单 OD_0100 的总价款为1100 元, 现在要将其修改为 1500 元,
where order_id = 'OD_0100'
采用 CAS 机制进行修改,假定已经知道订单修改前的总价款 1100,则update SQL为
update sale_order set order_amount = 1500.00
where order_id = 'OD_0100'
and order_amount = 1100.00
若出现并发冲突,例如:order_amount 已经先其他请求修改为 900, 那么上面的 update 语句的操作结果数为 0; 此时,客户端需要重新查询订单,再尝试第二次修改。 这类似于 CAS 中的自旋。
3. 与其他事务机制比较
数据库事务有悲观锁和乐观锁,乐观锁有一种机制是基于 version 字段来控制并发修改冲突。
与version事务机制类似,CAS事务也是一种细粒度的锁。然而,version 为行级锁,粒度过大; 而 CAS 事务为列级锁,粒度更小。 根据锁机制的一般原则,粒度越小,并发性能越高。
20、三元运算符
在返回值需要有默认值时常用:
return zipCode == null ? "" : zipCode;//如果为null, 则使用"",否则使用zipCode值。
21、CopyOnWriteArrayList:支持并发改动的List
- List<Integer> list = new ArrayList<Integer>();
- list.add(1);
- List<Integer> cw = list;
- cw.add(2);
- for(int a : list){
- System.out.println(a);
- }
- System.out.println("----------");
- for(int a : cw){
- System.out.println(a);
- }
结果:
- 1
- 2
- ----------
- 1
- 2
使用CopyOnWriteArrayList, 则完全生成新的List, 实现深度拷贝。
- 1
- ----------
- 1
- 2
22、网络编程相关
- @Test public void test1() throws Exception{
- InetAddress localAddr = InetAddress.getLocalHost();
- InetAddress remoteAddr = InetAddress.getByName("www.sina.com.cn");
- System.out.println("local addr: " + localAddr.getHostAddress());
- System.out.println("remote addr: " + remoteAddr.getHostAddress());
- boolean access = localAddr.isReachable(1000); //测试1000毫秒内是否可达
- System.out.println(access);
- }
URL类使用:
- URL url = new URL("http","www.mldnjava.cn",80,"/curriculum.htm") ;
- InputStream input = url.openStream() ; // 打开输入流
- Scanner scan = new Scanner(input) ; // 实例化Scanner类
- scan.useDelimiter("\n") ; // 设置读取分隔符
- while(scan.hasNext()){
- System.out.println(scan.next()) ;
- }
URLConnection类使用:
- URL url = new URL("http://www.mldnjava.cn") ;
- URLConnection urlCon = url.openConnection() ; // 建立连接
- System.out.println("内容大小:" + urlCon.getContentLength()) ;
- System.out.println("内容类型:" + urlCon.getContentType()) ;
URLEncoder和URLDecoder使用:常常在有中文、空格之类需要网络传输的情况下使用
- String keyWord = "张三" ;
- String encod = URLEncoder.encode(keyWord,"UTF-8") ; // 进行编码的操作
- System.out.println("编码之后的内容:" + encod) ;
- String decod = URLDecoder.decode(encod,"UTF-8") ; // 进行解码操作
- System.out.println("解码之后的内容:" + decod) ;