面向對象
類的定義和對象的創建
//定義了一個類Liwl,保存該源碼為文件Liwl.java。即類名與文件名一致
public class Liwl{
public static void main(String[] args){
System.out.println("hello,java");
}
}
類的屬性和方法
public class Liwl {
public String name = "liwanliang";
public Integer age = 30;
public static void main(String[] args){
Liwl liwl01 = new Liwl();
//liwl01.name = "hello,world"
System.out.println(liwl01.age)
}
}
//通過liwl01.name = "hello,world"的語句,無法保證類的安全性,不太滿足類的封裝
類的封裝
類的屬性設置為私有
public class Liwl {
private String name;
private Integer age;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public Integer getAge(){
return age;
}
public void setAge(Integer age){
this.age = age;
}
}
/*
說明:this表示對象自己。在類定義中,類的方法訪問類的屬性和訪問,通過this訪問。
*/
構造方法
構造方法的定義和重載
public class Liwl {
private String name;
private Integer age;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public void setAge(Integer age){
this.age = age;
}
public Integer getAge(){
return age;
}
public Liwl(){
System.out.println("無參數構造函數");
}
public Liwl(String name,Integer age){
System.out.println("有參數的構造函數");
this.name = name;
this.age = age;
}
public static void main(String[] args) {
Liwl liwl01 = new Liwl("liwanliang",30);
}
}
this關鍵字
static關鍵字
靜態變量以及靜態方法,一般通過類調用,而非對象
靜態變量
public class Liwl {
public static void main(String[] args) {
LiwanLiang liwl001 = new LiwanLiang("liwanliang",30);
liwl001.WORK_PLACE = "哈哈";//靜態變量是對象共享區域,通過對象修改靜態變量
System.out.println(LiwanLiang.WORK_PLACE);
}
}
class LiwanLiang extends Liwl {
public static String WORK_PLACE;
private String name;
private Integer age;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public void setAge(Integer age){
this.age = age;
}
public Integer getAge(){
return age;
}
public LiwanLiang(){
System.out.println("無參數構造函數");
}
public LiwanLiang(String name,Integer age){
System.out.println("有參數的構造函數");
this.name = name;
this.age = age;
}
public void run(){
}
}
靜態方法
public class Liwl {
public static void main(String[] args) {
LiwanLiang liwl001 = new LiwanLiang("liwanliang",30);
liwl001.WORK_PLACE = "哈哈";
System.out.println(LiwanLiang.WORK_PLACE);
LiwanLiang.run();
liwl001.run();
}
}
class LiwanLiang extends Liwl {
public static String WORK_PLACE;
private String name;
private Integer age;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public void setAge(Integer age){
this.age = age;
}
public Integer getAge(){
return age;
}
public LiwanLiang(){
System.out.println("無參數構造函數");
}
public LiwanLiang(String name,Integer age){
System.out.println("有參數的構造函數");
this.name = name;
this.age = age;
}
public static void run(){
System.out.println("我是靜態方法");
}
}
靜態代碼塊
當類被加載時,靜態代碼會被執行, 由於類只會被加載一次,因此靜態代碼塊只會執行一次
public class Liwl {
public static void main(String[] args) {
LiwanLiang liwl001 = new LiwanLiang("liwanliang",30);
liwl001.WORK_PLACE = "哈哈";
System.out.println(LiwanLiang.WORK_PLACE);
LiwanLiang.run();
liwl001.run();
}
}
class LiwanLiang extends Liwl {
public static String WORK_PLACE;
private String name;
private Integer age;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public void setAge(Integer age){
this.age = age;
}
public Integer getAge(){
return age;
}
public LiwanLiang(){
System.out.println("無參數構造函數");
}
public LiwanLiang(String name,Integer age){
System.out.println("有參數的構造函數");
this.name = name;
this.age = age;
}
public static void run(){
System.out.println("我是靜態方法");
}
static {
System.out.println("我是靜態代碼塊");
}
}
類的繼承
重寫父類方法
public class Liwl {
public void sayHello() //重寫了父類的sayHello方法
{
System.out.println("Hi");
}
public static void main(String[] args) {
Liwl liwl = new Liwl();
liwl.sayHello();
}
}
class LiwanLiang extends Liwl {
public static String WORK_PLACE;
private String name;
private Integer age;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public void setAge(Integer age){
this.age = age;
}
public Integer getAge(){
return age;
}
public LiwanLiang(){
System.out.println("無參數構造函數");
}
public LiwanLiang(String name,Integer age){
System.out.println("有參數的構造函數");
this.name = name;
this.age = age;
}
public void sayHello(){
System.out.println("hello");
}
public static void run(){
System.out.println("我是靜態方法");
}
static {
System.out.println("我是靜態代碼塊");
}
}
super關鍵字使用父類方法
public class Liwl extends LiwanLiang{
public Liwl(){
super("liwanliang007",30);
}
public void sayHello(){
super.sayHello(); //通過super關鍵字,直接使用父類的方法
}
public static void main(String[] args) {
Liwl liwl = new Liwl();
System.out.println(liwl.getName());
liwl.sayHello();
}
}
class LiwanLiang {
public static String WORK_PLACE;
private String name;
private Integer age;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public void setAge(Integer age){
this.age = age;
}
public Integer getAge(){
return age;
}
public LiwanLiang(){
System.out.println("無參數構造函數");
}
public LiwanLiang(String name,Integer age){
System.out.println("有參數的構造函數");
this.name = name;
this.age = age;
}
public void sayHello(){
System.out.println("hello,I am father class");
}
public static void run(){
System.out.println("我是靜態方法");
}
static {
System.out.println("我是靜態代碼塊");
}
}
final關鍵字拒絕重寫父類方法
類的多態
java多態是通過父類類型的變量,引導子類類型的對象,根據子類對象特征的不同,得到不同的結果。
interface LiwanLiangWork{
String ADDRESS = "無錫";
String NEWADDRESS = "江蘇";
void work();
}
class LiwanLiangWorkImpl01 implements LiwanLiangWork {
public void work() {
System.out.println("我的工作地點"+ADDRESS);
}
}
class LiwanLiangWorkImpl02 implements LiwanLiangWork {
public void work(){
System.out.println("我的新工作地點"+NEWADDRESS);
}
}
public class Liwl {
public static void main(String[] args) {
LiwanLiangWork liwl01 = new LiwanLiangWorkImpl01();
LiwanLiangWork liwl02 = new LiwanLiangWorkImpl02();
whereWork(liwl01);
whereWork(liwl02);
}
public static void whereWork(LiwanLiangWork w){
w.work();
}
}
多態中的類型轉換
多態中,將子類的對象當作父類類型使用,此種情況叫做向上轉型,向上轉型不需要顯示轉換,但是此時不能通過父類變量調用子類中的特有方法。
以下代碼【錯誤】:
public class Liwl {
public static void main(String[] args) {
LiwanLiangWork liwl01 = new LiwanLiangWorkImpl01();
LiwanLiangWork liwl02 = new LiwanLiangWorkImpl02();
whereWork(liwl01);
whereWork(liwl02);
}
public static void whereWork(LiwanLiangWork w){
LiwanLiangImpl01 l = (LiwanLiangImpl01) w; //這里對象的類型轉換,使得該方法在傳入LiwanLiangWork子類型對象時,調用另外子類的特定方法而報錯
l.work();
}
}
匿名內部類
public class Liwl {
public static void main(String[] args) {
whereWork(new LiwanLiangWork(){
public void work(){
System.out.println("匿名工作地點");
}
});
}
public static void whereWork(LiwanLiangWork w){
w.work();
}
}
//以new Object(){}方式作為方法的參數,這就是匿名內部類
抽象類和接口
/*
抽象類:LiwanLiangHome
*/
abstract class LiwanLiangHome{
abstract void call();
public void sayBye(){
System.out.println("bye");
}
}
public class Liwl extends LiwanLiangHome {
public void call(){
System.out.println("liwanliang在叫");
}
public static void main(String[] args) {
Liwl liwl = new Liwl();
liwl.call();
liwl.sayBye();
}
}
interface LiwanLiangWork{
String ADDRESS = "無錫";
void work();
}
class LiwanLiangWorkImpl implements LiwanLiangWork {
public void work() {
System.out.println("我的工作地點"+ADDRESS);
}
}
public class Liwl extends LiwanLiangWorkImpl {
public static void main(String[] args) {
Liwl liwl = new Liwl();
liwl.work();
}
}
異常及異常類
在程序運行過程中,內存,磁盤,網絡等發生異常導致的程序異常,比如內存溢出,內存不足,磁盤空間不足,讀寫失敗,網絡中斷等
java提供的異常機制,來處理發生異常時,使程序針對性處理
錯誤表示系統內部錯誤或者資源耗盡等僅靠程序本身不能恢復執行的問題
異常表示程序本身能夠正常處理的問題
try...catch...finally
throws
集合類
保存確定個數的元素使用數組,保存不確定個數的元素使用集合類(容器類)
- 集合類
- 單列集合 Collection
- 元素有序可重復 List
- ArrayList
- LinkedList
- Vector
- 元素無序不重復 Set
- HashSet
- LinkedHashSet
- TreeSet
- HashSet
- 元素有序可重復 List
- 雙列集合 Map
- HashMap
- LinkedHashMap
- TreeMap
- HashTable
- Properties
- HashMap
- 單列集合 Collection
集合與泛型
對象從集合中取出時,編譯類型變成Object類型,一般需要顯示的強制類型轉換
泛型限制傳入范圍,取出的對象也不用強制類型轉換
Collection-List-ArrayList
public class Liwl {
public static void main(String[] args) {
ArrayList<String> liwl = new ArrayList<>();
liwl.add("liwl01");
liwl.add("liwl02");
System.out.println(liwl);
System.out.println(liwl.size());
System.out.println("第一個元素:"+liwl.get(0));
System.out.println("第二個元素:"+liwl.get(1));
}
}
Iterator接口遍歷元素
import java.util.ArrayList;
import java.util.Iterator;
public class Liwl {
public static void main(String[] args) {
ArrayList<String> liwl = new ArrayList<>();//泛型的使用
liwl.add("liwl01");
liwl.add("liwl02");
System.out.println(liwl);
System.out.println(liwl.size());
System.out.println("第一個元素:"+liwl.get(0));
System.out.println("第二個元素:"+liwl.get(1));
Iterator<String> it = liwl.iterator();
while ( it.hasNext()) {
Object obj = it.next();//返回的是Object類型的對象
System.out.println(obj);
}
}
}
for...each循環
import java.util.ArrayList;
public class Liwl {
public static void main(String[] args) {
ArrayList<String> liwl = new ArrayList<>();
liwl.add("liwl01");
liwl.add("liwl02");
for ( Object obj: liwl) {
System.out.println(obj);
}
}
}
Collectioin-Set-HashSet
import java.util.HashSet;
import java.util.Iterator;
public class Liwl {
public static void main(String[] args) {
HashSet<String> liwl = new HashSet<>();
liwl.add("liwanliang");
liwl.add("liwl");
Iterator it = liwl.iterator();
while ( it.hasNext()) {
Object obj = it.next();
System.out.println(obj);
}
/*
for (Object obj : liwl) {
System.out.println(obj);
}
*/
}
}
Map-HashMap
HashMap的存取:
調用HashMap集合類的方法keySet(),獲取到Map中所有鍵的Set集合,然后通過Set集合類的Iterator迭代Set集合的每個元素(鍵),最后調用HashMap的get()方法,獲取值
import java.util.*;
public class Liwl {
public static void main(String[] args) {
HashMap<String,String> liwl = new HashMap<>();
liwl.put("001","liwanliang001");
liwl.put("002","liwanliang002");
Set keySet = liwl.keySet();
Iterator it = keySet.iterator();
while (it.hasNext()) {
Object key = it.next();
Object value = liwl.get(key);
System.out.println(key+":"+value);
}
}
}
另外一種方式:
獲取集合中的所有映射關系,從映射關系取出鍵值對
import java.util.*;
public class Liwl {
public static void main(String[] args) {
HashMap<String,String> liwl = new HashMap<>();
liwl.put("001","liwanliang001");
liwl.put("002","liwanliang002");
Set entrySet = liwl.entrySet();
Iterator it = entrySet.iterator();
while ( it.hasNext() ) {
Map.Entry entry = (Map.Entry)it.next();
Object key = entry.getKey();
Object value = entry.getValue();
System.out.println(key+":"+value);
}
}
}
Map-Properties
輸入輸出
- IO輸入輸出
- 字節流
- 字節輸入流 java.io.InputStream
- ByteArrayInputStream
- FileInputStream
- BufferedInpubStream
- DataInputStream
- FilterInputStream
- ObjectInputStream
- 字節輸出流java.io.OutputStream
- ByteArrayOutputStream
- FileOutputStream
- FilterOutputStream
- BufferedOutputStream
- PrintStream
- DataInputStream
- ObjectInputStream
- 字節輸入流 java.io.InputStream
- 字符流
- 字符輸入流java.io.Reader
- 字符輸出流java.io.Writer
- 字節流
字節流
文件的輸出
對文件對象的讀取
import java.io.*;
public class Liwl {
public static void main(String[] args) throws Exception {
FileInputStream input = new FileInputStream("liwl.txt");
int i = 0;
while (true){
i = input.read();
if ( i == -1 ){
break;
}
System.out.println(i);
}
input.close();
}
}
文件的輸入
對文件對象的寫入
import java.io.*;
public class Liwl {
public static void main(String[] args) throws Exception {
FileOutputStream output = null;
try {
output = new FileOutputStream("/root/liwl.txt");
String web = "nsccwx.cn";
byte[] arr = web.getBytes();
for ( int i = 0; i < arr.length; i++ ){
output.write(arr[i]);
}
} catch ( IOException e) {
//e.printStackTrace();
System.out.println("打開文件錯誤");
} finally {
if ( output != null ){
output.close();
}
}
}
}
文件的復制
import java.io.*;
public class Liwl {
public static void main(String[] args) throws Exception {
FileInputStream input = new FileInputStream("liwl.txt");
FileOutputStream output = new FileOutputStream("liwl_new.txt");
int i = 0;
long startTime = System.currentTimeMillis();
while ( ( i=input.read() ) != -1) {
output.write(i);
}
long endTime = System.currentTimeMillis();
System.out.println("復制文件時間:"+(endTime-startTime)+"毫秒");
input.close();
output.close();
}
}
字節流緩沖區
import java.io.*;
public class Liwl {
public static void main(String[] args) throws Exception {
FileInputStream input = new FileInputStream("dark.jpg");
FileOutputStream output = new FileOutputStream("dark_new.jpg");
byte[] buffer = new byte[1024];
int length = 0;
long startTime = System.currentTimeMillis();
while ( ( length = input.read(buffer) ) != -1) { //read方法可以讀取字節數組,緩存區
output.write(buffer,0,length);
}
long endTime = System.currentTimeMillis();
System.out.println("復制文件時間:"+(endTime-startTime)+"毫秒");
input.close();
output.close();
}
}
字節緩沖流
public class Liwl {
public static void main(String[] args) throws Exception {
BufferedInputStream bufferInput = new BufferedInputStream(new FileInputStream("dark.jpg"));
BufferedOutputStream bufferOutput = new BufferedOutputStream(new FileOutputStream("dark_new.jpg"));
long startTime = System.currentTimeMillis();
int length;
while ( (length=bufferInput.read()) != -1 ){
bufferOutput.write(length );
}
long endTime = System.currentTimeMillis();
System.out.println("復制時間:"+(endTime-startTime)+"毫秒");
bufferInput.close();
bufferOutput.close();
}
}
字符流
字符流的讀操作
import java.io.*;
public class Liwl {
public static void main(String[] args) throws Exception {
FileReader fileReader = new FileReader("liwl.txt");
int i;
while ( (i = fileReader.read()) !=-1 ) {
System.out.println((char) i);
}
fileReader.close();
}
}
字符流的寫操作
import java.io.*;
public class Liwl {
public static void main(String[] args) throws Exception {
FileWriter w = new FileWriter("liwl.txt",true);
String name = "liwanliang";
w.write(name);
w.close();
}
}
字符流的緩沖流
import java.io.*;
public class Liwl {
public static void main(String[] args) throws Exception {
BufferedReader bfr = new BufferedReader(new FileReader("liwl.txt"));
BufferedWriter brw = new BufferedWriter(new FileWriter("liwl001.txt"));
String s = null;
while ( (s=bfr.readLine())!=null){
brw.write(s);
brw.newLine();
}
bfr.close();
brw.close();
}
}
轉換流
字節流轉換為字符流,或者字符流轉為字節流
File類
多線程
線程的創建
通過繼承Thread類
public class Liwl extends Thread{
public void run(){
for (int i=0; i<5; i++){
System.out.println("Liwl類的run()方法執行了");
}
}
public static void main(String[] args) {
Liwl liwl01 = new Liwl();
liwl01.start();
for(int i=0; i<5; i++){
System.out.println("主方法的main()執行了");
}
}
}
實現Runnable接口
public class Liwl implements Runnable{
public void run(){
for (int i=0; i<5; i++){
System.out.println("Liwl類的run()方法執行了");
}
}
public static void main(String[] args) {
Liwl liwl01 = new Liwl(); //創建實例對象
Thread thr = new Thread(liwl01); //傳入實例對象,創建線程對象
thr.start(); //開啟線程,執行線程對象的run方法
for(int i=0; i<5; i++){
System.out.println("主方法的main()執行了");
}
}
}
Runnable相對於Thread類:
- 適合多個程序代碼相同的線程處理同一資源的情況
- 可以避免由於java的單繼承特性特來的局限
線程的狀態和轉換
線程生命周期
- 開始:線程對象創建完畢
- 結束:run方法正常執行完畢,或者出現未捕獲的異常或者錯誤
線程周期的五種狀態
-
新建狀態
線程對象創建以后,線程處於新建狀態。處於新建狀態的線程僅僅在java虛擬機分配了內存空間,不能運行
-
就緒狀態
線程調用了start方法后,進入就緒狀態。處於就緒狀態的線程位於可運行池中,具備運行的條件,等待系統調度運行
-
運行狀態
就緒狀態獲取CPU的執行權,並開始執行run方法時,線程處於運行狀態。當系統分配的CPU時間到達時,轉為就緒狀態
-
阻塞狀態
被人為掛起執行耗時的輸入輸出操作時,線程讓出CPU,進入阻塞狀態。阻塞原因解除后,進入就緒狀態。
-
死亡狀態
線程調用stop方法或者run方法執行結束后,線程處於死亡狀態。
多線程同步
線程安全
同步代碼塊
同步方法
java注解
注解是代碼的元數據,跟class,interface一樣,也是一種類型。其作用:
- 編譯檢查
注解的定義形式
public @interface AnnotationName{
//基本數據類型
public int xxx() default xxx;
public String yyy() default xxx;
}
元注解概念作用
元注解,是注解類型的注解。如果把注解理解為標簽 ,那元注解就是標簽的標簽,是一種特殊的標簽,來給其他普通標簽解釋說明。
元注解種類:
-
@Retention 保留期
取值:
RetentionPolicy.SOURCE 注解只在源碼階段保留,在編譯器編譯源碼成字節碼之后,該注解被丟棄
RetentionPolicy.CLASS 注解只被保留在字節碼中,不會被加載到JVM中
RetentionPolicy.RUNTIME 注解可以保留在程序運行時,會被加載到JVM中。程序運行時,可以獲取到注解內容。
-
@Target 注解的目標
取值:
ElementType.ANNOTATION_TYPE 給一個注解類型注解
ElementType.CONSTRUCTOT 給構造方法注解
ElementType.FIELD 給屬性注解
ElementType.LOCAL_VARIABLE 給局部變量注解
ElementType.METHOD 給方法注解
ElementType.PACKAGE 給一個包注解
ElementType.PARAMETER 給一個方法內的參數注解
ElementType.TYPE 給一個類型注解,比如類,接口,枚舉
-
@Documented 注解包含到javadoc
-
@Inherited 注解的普通注解能被子類繼承
-
@Repeatable 多重標簽
解釋:被Repeatable標注的普通注解,可用來多次注解同一個目標。如:
@interface LiwanLiangs { Liwanliang[] value(); } @Repeatable(Liwanliangs.class) @interface Liwanliang{ String name(); } @LiwanLiang("liwl01") @Liwanliang("liwl02") public class Others{ }
這段代碼中,自定義注解Liwanliang用來多次注解類Others。而自定義注解Liwanliang是一個被元注解Repeatable注解的普通注解。元注解Repeatable傳入了一個參數類——LiwanLiangs.class,它是一個容器注解。這個LiwanLiangs是一個用來存放其他注解的普通注解,按照注解的定義,LiwanLiangs必須有個一value屬性,這個value屬性是被Repeatable標注過的LiwanLiang注解的數組,即LiwanLiang[]
注解的屬性
注解的屬性,也叫做成員變量(注解也是類型)。
屬性以“無參數方法”的形式類定義,屬性的名字就是方法的名字,屬性的返回值就是方法的返回值。屬性的返回值,只能是8中基本數據類型,類,接口,注解,以及它們的數組。
屬性的賦值:在注解括號內,以value=key的形式,多個屬性用逗號隔開。屬性可以有默認值,在屬性方法括號后,使用default關鍵字指定。有默認值時,注解參數中可以省略書寫。
java內置注解
這些注釋是面向編輯器或者編譯器的
@Deprecated
用來標記過時的元素,如過時的類,方法,變量等
@Override
提示子類重寫父類中被@override修飾的方法
@SuppressWarnings
壓制警告
@SafeVarargs
參數安全類型注解。提示開發者不要用參數做一些不安全的操作,它的存在會組織編譯器產生unchecked這樣的警告。
@FunctionlInterface
函數式接口注解。
注解的提取
注解需要通過java的反射機制來獲取。
基本步驟:
-
首先通過Class對象的isAnnotationPresent()方法判斷它是否應用了某個注解
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass){}
-
然后通過getAnnotation()方法獲取Annotation對象
public < A extends Annotation> A getAnnotation(Class<A> annotationClass) {}
-
然后獲取注解的屬性值(調用屬性方法)
注解應用實例—用來替換配置文件
自定義注解
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface LiwlAnnoDamo {
public String name();
public int age();
}
對一個類使用自定義注解
@LiwlAnnoDamo(age=30,name="liwanliang")
class Liwl {
private String name;
private int age;
public int getLiwlAge(){
return age;
}
public void setLiwlAge(int age){
this.age = age;
}
public String getLiwlName(){
return name;
}
public void setLiwlName(String name){
this.name = name;
}
}
創建注解解析器
class LiwlInfoUtil{
public static Liwl getLiwl(Class<?> clazz) throws Exception{
LiwlAnnoDamo lad = clazz.getAnnotation(LiwlAnnoDamo.class);
Liwl liwl = (Liwl)clazz.getDeclaredConstructor().newInstance();
liwl.setLiwlAge(lad.age());
liwl.setLiwlName(lad.name());
return liwl;
}
}
測試注解
public class LiwanLiangMain {
public static void main(String[] args) throws Exception {
Liwl liwl01 = LiwlInfoUtil.getLiwl(Liwl.class);
System.out.println("名字:"+liwl01.getLiwlName());
System.out.println("年紀:"+liwl01.getLiwlAge());
}
}