第一篇:達內學習心得:JDBC總結:系列筆記之四
達內學習心得:JDBC總結:系列筆記之四
參賽學員:常彥博 獲獎獎項:二等獎
說明:(又花了幾個小時把JDBC筆記轉成了word版!筆記內容真實,都是課上及TTS上內容,不是從網上復制粘貼來的!同時也不會去刷點擊率!不想評分的按F5刷新頁面即可!不用選擇分數,一旦選擇就不能改了!也可以拿到電子版后再來評分!Q在下)1)此筆記為本人系列筆記之一:Java、Oracle、PL/SQL、JDBC、XML、HTML、CSS、JavaScript、Servlet??
2)筆記內容整理了:JDBC(范傳奇老師主講,占筆記內容100%)。3)此筆記已打印出成品,一共19頁!(不包括目錄)。排版格式大部分按照畢業論文做的!有目錄、章節、頁眉、頁腳、縮進、一二三級標題等。同時排版格式也照顧到了雙面打印,所以電子版可直接雙面打印,不需要調格式。
因此,本人的系列筆記平均花費20個小時以上(筆記純手工輸入)!每天的總結、排版很辛苦!之前有很多朋友拿到了我分享的筆記,因此還望各位尊重他人勞動成果(你懂得~~)。4)評選系統由于不能上傳word版,所以格式、布局上不太好看,如文中的注意事項有特殊項目符號,這里顯示的是字母u和字母v,有的圖片也不能顯示!內容太長,老是提交失敗!只能一點一點發!
5)希望大家多多支持,評選結束后,我會找時間統一分享給大家所有的筆記!之前拿到過的朋友,也可以再要,因為修改、更新了很多內容。
——————————————————————————————————————————————————————————————————— 目錄
一、JDBC概述 1 1.1 什么是JDBC 1 1.2什么是驅動 1 1.3 SQL lite 1 1.4如何使用Java連接某種數據庫 1 1.5連接數據庫并操作 1 1.6連接數據庫時常見的錯誤 1
二、JDBC核心API 2 2.1 Connection 2 2.2 Statement 2 2.3 ResultSet 2 2.4 DriverManager 2 2.5 UUID3 2.6案例:使用JDBC連接數據庫,并操作SQL語句 3 2.7案例:通過JDBC創建表 4 2.8案例:使用JDBC向表中插入數據 4 2.9遍歷Student_chang表 5
三、JDBC核心API:PreparedStatement 6 3.1Statement的缺點 6 3.2PreparedStatement的優點 6 3.3案例詳見第五章StudentDAO類 6
四、Connection封裝 7
五、DAO 8 5.1持久類封裝 8 5.2 DAO層 8 5.3 Properties類 8 5.4案例:注冊系統 8
六、批處理 12 6.1批處理的優點 12 6.2 JDBC批處理API 12 6.3案例:詳見8.4案例step7 12
七、事務處理 13 7.1事務特性ACID 13 7.2 JDBC中對事務的支持(API)13
八、DAO事務封裝 14 8.1ThreadLocal原理 14 8.2原理圖 14 8.3ThreadLocal核心API 14 8.4案例:登錄系統(使用ThreadLocal實現連接共享)14
九、分頁查詢 17 9.1分頁查詢的基本原理 17 9.2為何使用分頁查詢 17 9.3 Oracle分頁查詢SQL語句 17 9.4 MySQL分頁查詢SQL語句 17 9.5“假”分頁 17 9.6案例:分頁查詢 18
一、JDBC概述 1.1 什么是JDBC 1)Java的設計者希望使用相同的方式訪問不同的數據庫。
2)JDBC是Java用于統一連接數據庫并操作數據庫的一組通用接口定義(即通過一系列接口定義了訪問數據庫的通用API)。
3)JDBC是連接數據庫的規范,不同的數據庫廠商若想讓Java語言可以對其操作,就需要實現一組類,這組類需要實現Java提供的這組用于連接數據庫的接口,并實現其中定義的相關方法。那么不同的數據庫廠商根據各自數據庫的特點,去提供對JDBC的實現(實現類包),那么這組類就是該數據庫的驅動包了。4)原理圖:
1.2什么是驅動
簡單的說就是讓軟件知道如何去操作硬件。1.3 SQL lite 是輕量級的數據庫,常用于嵌入式。1.4如何使用Java連接某種數據庫 需要兩個部分:1)使用JDBC連接數據庫(導入某數據庫的.jar包)。
2)提供對該數據庫的驅動包(使用靜態方法Class.forName注冊驅動)。1.5連接數據庫并操作
1)打開與數據庫的連接(使用DriverManager.getConnection獲取連接)。2)執行SQL語句(使用Statement或者PreparedStatement)。3)得到結果。
1.6連接數據庫時常見的錯誤
1)報錯ClassNotFoundException則有兩種情況: ①驅動包沒導入。
②Class.forName()中的字符串拼寫有誤。2)報錯port number,應注意:
①連接數據庫時輸入數據庫路徑時沒有添加端口號。
②Oracle數據庫的完整寫法應為:jdbc:oracle:thin:@IP地址:端口號:數據庫名 u 注意事項:Oracle數據庫默認端口號1521。MySql數據庫默認端口號為3306
二、JDBC核心API 2.1 Connection 接口,需導入java.sql.Connnection包,與特定數據庫進行連接(會話)。2.2 Statement 接口,需導入java.sql.Statement包,用于執行靜態SQL語句并返回它所生成結果的對象。1)ResultSet executeQuery(String sql)throws SQLException方法:執行給定的SQL語句(通常為靜態SQL SELECT語句),該語句返回單個ResultSet對象。
2)boolean execute(String sql)throws SQLException方法:執行給定的SQL語句,該語句可能返回多個結果。如果第一個結果為ResultSet對象,則返回true;如果其為更新計數或者不存在任何結果,則返回false。詳細介紹請看2.6案例注釋。
3)int executeUpdate(String sql)throws SQLException方法:執行給定SQL語句,該語句可能為INSERT、UPDATE、DELETE(DML語句),或者不返回任何內容的DDL語句。返回值:①對于數據操作語句(DML語句),返回行計數。②對于DDL語句,返回0。
4)boolean execute(String sql)方法:返回結果為true、false,常用與執行表級操作的SQL語句,如建表、刪表等,創建表若失敗實際上是會直接拋出異常的。false:為建表成功的標志。5)exectue()方法:原則上可以執行任意SQL語句。返回true:若執行結果為一個結果集(ResultSet)。返回false:為其他信息(如影響表數據總條數等)。所以我們通常不會使用execute去執行查詢語句。
6)int executeUpdate(String sql)throws SQLException方法:返回值int,返回值為當前執行的SQL語句影響了數據庫數據的總條數;該方法常用與執行insert、update、delete語句。7)在底層一定會用到網絡Socket和流,但我們不用關心使用字符還是字節接收,都由Statement做了。2.3 ResultSet 接口,表示數據庫結果集的數據表(很像一個集合),通常通過執行查詢數據庫的語句生成。1)ResultSet特點:按行遍歷,按字段取值。
2)它的next()方法包含了是否有下一條記錄的hasnext()方法。
3)按字段取值時,getString(int)方法中的int,代表結果集的第幾列,u 注意事項:這里的int從1開始,和Java對索引的習慣不同。2.4 DriverManager 它是管理一組JDBC驅動程序的類。1)Connection getConnection(String url,String user,String password)方法:靜態方法,建立與給定數據庫URL的連接(DriverManager試圖從已注冊的JDBC驅動程序集中選擇一個適當的驅動程序)。
2)DriverManager如何知道某種數據庫已注冊的?
例如:oracle.jdbc.driver.OracleDriver類在Class.forName()的時候被載入JVM; 而OracleDriver是JDBC中Driver的子類,它被要求在靜態初始化的時候要將自身驅動的信息通過DriverManager的靜態方法注冊進去,這樣DriverManager就知道應該如何通過OracleDriver去連接該數據庫了。所以之后就可以通過DrvierManager的另一個靜態方法:getConnection()來根據之前注冊的驅動信息獲取連接了:
Connection conn=DriverManager.getConnetion(“",”“,”“);2.5 UUID UUID為通用唯一標識碼(Universally Unique Indentifier)對于大數據量的表來說,UUID是存放ID最好的方式。1)Java提供的支持
UUID類:UUID.randomUUID().toString():獲得一個36位不重復的字符串。2)Oracle提供的支持
函數sys_guid():獲取一個32位不重復的字符串。2.6案例:使用JDBC連接數據庫,并操作SQL語句 /** 連接數據庫一定要捕獲異常的 */ Connection conn=null;//定義在try外面是用于在finally塊中關閉它,同時局部變量在使用前,一定要初始化!
try{ /** 與數據庫進行連接分為兩步:1)注冊驅動:不同的數據庫實現不盡相同,所以要使用不同數據庫廠商提供的驅動包。連接不同數據庫,傳入的字符串不盡相同,但是目的相同,都是注冊驅動。而對于驅動包路徑,名字是固定的,基本上不會變的!2)根據數據庫的位置(路徑)以及用戶名和密碼進行連接 */ Class.forName(”oracle.jdbc.driver.OracleDriver“);/** 路徑:不同數據庫連接的路徑寫法不盡相同,Oracle的寫法:
jdbc:oracle:thin:@HOST:DB_NAME
其中HOST包含兩部分:IP地址和端口號;本機則使用localhost或127.0.0.1 */ conn=DriverManager.getConnection(”jdbc:oracle:thin:@192.168.0.20:1521:tarena“, ”jsd1304“,”jsd1304“);/** 使用SQL語句來操作數據庫,若想執行SQL語句,我們需要使用一個專門處理SQL語句的類,這個類叫做Statement */ Statement state=conn.createStatement();/** user_tables是Oracle用于存儲當前用戶創建的所有表的信息,其中一個字段叫做table_name用戶保存的表名 */ String sql=”SELECT table_name FROM user_tables“;/** 通過Statement執行查詢語句,當查詢完畢后,數據庫會將查詢結果返回,Statement會將查詢結果存儲到ResultSet中 */ ResultSet rs=state.executeQuery(sql);while(rs.next()){ //按行遍歷,包含了是否有下一條記錄的方法hasnext()/** 按字段取值;整數參數:結果集的第幾列。注意:這里從1開始,和Java對索引的習慣不同 */ String tableName=rs.getString(1);System.out.println(tableName);} /** 底層一定會用到網絡socket和流,但我們不用關心使用字符還是字節接收,都由Statement做了 */ rs.close();state.close();}catch(Exception e){ e.printStackTrace();}finally{ if(conn!=null){ try { conn.close();} catch(SQLException e){ e.printStackTrace();} } } u 注意事項: 養成良好的編碼習慣:所有SQL關鍵字用純大寫,其他內容用純小寫。2.7案例:通過JDBC創建表 Connection conn=null;try{ //1 注冊驅動
Class.forName(”oracle.jdbc.driver.OracleDriver“);//2 打開連接,支持import java.sql.*,但全導入較耗費性能 conn=DriverManager.getConnection(”jdbc:oracle:thin:@192.168.0.20:1521:tarena“,”jsd1304“,”jsd1304“);//3 創建用于執行SQL語句的Statement Statement state=conn.createStatement();//創建建表語句
String sql=”CREATE TABLE Student_chang(“ + ”id varchar2(36)PRIMARY KEY,“ +”name varchar2(30),“ + ”age number(2),“ + ”sex varchar2(2)“ + ”)“;//execute()方法詳見2.2節
if(!state.execute(sql)){ System.out.println(”創建表成功!“);}else{ System.out.println(”創建失敗!“);} state.close();}catch(Exception e){ e.printStackTrace();}finally{ if(conn!=null){
try { conn.close();} catch(SQLException e){
e.printStackTrace();
}
} } 2.8案例:使用JDBC向表中插入數據 Connection conn=null;try{ Class.forName(”oracle.jdbc.driver.OracleDriver“);conn=DriverManager.getConnection(”jdbc:oracle:thin:@192.168.0.20:1521:tarena“,”jsd1304“,”jsd1304“);Statement state=conn.createStatement();//UUID詳見2.5 String uuid=UUID.randomUUID().toString();System.out.println(uuid);String sql=”INSERT INTO Student_chang VALUES('“+uuid +”','Chang',22,'1')“;
//或String sql=”INSERT INTO Student_chang VALUES(sys_guid(),'chang',23,'1')“;//判斷insert語句是否成功,看返回值是否大于0,executeUpdate方法詳見2.2 if(state.executeUpdate(sql)>0){ System.out.println(”插入數據成功“);} state.close();}catch(Exception e){ e.printStackTrace();}finally{ if(conn!=null){ try { conn.close();} catch(SQLException e){
e.printStackTrace();} } } 2.9遍歷Student_chang表 Connection conn=null;try{ Class.forName(”oracle.jdbc.driver.OracleDriver“);conn=DriverManager.getConnection(”jdbc:oracle:thin:@192.168.0.20:1521:tarena“,”jsd1304“,”jsd1304“);Statement state=conn.createStatement();String sql=”SELECT * FROM Student_chang“;ResultSet rs=state.executeQuery(sql);while(rs.next()){ String id=rs.getString(1);String name=rs.getString(”name“);//不知第幾列也可寫列名 int age=rs.getInt(”age“);String sex=rs.getString(4).equals(”1“)?”男“:”女“;System.out.println(id+”,“+name+”,“+age+”,"+sex);} rs.close();state.close();}catch(Exception e){ e.printStackTrace();}finally{ if(conn!=null){ try { conn.close();} catch(SQLException e){ e.printStackTrace();} } }
三、JDBC核心API:PreparedStatement 3.1Statement的缺點
1)用Statement操作時代碼的可讀性和可維護性差,編寫SQL語句復雜。
2)Statement操作SQL語句,每執行一次都要對傳入的語句編譯一次,效率比較差。3)不安全可能出現SQL注入攻擊,詳見9.6案例step3。
4)擴展:XSS攻擊、html代碼注入攻擊、struts2 OGNL存在可以遠程執行底層操作系統命令的漏洞。
3.2PreparedStatement的優點
1)PreparedStatement實例包含已編譯的SQL語句。包含于PreparedStatement對象中的SQL語句可具有一個或多個IN參數。IN參數的值在SQL語句創建時未被指定。該語句為每個IN參數保留一個問號(“?”)作為占位符,不考慮類型。每個問號的值必須在該語句執行之前,通過適當的setString、setInt、setDouble??等方法來提供。
2)由于PreparedStatement對象已預編譯過,所以其執行速度要快于Statement對象。因此,多次執行的SQL語句經常創建為PreparedStatement對象,以提高效率。3)PreparedStatement繼承于Statement,其中三種方法:execute、executeQuery、executeUpdate都已被更改為不再需要參數了。因為我們在獲取PreparedStatement時已經將SQL語句傳入了。所以執行就可以,不需要再傳入SQL。4)PreparedStatement可以進行批量處理。5)可以防止SQL注入攻擊。u 注意事項:
v 使用預編譯語句,你傳入的任何內容就不會和原來的語句發生任何匹配的關系,只要全使用預編譯語句,你就不用對傳入的數據作任何的過濾。
v 對一個表只作一個操作用PreparedStatement,效率高、方便 v 對表進行2種及以上的操作用Statement。3.3案例詳見第五章StudentDAO類 ???????? ????????
五、DAO 5.1持久類封裝
對象關系映射(ORM)使用描述對象和數據庫之間映射的元數據,將Java程序中的對象自動持久化到關系數據庫中。1)表和類對應。2)表中的字段和類的屬性對應。3)記錄和對象對應。5.2 DAO層
1)DAO:數據連接對象(DataAccessObjects)
2)作用:將數據庫中的數據轉化為Java的對象并返回(即讀數據),將Java的對象轉化為數據庫中表的一條數據(即寫數據)。
3)Java對象在這里就是所謂的實體entity,DAO要達到的目的:對數據庫數據的操作面向對象化。
4)實體:用Java中的對象去描述數據庫中的某表中的某一條記錄。
比如:Student表有字段id、name、age、sex,則對應的Java類中有Student類,屬性有id、name、age、sex 5)實體類:用于對應數據庫中的表。通常實體類的名字和數據庫中表的名字一致。u 注意事項:實體類代表表,屬性代表字段,對象代表一條數據。5.3 Properties類
用于讀取“.properties”文本文件的類,導入java.util.Properties包。1)“.properties”文件是一個純文本文件,里面定義的內容格式有要求,必須是key=value的形式,并且以行為單位。一行只記錄一條數據!2)Properties類可以方便的讀取properties文件,并將內容以類似HashMap的形式進行讀取。3)db.properties文件里的內容如下:
jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@192.168.0.20:1521:tarena
jdbc.user=jsd1304
jdbc.pwd=jsd1304 u 注意事項:讀取的都是字符串!不用寫雙引號,無空格!
4)getProperty(String key)方法:該方法可以從properties文件中獲取數據,如:jdbc.driver=oracle.jdbc.driver.OracleDriver。獲取方式是將jdbc.driver以key作為參數調用方法。返回的就是等號右面的值oracle.jdbc.driver.OracleDriver了。
第二篇:達內學習心得:俄羅斯方塊項目總結
達內學員:我的俄羅斯方塊項目總結
獲獎學員:陳啟壯 所獲獎項:三等獎 內容
俄羅斯方塊一共三個類中間用等號隔開 軟件的開發過程 明確業務需求
用自然語言,將業務功能描述清楚
...2 業務分析
找到有哪些業務對象,和圖片的分析
tetris(俄羅斯方塊)
|-- score 累計分數
|-- lines 銷毀的行數
|-- Wall(墻 20行x10列)
|-- 20row(行)
|--10 col cell(列)
|-- tetromino(4格方塊,有7種形態)
|-- 4 cell
|--nextOne 下一個準備下落的方塊
|-- 4 cell 數據模型,一切業務對象轉換為數字表示
場地按照行列劃分為20x10格子
格子有屬性row,col,color 4 類 設計
Tetris
|--int score
|--int lines
|--Cell[20][10] wall
|--Tetromino tetromino
|
|--Cell[4] cells
|--row
|--col
|--color 5 算法設計,就是如何利用數據的計算實現軟件的功能
4格方塊的初始形態: I S Z J L T O
就在初始數據的數值狀態設計
四格方塊的下落計算:就是將每個格子的row+1
就是將下落的業務功能,轉換為數字計算實現
左右移動
下落流程控制:控制方塊下落與墻之間的控制關系
1 合理的文字流程描述
2 分析文字描述中的功能(動作)為方法
3 用流程控制語句連接方法實現功能 嚴格測試結果!TestCase 左右移動流程控制
分數計算
界面的繪制
鍵盤事件控制
旋轉流程控制
加速下降流程控制
開始流程控制(Timer)
暫停流程控制
繼續流程控制
結束流程控制
首先是Cell類,最基本的類包含3個私有屬性和get,set方法,重寫Object類的toString輸出方法,并規定格子所具有的3個移動功能 package com.tarena.tetris;//包:小寫英文字母,域名倒寫.項目名 /** * 最小的格子
*/ public class Cell{
private int row;
private int col;
private int color;
public Cell(int row, int col, int color){
super();
this.row = row;
this.col = col;
this.color = color;
}
public int getCol(){
return col;
}
public void setCol(int col){
this.col = col;
}
public int getColor(){
return color;
}
public void setColor(int color){
this.color = color;
}
public int getRow(){
return row;
}
public void setRow(int row){
this.row = row;
}
public void left(){
col--;
}
public void right(){
col++;
}
public void drop(){
row++;
}
public String toString(){
return row+“,”+col;
} } =============================================================== package com.tarena.tetris;import java.util.Arrays;import java.util.Timer;import java.util.TimerTask;
import javax.swing.JPanel;//是能夠顯示的矩形面板區域 import javax.swing.JFrame;//窗口框
import javax.swing.border.LineBorder;//實現邊框 import java.awt.Color;import java.awt.Font;import java.awt.Graphics;import java.awt.event.KeyAdapter;import java.awt.event.KeyListener;import java.awt.event.KeyEvent;/* * 俄羅斯方塊類
* 俄羅斯方塊 擴展了(extends)系統的顯示面板,增加了墻和
* 正在下落的方塊
* */ public class Tetris extends JPanel{
public static final int ROWS = 20;
public static final int COLS= 10;
/*代表方塊下落著陸的墻*/
private Cell[][] wall = new Cell[ROWS][COLS];
/*是正在下落的方塊*/
private Tetromino tetromino;
/*下一個進入的方塊*/
private Tetromino nextOne;
private static int score;
private int lines;
Timer timer;
private boolean gameOver = false;
private boolean pause = false;//暫停
private static final int[] SCORE_LEVEL={0,1,4,10,100};
private static final Graphics Graphics = null;
/*銷毀(destory)滿行*/
//
0 1 2 3 4
/*在Tetris中添加方法,檢查游戲是否結束*/
public void rotateRightAction(){
tetromino.rotateRight();
if(outOfBounds()||coincide()){
tetromino.rotateLeft();
}
}
public void rotateLeftAction(){
tetromino.rotateLeft();
if(outOfBounds()||coincide()){
tetromino.rotateRight();
}
}
/*在Tetris中添加方法,檢查游戲是否結束*/
private boolean gameOver(){
gameOver = wall[0][4]!=null;
return gameOver;
}
/*在Tetris中添加方法*/
public void hardDropAction(){
while(canDrop()){
tetromino.softDrop();
}
tetrominoLandToWall();
destroy();
if(gameOver()){
gameOverAction();
}
nextTetromino();
}
public void destroy(){
int lines = 0;//統計本次銷毀的行數
for(int row = 0;row Cell[] line = wall[row]; if(fullCell(line)){ clearLine(row,wall); lines++;//每消除一行就累計加1 } } score += SCORE_LEVEL[lines]; this.lines +=lines; } public static void clearLine(int row,Cell[][] wall){ for(int i=row;i>1;i--){ System.arraycopy(wall[i-1],0,wall[i],0,wall[i].length); } Arrays.fill(wall[0],null); } public static boolean fullCell(Cell []line){ for(int col = 0;col if(line[col]==null){ return false;//找到空格子,這行沒有滿 } } return true; } public String toString(){//顯示全部的墻 String str = “"; for(int row = 0;row Cell[] line = wall[row]; for(int col = 0;col Cell cell = line[col]; if(tetromino.contains(row,col)){ str +=row+”,“+col+” “; }else{ str = str + cell + ” “; } } str +=”n“; } return str; } /*4格方塊下降流程 * 方塊移動到區域最下方或是著地到其他方塊上無法移動時,* 就會固定到該處,而新的方法快出現在區域上方開始下落。 * 如果能下降就繼續下降,* 否則就著陸到墻上,并且生成(隨機)下一個方塊 * */ public void softDropAction(){ if(canDrop()){//如果能下降 tetromino.softDrop();//方塊繼續下降 }else{ tetrominoLandToWall();//著陸到墻上 destroy();// if(gameOver()){ gameOverAction(); } nextTetromino();//生產(隨機)下一個方塊 } } private void startGameAction(){ gameOver = false; pause = false; score = 0; lines = 0; emptyWall(); nextTetromino(); repaint(); timer = new Timer(); timer.schedule(new TimerTask(){ public void run(){ softDropAction(); repaint(); } }, 500, 500); } private void emptyWall(){ for(int row=0;row Arrays.fill(wall[row],null); } } /*清理游戲結束現場,如:停止定時器等*/ private void gameOverAction(){ timer.cancel();//停止定時器 } /*檢查 方塊 是否能夠繼續下落:到底最低部,或者墻上 * 的下方有方塊,返回false不能下降,返回true可以下降 * */ public boolean canDrop(){ //檢查到底部 Cell[] cells = tetromino.getCells(); for(Cell cell:cells){ if(cell.getRow()==ROWS-1){ return false; } } //檢查墻上下方是否有方塊 for(Cell cell:cells){ int row = cell.getRow(); int col = cell.getCol(); Cell block = wall[row+1][col]; if(block!=null){ return false; } } return true; } /*方塊“著陸”到墻上,* 取出每個小cell * 找到cell的行號row和列號col * 將cell放置到wall[row][col]位置上 * */ public void tetrominoLandToWall(){ Cell[] cells = tetromino.getCells(); for(Cell cell:cells){ int row = cell.getRow(); int col = cell.getCol(); wall[row][col] = cell; } } /*生產(隨機)下一個方塊 * 1 下一個變為當前的* 2 隨機產生下一個 * */ public void nextTetromino(){ if(nextOne==null){//第一次nextOne是null時候先生產一個 nextOne = Tetromino.randomTetromino(); } tetromino = nextOne;//下一個變為當前的 nextOne = Tetromino.randomTetromino();//隨機產生下一個 if(tetromino==null){//處理第一次使用時候下一個是null tetromino=Tetromino.randomTetromino(); } } /*以格子為單位左右移動方塊 * 1)如果遇到左右邊界就不能移動了 * 2)如果與墻上的格子相撞就不能移動了 * 變通為: * 1)先將方塊左移動,* 2)檢查(移動結果是否出界),或者(重合) * 3)如果檢查失敗,就右移的回來 * * */ public void moveLeftAction(){ tetromino.moveLeft(); if(outOfBounds()|| coincide()){ tetromino.moveRight(); } } private boolean outOfBounds(){ Cell[] cells = tetromino.getCells(); for(int i = 0;i < cells.length;i++){ Cell cell = cells[i]; int row = cell.getRow(); int col = cell.getCol(); if(row == ROWS||col<0||col>=COLS){ return true; } } return false; } private boolean coincide(){ Cell[] cells = tetromino.getCells(); for(int i = 0;i < cells.length;i++){ Cell cell = cells[i]; int row = cell.getRow(); int col = cell.getCol(); if(row >0&&row &&wall[row][col]!=null){ return true;//重合 } } return false; } public void moveRightAction(){ tetromino.moveRight(); if(outOfBounds()|| coincide()){ tetromino.moveLeft(); } } public static final int CELL_SIZE = 25; /*在Tetris.java中添加main方法 作為軟件的啟動方法*/ public static void main(String []args){ JFrame frame = new JFrame(”俄羅斯方塊“); int wigth =(COLS+8)*CELL_SIZE +100; int height =ROWS*CELL_SIZE +100; frame.setSize(wigth,height); frame.setLocationRelativeTo(null);//居中 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設置關閉窗口就關閉軟件 frame.setLayout(null);//取消默認布局,取消自動充滿 Tetris panel = new Tetris(); panel.setLocation(45,25); panel.setSize((COLS+8)*CELL_SIZE,ROWS*CELL_SIZE); panel.setBorder(new LineBorder(Color.black)); frame.add(panel);//窗口中添加面板 frame.setVisible(true);//顯示窗口時候調用paint() panel.action(); } /*動作方法,這里是讓軟件開始動作,*/ public void action(){ //wall[18][2] = new Cell(18,2,0xff0000); startGameAction(); //重繪方法->盡快調用paint() //startGameAction(); //this 是當前Tetris面板 this.requestFocus();//為當前面板請求獲得輸入焦點 //this對象就獲得了輸入焦點,以后任何的 //鍵盤輸入(包括左右方向鍵)目標就是這個面板對象了! //addKeyLIstener添加鍵盤監聽,監聽那些按鍵輸入了 this.addKeyListener(new KeyAdapter(){ public void keyPressed(KeyEvent e){ int key = e.getKeyCode();//key按鍵 if(gameOver){ if(key==KeyEvent.VK_S){ startGameAction();//啟動游戲開始流程 } return; } if(pause){ if(key==KeyEvent.VK_C){ continueAction(); }return; } //System.out.println(”Type:“+e.getKeyCode()); switch(key){ case KeyEvent.VK_RIGHT :moveRightAction();break; case KeyEvent.VK_LEFT :moveLeftAction();break; case KeyEvent.VK_DOWN :softDropAction();break; case KeyEvent.VK_UP :rotateRightAction();break; case KeyEvent.VK_SPACE :hardDropAction();break; case KeyEvent.VK_P :pasueAction();break; } //按鍵->方塊移動方法->改變方塊數據->repaint() //->盡快調用paint()->利用新數據繪制 repaint(); } private void continueAction(){ pause = false; timer = new Timer(); timer.schedule(new TimerTask(){ public void run(){ softDropAction(); repaint(); } }, 500, 500); } private void pasueAction(){ pause = true; timer.cancel(); } }); } //JPanel 類利用paint(涂畫)方法繪制界面 //子類重寫paint方法可以修改繪圖邏輯 public static final int BORDER_COLOR = 0x667799; public static final int BG_COLOR = 0xC3D5EA; public static final int FONT_COLOR = 0; public void paint(Graphics g){ //g 代表綁定在當前面板上的畫筆 //利用畫筆在當前 面板上 繪制了一串字符! paintBackground(g);//填充背景 paintWall(g);//繪制墻 paintTetromino(g);//繪制當前方塊 paintNextOne(g);//繪制下一個方塊 paintScore(g);//繪制分數 paintTetrisBorder(g);//繪制邊線 } private void paintScore(Graphics g){ int x = 12 * CELL_SIZE; int y = 5 * CELL_SIZE; Font font = new Font(getFont().getName(),Font.BOLD,25); String str = ”分數: “+score; g.setColor(new Color(FONT_COLOR)); g.setFont(font); g.drawString(str, x, y); y+=2*CELL_SIZE; str = ”行數: “+lines; g.drawString(str, x, y); if(gameOver){ str = ”(T_T)![s]再來!“; y+=2*CELL_SIZE; g.drawString(str, x, y); } if(pause){ str = ”[c]繼續!“; y+=2*CELL_SIZE; g.drawString(str, x, y); }else{ str = ”[p]暫停!"; y+=2*CELL_SIZE; g.drawString(str, x, y); } } private void paintNextOne(Graphics g){ if(nextOne==null)//如果沒有4格方塊就返回,不繪制 return; for(Cell cell : nextOne.getCells()){ int row = cell.getRow()+1; int col = cell.getCol()+9; int x = col*CELL_SIZE; int y = row*CELL_SIZE; g.setColor(new Color(cell.getColor())); g.fillRect(x, y, CELL_SIZE, CELL_SIZE); g.setColor(new Color(BORDER_COLOR)); g.drawRect(x, y, CELL_SIZE, CELL_SIZE); } } private void paintTetromino(Graphics g){ if(tetromino==null)//如果沒有4格方塊就返回,不繪制 return; for(Cell cell : tetromino.getCells()){ int row = cell.getRow(); int col = cell.getCol(); int x = col*CELL_SIZE; int y = row*CELL_SIZE; g.setColor(new Color(cell.getColor())); g.fillRect(x, y, CELL_SIZE, CELL_SIZE); g.setColor(new Color(BORDER_COLOR)); g.drawRect(x, y, CELL_SIZE, CELL_SIZE); } } private void paintWall(Graphics g){ for(int row = 0;row for(int col = 0;col < COLS;col++){ Cell cell = wall[row][col]; int x = col*CELL_SIZE; int y = row*CELL_SIZE; if(cell == null){ //g.setColor(new Color(BORDER_COLOR)); // g.drawRect(x, y,// CELL_SIZE, CELL_SIZE); }else{ g.setColor(new Color(cell.getColor())); g.fillRect(x, y,CELL_SIZE, CELL_SIZE); g.setColor(new Color(BORDER_COLOR)); g.drawRect(col*CELL_SIZE, row*CELL_SIZE,CELL_SIZE, CELL_SIZE); } } } } private void paintBackground(Graphics g){ g.setColor(new Color(BG_COLOR)); g.fillRect(0, 0, getWidth(), getHeight()); } private void paintTetrisBorder(Graphics g){ g.setColor(new Color(BORDER_COLOR)); g.drawRect(0, 0, CELL_SIZE*COLS, CELL_SIZE*ROWS-1); g.drawRect(CELL_SIZE*COLS,0,CELL_SIZE*8-1, CELL_SIZE*ROWS-1); } } =============================================================== package com.tarena.tetris;import java.util.Arrays;import java.util.Random;/* * 四格方塊類,有7種子類:I T S Z J L O * */ public abstract class Tetromino { public static final int I_COLOR =0xff6600; public static final int T_COLOR =0xffff00; public static final int S_COLOR =0x66ccff; public static final int Z_COLOR =0x00ff00; public static final int J_COLOR =0x0000ff; public static final int L_COLOR =0xcc00ff; public static final int O_COLOR =0xff0000; protected Cell[] cells = new Cell[4]; /*四格方塊的下落,是四個格子一起下落*/ public void softDrop(){ for(int i = 0;i cells[i].drop(); } } /*向左移動一步*/ public void moveLeft(){ for(int i = 0;i Cell cell = cells[i];//引用賦值 cell.left(); } } public void moveRight(){ //增強for循環,是傳統數組迭代的“簡化版本”,//也稱為foreach循環(foreach迭代)(java 5以后) for(Cell cell:cells){//底層實現就是經典迭代 cell.right(); } } public Cell[] getCells(){ return cells; } protected Offset[] states;//旋轉的狀態 protected class Offset{ int row0,col0; int row1,col1; int row2,col2; int row3,col3; public Offset(int row0, int col0, int row1,int col1, int row2, int col2,int row3, int col3){ this.row0 = row0; this.col0 = col0; this.row1 = row1; this.col1 = col1; this.row2 = row2; this.col2 = col2; this.row3 = row3; this.col3 = col3; } } private int index = 10000-1; /*向右轉*/ public void rotateRight(){ index++; Offset offset = states[index%states.length]; Cell axis = cells[0];//找到軸(axis)的位置 cells[0].setRow(offset.row0+axis.getRow()); cells[0].setCol(offset.col0+axis.getCol()); cells[1].setRow(offset.row1+axis.getRow()); cells[1].setCol(offset.col1+axis.getCol()); cells[2].setRow(offset.row2+axis.getRow()); cells[2].setCol(offset.col2+axis.getCol()); cells[3].setRow(offset.row3+axis.getRow()); cells[3].setCol(offset.col3+axis.getCol()); } public void rotateLeft(){ index--; Offset offset = states[index%states.length]; Cell axis = cells[0];//找到軸(axis)的位置 cells[0].setRow(offset.row0+axis.getRow()); cells[0].setCol(offset.col0+axis.getCol()); cells[1].setRow(offset.row1+axis.getRow()); cells[1].setCol(offset.col1+axis.getCol()); cells[2].setRow(offset.row2+axis.getRow()); cells[2].setCol(offset.col2+axis.getCol()); cells[3].setRow(offset.row3+axis.getRow()); cells[3].setCol(offset.col3+axis.getCol()); } /*隨機生成一個具體方法*/ public static Tetromino randomTetromino(){ Random random = new Random(); int type = random.nextInt(7);//0~6 switch(type){ case 0:return new I(); case 1:return new T(); case 2:return new S(); case 3:return new J(); case 4:return new Z(); case 5:return new L(); case 6:return new O(); } return null; } public String toString(){ return Arrays.toString(cells); } public boolean contains(int row, int col){ for(int i =0;i Cell cell = cells[i]; if(cell.getRow()==row && cell.getCol()==col){ return true; } } return false; } } class I extends Tetromino{ public I(){ cells[0] = new Cell(0,4,I_COLOR); cells[1] = new Cell(0,3,I_COLOR); cells[2] = new Cell(0,5,I_COLOR); cells[3] = new Cell(0,6,I_COLOR); states = new Offset[]{ new Offset(0,0,-1,0,1,0,2,0),new Offset(0,0,0,-1,0,1,0,2),}; } } class T extends Tetromino{ public T(){ cells[0] = new Cell(0,4,T_COLOR); cells[1] = new Cell(0,3,T_COLOR); cells[2] = new Cell(0,5,T_COLOR); cells[3] = new Cell(1,4,T_COLOR); states = new Offset[]{ new Offset(0,0,1,0,-1,0,0,1),new Offset(0,0,0,-1,0,1,1,0),new Offset(0,0,1,0,-1,0,0,-1),new Offset(0,0,0,1,0,-1,-1,0),}; } } class S extends Tetromino{ public S(){ cells[0] = new Cell(0,4,S_COLOR); cells[1] = new Cell(0,5,S_COLOR); cells[2] = new Cell(1,3,S_COLOR); cells[3] = new Cell(1,4,S_COLOR); states = new Offset[]{ new Offset(0,0,-1,0,1,1,0,1),new Offset(0,0,0,1,1,-1,1,0),}; } } class Z extends Tetromino{ public Z(){ cells[0] = new Cell(0,4,Z_COLOR); cells[1] = new Cell(0,3,Z_COLOR); cells[2] = new Cell(1,4,Z_COLOR); cells[3] = new Cell(1,5,Z_COLOR); states = new Offset[]{ new Offset(0,0,-1,1,0,1,1,0),new Offset(0,0,-1,-1,-1,0,0,1),}; } } class J extends Tetromino{ public J(){ cells[0] = new Cell(0,4,J_COLOR); cells[1] = new Cell(0,3,J_COLOR); cells[2] = new Cell(0,5,J_COLOR); cells[3] = new Cell(1,5,J_COLOR); states = new Offset[]{ new Offset(0,0,-1,0,1,0,1,-1),new Offset(0,0,0,1,0,-1,-1,-1),new Offset(0,0,1,0,-1,0,-1,1),new Offset(0,0,0,-1,0,1,1,1),}; } } class L extends Tetromino{ public L(){ cells[0] = new Cell(0,4,L_COLOR); cells[1] = new Cell(0,3,L_COLOR); cells[2] = new Cell(0,5,L_COLOR); cells[3] = new Cell(1,3,L_COLOR); states = new Offset[]{ new Offset(0,0,-1,0,1,0,-1,-1),new Offset(0,0,0,1,0,-1,-1,1),new Offset(0,0,1,0,-1,0,1,1),new Offset(0,0,0,-1,0,1,1,-1),}; } } class O extends Tetromino{ public O(){ cells[0] = new Cell(0,4,O_COLOR); cells[1] = new Cell(0,5,O_COLOR); cells[2] = new Cell(1,4,O_COLOR); cells[3] = new Cell(1,5,O_COLOR); states = new Offset[]{ new Offset(0,0,0,1,1,0,1,1),new Offset(0,0,0,1,1,0,1,1),}; } } 達內培訓總結 今年的7月初我和大多數達內學員一樣,興奮的進入了達內進行培訓,開始了C/C++的培訓學習,轉眼間4個多月已經過了,也結束了我們培訓課程。雖然自己學的是軟件技術專業,但自己在來達內之前也沒有接觸過C跟C++,既然走在了這條路上,我想我會一直走在這條路上,給自己的這四個月來說下幾點: 1、端正自己學習的態度 在課程學習中如何端正自己的態度也是很重要的。在達內學習的過程中,每門課的時間都是很緊的,每天很辛苦,我也想過自己到底自己要不要學C/C++,但是自己還是保持了下來,有一個良好的心態去接受新的東西,哪些是自己懂的,哪些是自己不會的,自己還是要有一個計劃,跟不上老師的講課進度,也要試著去趕上老師的進度,調整自己的學習方法。 2、編程當作興趣 在學習之初感覺編程很枯燥,所以自己還是要培養出對編程的興趣。一開始其實多編程的興趣也不是很大,只是慢慢習慣了枯燥,不是很感興趣只要裝著很感興趣,久而久之開始對編程有了興趣,正所謂興趣才是最后的老師。 3、多敲敲代碼 程序員是代碼敲出來。在達內,每天學的東西到很多而且新的理論知識也多,然而那只是理論,和實際的應用還有很大差距,而這些差距只有在實際的代碼編寫中我們才能體會出來。所以還是每天堅持多敲敲多練練。總之,每天要保證一定量的代碼,這樣我們才會有真正水平上的提高。另外,在實際動手的過程中,還要多留心編譯器錯誤提示,也有助于我們對語言的學習和理解。 4、多堅持一下 學習C/C++畢竟是非常枯燥的一件事情,雖然我們可以培養自己的興趣,但是4個月的時間畢竟很讓人疲勞、很累,隨著時間的推移,我們剛開始時的興奮勁也慢慢減退了,有什么感覺沒什么希望,我們能做的就只有多堅持一下,忍得住寂寞,才守得住陣地,保得住成果。自己還是踏踏實實的堅持完成這4個月的學習,還一直在堅持。 其他的也沒有什么要說的,一切多看自己的能力。 達內學習心得:精心總結的面向對象 參賽學員:方錢有 獲獎獎項:二等獎 什么面向對象: 個人分析覺得:在程序設計里,面向對象是一種相對說法,相對于面向過程而言的; 面向“對象“:即重點在于“對象”;而面向過程:則重點在于“過程”,簡單說:就是我我們看待事物在眼光上注重點不一樣;比如說:我們評判一個女孩漂亮與否,有的人看重外表,有的人則看重“心靈”,只是側重點不一樣。 舉個例子:把大象裝進冰箱! 面向過程面向對象(注重一系列動作即過程)(注重動作所操作的承受者[“對象”]) “打開”冰箱“冰箱”打開“裝入”大象“大象”裝入“關閉”冰箱“冰箱”關閉 類:通俗的說類就是“一類事物的簡稱”,并且這些事物至少具有一點“共同的”特征.比如說:動物就是一個類 對象:就是某一類中一個具體的(就是可以具體描述出來的)東西,比如:動物(類)里的“狗”就是一個對象。(個人覺得對象相對于類而言的,因為狗又可以分好多種,‘狗’相對于‘哈士奇’是一個類,‘哈士奇’是‘狗’類的一個具體對象) 在生活中就拿描述汽車來說,我們都知道汽車都有4個輪子; 都有跑的功能 可以如下描述: 類汽車 屬性: 4個輪 功能: 跑 那么怎么在Java中描述汽車這類呢? class car{ int wheel=4;//屬性: 4個輪 void run(){//方法(功能): 跑 System.out.println(“是汽車都會跑”); } } 那么可見“出租車”應當是“汽車”這類的一個具體化(實實在在的例子即“實例”)對象,那自然出租車也就具備了汽車這類所具備的“共有”屬性功能! 如何創建一個出租車對象呢?java中通過new關鍵字來創建一個類的實例即對象,也叫類的實例化,就是把類具體化成一個實例嘛! 格式:類名對象名 =mew 類名() Cartexi =newCar(); 創建了“出租車”對象(實例)之后那么它也就有了如下“自己”的屬性和功能。 int wheel=4;//屬性: 4個輪 void run(){//功能: 跑 System.out.println(“我是出租車我也會跑”); } 我們如何來訪問對象中的它自己的屬性和方法呢? 格式:對象.屬性;對象.方法名();這一點也驗證了面向對象編程的側重點在于“對 象”上; texi.wheel;texi.run() ******************************************************************************* ******************************************************************************* ******************************************************************************* 1.封裝: 從字面可以解讀為將東西封起來再裝好。要想拿到里面的東西就得有相應的方法打開,才能 拿到。 舉例來說:一個房間的門如果沒有上鎖,那么大家都可以進去拿東西,但現在我們不想讓誰 都進來拿東西,我們可以將房門上鎖,只對外提供一把鑰匙,只有有鑰匙的人才能進來,這 就是“封裝”現象! 在java程序中,“封裝”現象如何實現呢? 可以這樣實現:將類中的一些屬性和方法用private關鍵字修飾,將他們“私有化(即不對 外直接公開)”,使外部其他類不能通過創建該類對象或通過類名直接訪問這些屬性和方法; 只對外提供公有的方法,外部其他類必須通過該類對外提供的公有方法來訪問該類的相應成員;例如: class Person{ private String name;//將name屬性私有化(封裝)[相當于了上鎖]使外部其他類不能直 接訪問到 public SetName(String name){//對外提供公有方法(相當于房門鑰匙)供外部其他類訪問 到本類屬性 this.name=name; } } 2.繼承: 從字面來說繼承就是子父類關系的簡稱,就是兒子(女兒也行,好吧)會繼承老爸的一些屬性和行為 在java中如何描述繼承關系呢? 注意:第一得知道在java中繼承是類與類之間或者是接口與接口之間才有繼承關系; 通過extends關鍵字來描述繼承關系 例如:老爸這個類 class Dad{ String sex=man; void smoke(){ System.out.println(“老子會抽煙!”); } } 那么我們怎么來讓兒子這個類繼承老爸這個類呢? class Son extends Dad{//通過extends關鍵字兒子這個類就繼承老爸這個類了 String name;//定義自己的屬性 String sex=man;//繼承過來的屬性,無須再定義,這里寫出來是為了好理解 void smoke(){//繼承過來的方法,無須再定義,這里寫出來是為了好理解 System.out.println(“老子會抽煙!”); } void playBall(){//定義自己的方法 System.out.println(“兒子即會打球又會抽煙!”); } void somke(){//重寫的方法 System.out.println(“我不抽20塊以下的煙”); } void smoke(int n){//重載的方法 System.out.println(“我抽了+n+”年的煙了“); } } 那么具有繼承關系的兩個類有什么特點呢? 1)子類會將父類的屬性和方法繼承過來,當然子類也可以自己定義的屬性和方法 2)當子類自己定義的方法和父類繼承過來的方法相同時會發生“重寫“現象! 3)父類用private關鍵字私有的方法是不能被繼承的! 4)子類可以使用super訪問父類的屬性和方法 5)子類通過重寫父類方法,修改父類的功能 6)子類構造器一定調用父類的無參構造器 7)構造器不能繼承 3.多態: 字面意思就是多種形態,也就是說一種事物同時局部多種形態.注意:要出現多態情況,那么類和類之間一定得是繼承關系,或者類和接口是實現關系 我覺得:在java中多態是相對于一個對象而言的,就是父類型引用變量引用子類對象,并 且父類型引用變量可以接受不同子類的對象 例如:拿上面的舉例 Dad uncle=new Son();父類引用變量uncle即具備Son類的成員又具備父類的成員;這也稱 為“向上造型”; 多態時的特點 1)多態時訪問成員變量,如uncle.name; 編譯時看等號左邊,父類有該成員變量則編譯通過,否則編譯出錯! 運行時也看等號左邊,有則運行結果 2)多態時訪問方法,如uncle.smoke() 編譯時看等號左邊,父類有該成員方法則編譯通過,否則編譯出錯! 運行時看等號右邊,父類有該方法,子類沒有該方法執行父類方法;父類有該方法,子類也 有該方法執行子類方法 3)多態時訪問靜態方法 編譯運行都看等號左邊 ******************************************************************************* ******************************************************************************* ******************************************************************************* ********************* 4.抽象(有爭議): 什么是抽象? 抽象就是不具體。 一般我們把不能具體描述的東西約定俗成為“抽象”的東西。例如:我們說一個人長得很 “抽象”,n你想你能具體形容描述出來么? 在JAVA中如何描述抽象這個概念呢? 我覺得在java中抽象類是由抽象方法而衍生出來的,為什么呢? 因為Java規定一個類中定義了抽象方法那這個類就跟著必須定義為抽象類,而不是因 為先定義抽象類再跟著規定抽象類中的方法必須是抽象的,可能最后理解的結果是一樣的但 性質是不一樣的(個人理解)簡單說:就是有抽象方法的類一定是抽象類,但是抽象類中不 一定都是抽象方法,也可以有具體方法。 首先就是當我要在一個類定義一個方法時,暫時我不知道該方法具體功能是什么;等我想好 了我在用他實現一個功能時我再具體描述他功能,這樣我們就可以將這個方法用abstract關 鍵字修飾定義為抽象方法 (還有一點也就是什么時候定義抽象類的?也可以說抽象類是向上抽取而來的,就是幾個類 據有共同的屬性和方法,不想每個類都定義一次,那么定義一個公有類(即抽象類)其他類 只要繼承抽象類再重寫方法就行!) 例如:我有一百塊錢,現在我不知道怎么用,等我想好了在具體怎么用! abstract class Money{//因為有了抽象方法所以必須定義為抽象類 public abstract void buySomthing();//現在不知道怎么用,那就把它的功能代碼體去掉 } //現在我餓了,想買東西吃了,我就知道怎么用了 class Hungry extends Money{ void buySomething(){ System.out.println(”我餓了,現在我要買東西吃!“) } } 抽象類的特點 1)抽象類不能實例化 2)抽象類可以繼承抽象類 3)繼承抽象類必須得重寫抽象方法 5.抽象類,接口,普通類 的不同點和相同點? 1)不同點: 普通類接口抽象類 可以直接實例化對象不可以直接實例化對象不可以直接實例化對象 可以定義任何成員只能定義抽象成員方法和常量成員 方法必須定義為抽象其他和普通類相同 可以被繼承類可以實現接口,且可以實現多個接口可以被繼承 接口可以繼承多個接口抽象類有構造方 法,接口中不能有 抽象類有普通成員變 量,接口中沒有 抽象類可以有非抽象方 法,接口中不能有 抽象類可以用public、protected修飾,接口中只能public(默認public) 抽象類包含靜態方法,接 口中沒有 接口中的變量只能是 public static final,抽象類中可以是任意類型修飾 2)相同點:都可以用于描述(封裝)事物的,內部類分為哪幾種?分別如何創建對象? 分為 局部內部類,匿名內部類...3種 1)外部類名.內部類名 對象名=new 外部類名().new 內部類名() 2)外部類名.內部類名 對象名=外部類名.new 內部類名() 3)....不記得了第3種 匿名內部類 二、集合集合的定義? 集合:用來保存一組數據的數據結構 集合的父接口,實現接口,實現類,實現類的常用方法是什么?(建議以樹狀圖畫出來,便 于加深印象)。 Collectionlistset ArraylistLinkedListHashSet TreeSet 1.List集合List集合的特征是元素可重復且有序 ;我們可以把他看成是一個動態數組,一般通過下標 訪問 ArrayList和LinkedList最常用的兩個子類實現 1)list可以使用for循環遍歷 for(int i=;i list.get(i); } 2)list的淺層復制 調用ArraryList.clone()方法 注意:不能使用list.clone(),clone()方法是Object類的方法,list是接口是不能繼承Object類的2.Set集合: 不重復且無序集 遍歷set只能迭代器,用迭代器遍歷集合遵循的操作原則:先問后取。問一次取一次。Iterator while(it.hashnext()){ E e=it.next(); } 3)map表 Map存儲數據使用key-value(鍵-值)對的形式存儲數據的。 對于Map而言,要求key值是唯一的。value值可以重復 獲取數據時,使用key可以獲取其對應的value 遍歷map有3種方法 1)遍歷key Set for(String key:keySet){ System.out.println(”key:“ + key); //可以根據每一個key獲取其對應的value值 int value = map.get(key); 2)遍歷value Collection Iterator while(it.hasNext()){ int value = it.next();//不能采用 map.next() System.out.println(”value:“ + value); 注意:通過迭代器在遍歷集合的過程中,不能通過集合(即不能采用 map.next())去改變集合元素數量 3)遍歷鍵值對 Set for(Entry //獲取一組鍵值對的鍵和值 String key = entry.getKey(); int value = entry.getValue(); System.out.println(key + ”=" + value); Collection接口方法的定義 這里我主要列舉 Iterator iterator()方法的使用 Collection提供的方法 Iterator iterator()方法來獲取迭代器 Iterator是一個接口,定義了遍歷集合應有的方法。 使用迭代器遍歷集合遵循的操作原則:先問后取。問一次取一次。問:boolean hashNext() 取:Object next() 迭代器可以將取出的數據刪除掉 刪:remove()將當前獲取的元素刪除掉。 注意:1)刪除的是next()取出的元素。且只能刪除一次! 2)調用1次next()后只能調用一次remove()! 達內學習心得:精心總結的面向對象 參賽學員:方錢有 獲獎獎項:二等獎 什么面向對象: 個人分析覺得:在程序設計里,面向對象是一種相對說法,相對于面向過程而言的; 面向“對象“:即重點在于“對象”;而面向過程:則重點在于“過程”,簡單說:就是我我們看待事物在眼光上注重點不一樣;比如說:我們評判一個女孩漂亮與否,有的人看重外表,有的人則看重“心靈”,只是側重點不一樣。舉個例子:把大象裝進冰箱! 面向過程 面向對象 (注重一系列動作即過程) (注重動作所操作的承受者[“對象”]) “打開”冰箱 “冰箱”打開 “裝入”大象 “大象”裝入 “關閉”冰箱 “冰箱”關閉 類:通俗的說類就是“一類事物的簡稱”,并且這些事物至少具有一點“共同的”特征.比如說:動物就是一個類 對象:就是某一類中一個具體的(就是可以具體描述出來的)東西,比如:動物(類)里的“狗”就是一個對象。(個人覺得對象相對于類而言的,因為狗又可以分好多種,‘狗’相對于‘哈士奇’是一個類,‘哈士奇’是‘狗’類的一個具體對象) 在生活中就拿描述汽車來說,我們都知道汽車都有4個輪子; 都有跑的功能 可以如下描述: 類 汽車 屬性: 4個輪 功能: 跑 那么怎么在Java中描述汽車這類呢? class car{ int wheel=4;//屬性: 4個輪 void run(){//方法(功能): 跑 System.out.println(“是汽車都會跑”); } } 那么可見“出租車”應當是“汽車”這類的一個具體化(實實在在的例子即“實例”)對象,那自然出租車也就具備了汽車這類所具備的“共有”屬性功能! 如何創建一個出租車對象呢?java中通過new關鍵字來創建一個類的實例即對象,也叫類的實例化,就是把類具體化成一個實例嘛!格式:類名 對象名 = mew 類名 () Car texi = new Car();創建了“出租車”對象(實例)之后那么它也就有了如下“自己”的屬性和功能。 int wheel=4;//屬性: 4個輪 void run(){//功能: 跑 System.out.println(“我是出租車我也會跑”); } 我們如何來訪問對象中的它自己的屬性和方法呢? 格式:對象.屬性; 對象.方法名(); 這一點也驗證了面向對象編程的側重點在于“對象”上; texi.wheel; texi.run()********************************************************************************************************************************************************************************************************************************************* 1.封裝: 從字面可以解讀為將東西封起來再裝好。要想拿到里面的東西就得有相應的方法打開,才能拿到。 舉例來說:一個房間的門如果沒有上鎖,那么大家都可以進去拿東西,但現在我們不想讓誰都進來拿東西,我們可以將房門上鎖,只對外提供一把鑰匙,只有有鑰匙的人才能進來,這就是“封裝”現象! 在java程序中,“封裝”現象如何實現呢? 可以這樣實現:將類中的一些屬性和方法用private關鍵字修飾,將他們“私有化(即不對外直接公開)”,使外部其他類不能通過創建該類對象或通過類名直接訪問這些屬性和方法;只對外提供公有的方法,外部其他類必須通過該類對外提供的公有方法來訪問該類的相應成員;例如: class Person{ private String name;//將name屬性私有化(封裝)[相當于了上鎖]使外部其他類不能直接訪問到 public SetName(String name){//對外提供公有方法(相當于房門鑰匙)供外部其他類訪問到本類屬性 this.name=name; } } 2.繼承: 從字面來說繼承就是子父類關系的簡稱,就是兒子(女兒也行,好吧)會繼承老爸的一些屬性和行為 在java中如何描述繼承關系呢? 注意: 第一得知道在java中繼承是類與類之間或者是接口與接口之間才有繼承關系;通過extends關鍵字來描述繼承關系 例如:老爸這個類 class Dad{ String sex=man; void smoke(){ System.out.println(“老子會抽煙!”); } } 那么我們怎么來讓兒子這個類繼承老爸這個類呢? class Son extends Dad{//通過extends關鍵字兒子這個類就繼承老爸這個類了 String name;//定義自己的屬性 String sex=man;//繼承過來的屬性,無須再定義,這里寫出來是為了好理解 void smoke(){//繼承過來的方法,無須再定義,這里寫出來是為了好理解 System.out.println(“老子會抽煙!”); } void playBall(){//定義自己的方法 System.out.println(“兒子即會打球又會抽煙!”); } void somke(){//重寫的方法 System.out.println(“我不抽20塊以下的煙”); } void smoke(int n){//重載的方法 System.out.println(“我抽了+n+”年的煙了“); } } 那么具有繼承關系的兩個類有什么特點呢? 1)子類會將父類的屬性和方法繼承過來,當然子類也可以自己定義的屬性和方法 2)當子類自己定義的方法和父類繼承過來的方法相同時會發生“重寫“現象!3)父類用private關鍵字私有的方法是不能被繼承的!4)子類可以使用super訪問父類的屬性和方法 5)子類通過重寫父類方法,修改父類的功能 6)子類構造器一定調用父類的無參構造器 7)構造器不能繼承 3.多態: 字面意思就是多種形態,也就是說一種事物同時局部多種形態.注意:要出現多態情況,那么類和類之間一定得是繼承關系,或者類和接口是實現關系 我覺得:在java中多態是相對于一個對象而言的,就是父類型引用變量引用子類對象,并且父類型引用變量可以接受不同子類的對象 例如:拿上面的舉例 Dad uncle=new Son();父類引用變量uncle即具備Son類的成員又具備父類的成員;這也稱為“向上造型”; 多態時的特點 1)多態時訪問成員變量,如uncle.name;編譯時看等號左邊,父類有該成員變量則編譯通過,否則編譯出錯!運行時也看等號左邊,有則運行結果 2)多態時訪問方法,如uncle.smoke()編譯時看等號左邊,父類有該成員方法則編譯通過,否則編譯出錯!運行時看等號右邊,父類有該方法,子類沒有該方法執行父類方法;父類有該方法,子類也有該方法執行子類方法 3)多態時訪問靜態方法 編譯運行都看等號左邊 ****************************************************************************************************************************************************************************************************************************************************************** 4.抽象(有爭議): 什么是抽象? 抽象就是不具體。 一般我們把不能具體描述的東西約定俗成為“抽象”的東西。例如:我們說一個人長得很“抽象”,n你想你能具體形容描述出來么? 在JAVA中如何描述抽象這個概念呢? 我覺得在java中抽象類是由抽象方法而衍生出來的,為什么呢? 因為Java規定一個類中定義了抽象方法那這個類就跟著必須定義為抽象類,而不是因為先定義抽象類再跟著規定抽象類中的方法必須是抽象的,可能最后理解的結果是一樣的但性質是不一樣的(個人理解)簡單說:就是有抽象方法的類一定是抽象類,但是抽象類中不一定都是抽象方法,也可以有具體方法。首先就是當我要在一個類定義一個方法時,暫時我不知道該方法具體功能是什么;等我想好了我在用他實現一個功能時我再具體描述他功能,這樣我們就可以將這個方法用abstract關鍵字修飾定義為抽象方法 (還有一點也就是什么時候定義抽象類的?也可以說抽象類是向上抽取而來的,就是幾個類據有共同的屬性和方法,不想每個類都定義一次,那么定義一個公有類(即抽象類)其他類只要繼承抽象類再重寫方法就行!) 例如:我有一百塊錢,現在我不知道怎么用,等我想好了在具體怎么用!abstract class Money{//因為有了抽象方法所以必須定義為抽象類 public abstract void buySomthing();//現在不知道怎么用,那就把它的功能代碼體去掉 } //現在我餓了,想買東西吃了,我就知道怎么用了 class Hungry extends Money{ void buySomething(){ System.out.println(”我餓了,現在我要買東西吃!“) } } 抽象類的特點 1)抽象類不能實例化 2)抽象類可以繼承抽象類 3)繼承抽象類必須得重寫抽象方法 5.抽象類,接口,普通類 的不同點和相同點? 1)不同點: 普通類 接口 抽象類 可以直接實例化對象 不可以直接實例化對象 不可以直接實例化對象 可以定義任何成員 只能定義抽象成員方法和常量 成員方法必須定義為抽象其他和普通類相同 可以被繼承 類可以實現接口,且可以實現多個接口 可以被繼承 接口可以繼承多個接口 抽象類有構造方法,接口中不能有 抽象類有普通成員變量,接口中沒有 抽象類可以有非抽象方法,接口中不能有 抽象類可以用public、protected修飾,接口中只能public(默認public) 抽象類包含靜態方法,接口中沒有 接口中的變量只能是public static final,抽象類中可以是任意類型修飾 2)相同點:都可以用于描述(封裝)事物的,內部類分為哪幾種?分別如何創建對象? 分為 局部內部類,匿名內部類...3種 1)外部類名.內部類名 對象名=new 外部類名().new 內部類名()2)外部類名.內部類名 對象名=外部類名.new 內部類名()3)....不記得了第3種 匿名內部類 二、集合集合的定義? 集合:用來保存一組數據的數據結構 集合的父接口,實現接口,實現類,實現類的常用方法是什么?(建議以樹狀圖畫出來,便于加深印象)。 Collection list set Arraylist LinkedList HashSet TreeSet 1.List集合 List集合的特征是元素可重復且有序 ;我們可以把他看成是一個動態數組,一般通過下標訪問 ArrayList和LinkedList最常用的兩個子類實現 1)list可以使用for循環遍歷 for(int i=;i list.get(i);} 2)list的淺層復制 調用ArraryList.clone()方法 注意:不能使用list.clone(),clone()方法是Object類的方法,list是接口是不能繼承Object類的 2.Set集合: 不重復且無序集 遍歷set只能迭代器,用迭代器遍歷集合遵循的操作原則:先問后取。問一次取一次。Iterator E e=it.next();} 3)map表 Map存儲數據使用key-value(鍵-值)對的形式存儲數據的。 對于Map而言,要求key值是唯一的。value值可以重復 獲取數據時,使用key可以獲取其對應的value 遍歷map有3種方法 1)遍歷key Set for(String key:keySet){ System.out.println(”key:“ + key); //可以根據每一個key獲取其對應的value值 int value = map.get(key);2)遍歷value Collection Iterator while(it.hasNext()){ int value = it.next();//不能采用 map.next() System.out.println(”value:“ + value);注意:通過迭代器在遍歷集合的過程中,不能通過集合(即不能采用 map.next())去改變集合元素數量 3)遍歷鍵值對 Set for(Entry //獲取一組鍵值對的鍵和值 String key = entry.getKey(); int value = entry.getValue(); System.out.println(key + ”=" + value); Collection接口方法的定義 這里我主要列舉 Iterator iterator()方法的使用 Collection提供的方法 Iterator iterator()方法來獲取迭代器 Iterator是一個接口,定義了遍歷集合應有的方法。 使用迭代器遍歷集合遵循的操作原則:先問后取。問一次取一次。 問:boolean hashNext() 取:Object next() 迭代器可以將取出的數據刪除掉 刪:remove()將當前獲取的元素刪除掉。 注意:1)刪除的是next()取出的元素。且只能刪除一次! 2)調用1次next()后只能調用一次remove()!第三篇:達內培訓總結
第四篇:達內學習心得:精心總結的面向對象
第五篇:達內學習心得:精心總結的面向對象