筆記參考來源狂神說Java視頻https://www.bilibili.com/video/BV12J41137hu 本篇筆記有點長,可以根據目錄定位,建議配合視頻學習。
預科
什么是計算機
- 名稱:Computer,全稱電子計算機,俗稱電腦。
- 定義:能夠按照程序運行,自動、高速處理海量數據的現代化智能電子設備。
- 組成:由硬件和軟件組成。
- 形式:常見顯示有台式計算機、筆記本計算機、大型計算機等。
- 應用:科學計算、數據處理、自動控制、計算機輔助設計、人工智能、網絡等領域。
硬件及馮諾依曼結構
計算機硬件
組成:CPU,主板,內存,電源,主機箱,硬盤,顯卡,鍵盤、鼠標,顯示器。
馮諾依曼結構
軟件及軟件開發
計算機軟件
Windows常用快捷鍵
Alt+f4關閉窗口 Shift+Delete永久刪除 ctrl+w自動保存
死機:任務管理器結束進程
基本的Dos命令
打開CMD的方式
- 開始+系統+命令提示符
- win鍵+R+輸入cmd (推薦使用)
- 在任意的文件夾下,按住Shift鍵+鼠標右擊,打開命令行窗口
- 在資源管理器地址欄路徑前面加 “cmd ”
- 管理員運行方式:命令提示符右鍵以管理員身份運行(最高權限運行)
常用的Dos命令
# 盤符切換 E:
# 查看當前目錄下所有文件 dir
# 切換目錄 cd /d E:\idea
# 返回上一級目錄 cd ..
# 進入同級目錄下的下一級目錄 cd tmp(該目錄下的文件名)
# 清屏 cls (clear screen)
# 退出終端 exit
# 查看電腦當前IP地址 ipconfig
# 打開計算器 calc
# 打開畫圖 mspaint
# 新建記事本 notepad
# 在當前目錄新建文件夾 md test(文件夾名)
# 新建文件 cd> a.txt(文件名)
# 刪除文件 del a.txt(文件名)
# 刪除目錄 rd test(目錄名)
# ping命令(復制鏈接進入Dos直接單擊鼠標右鍵粘貼)
ping www.baidu.com
計算機語言發展史
- 第一代語言:機器語言
- 第二代語言:匯編語言
- 第三代語言:高級語言
高級語言
C、C++、Java、C#、Python、PHP、JavaScript …
大體上分為:面向過程與面向對象兩大類
- C語言是典型的面向過程的語言,C++,Java是典型的面向對象的語言
Java入門
Java帝國的誕生
Java特性與優勢
- 簡單性
- 面對對象
- 可移植性
- 高性能
- 分布式
- 多態性
- 多線程
- 安全性
- 健壯性
Java三大版本
- Write Once,Run Anywhere
- JavaSE: 標准版 (桌面程序,控制台開發…)
- JavaME: 嵌入式開發 (手機,小家電…),已經涼了
- JavaEE: E企業級開發 (Web端,服務端開發…),JavaSE為基礎
JDK JRE JVM
- JDK:Java Development Kit (Java開發者工具,包括 JRE,JVM)
- JRE:Java Runtime Environment (Java運行時環境)
- JVM:Java Virtual Machine (Java虛擬機,跨平台核心)
安裝開發環境
卸載JDk
- 刪除Java安裝目錄
- 刪除環境變量JAVA_HOME
- 刪除path下關於JAVA的目錄
- Java -version
安裝JDK
- 百度搜索JDK8,找到下載地址
- 同意協議,下載電腦對應的版本,如64位操作系統下載 jdk-8u281-windows-x64.exe
- 雙擊安裝JDK
- 記住安裝路徑
- 配置環境變量
- 我的電腦-》屬性-》系統高級設置-》環境變量
- 系統變量 新建–> JAVA_HOME 輸入對應的jdk安裝路徑
- path變量–>% JAVA_HOME%\bin
- 測試是否成功 cmd–>Java -version
Java基礎
注釋
- 單行注釋 //
- 多行注釋 /* */
- 文檔注釋 /** */
標識符和關鍵字
- Java 所有的組成部分都需要名字。類名、變量名、方法名都被稱為標識符
關鍵字
標識符注意點
- 所有標識符都應該以 字母、$(美元符)、_(下划線) 開頭
- 首字母之后可以是 字母、$、_ 或數字任何字符組合
- 關鍵字不能作為變量名或方法名
- 標識符大小寫敏感
- 可以用中文命名,但不建議使用,即使用拼音命名也Low
數據類型
- 強類型語言
- 要求變量的使用要嚴格符合規定,所有變量都必須先定義后才能使用
- 弱類型語言:JavaScript,Python
Java的數據類型分為兩大類
- 基本類型(primitive type),有8大基本類型,此外都是引用類型
- 引用類型(reference type)
//整數
int num1 = 10; //最常用,只要別超過21億(2^31-1)
byte num2 = 20; //-128~127
short num3 = 30;
long num4 = 30L; //long類型數字后面要價格L(盡量用大寫,小寫l容易與1搞混)
//小數:浮點數
float num5 = 50.1F; //float類型數字后面要加個F
double num6 = 3.141592653589793238;
//布爾值:是非
boolean flag = true
類型轉換
- 由於Java是強類型語言,所以要進行有些運算的時候,需要用到類型轉換。
- 容量高–>低:
運算中,不同類型的數據先轉化位同一類型,再進行運算。
- 強制轉換,(類型)變量名,容量由高到低
- 自動轉換,容量由低到高
//強制轉換 (類型)變量名 高--低
//自動轉換 低--高
int i = 128;
byte b = (byte)i; //強制轉換 內存溢出 -128~127
double d = i; //自動轉換
System.out.println(i); //128
System.out.println(b); //-128
System.out.println(d); //128.0
/*
注意點:
1.不能對布爾值進行轉換
2.不能把對象類型轉換為不相干的類型
3.在把高容器轉換到低容量的時候,強制轉換
4.可能存在內存溢出,或者精度問題
*/
System.out.println((int)23.7); //23丟失精度
char c = 'a';
int n = c+1;
System.out.println(n); //98
System.out.println((char)n); //b
//當操作數比較大時,注意溢出問題
//JDK7新特性,數字之間可以用下划線分割
int money = 10_0000_0000; //10億,下划線不會被打印出來
System.out.println(money); //1000000000
int years = 20;
int total = money*years; //數據大,溢出
System.out.println(total); //-1474836480
long total2 = money*years; //默認是int,轉換前就有溢出問題
System.out.println(total2); //-1474836480
long total3 = money*(long)years; //先把一個數轉Long
System.out.println(total3); //20000000000
變量、常量、作用域
- 變量是什么:就是可以變化的量
- Java是一種強類型語言,每個變量都必須聲明其類型
- Java變量是程序中最基本的存儲單元,要素包括變量名,變量類型和作用域
//數據類型 變量名 = 值;
type varName [=value][{,varName[=value]}];
//可以使用逗號隔開多個類型的變量,但不建議在一行定義多個變量
變量作用域
- 類變量(static)
- 實例變量
- 局部變量
public class Variable{
static int allClicks = 0; //類變量
String str = "hello world"; //實例變量
public void method(){
int i = 0; //局部變量
}
}
常量
- 常量:初始化后不能再改變的值,不會變動的值。
- 可以理解為一種特殊的變量,其值被設定后,在程序運行過程不允許被更改。
//常量一般用大寫字符final 常量名=值; final double PI = 3.14;
//修飾符 不存在先后順序,static可以寫final后面 static final double PI=3.14; //類變量,該類下的全局范圍
變量的命名規范
- 所有變量、方法、類名:見名知意
- 類成員變量:首字母小寫+駝峰原則:lastName
- 局部變量:首字母小寫+駝峰原則
- 常量:大寫字母和下划線:MAX_VALUE
- 類名:首字母大寫+駝峰原則:Man,GoodMan
- 方法名:首字母小寫+駝峰原則:run(),fastRun()
運算符
int a=10;
int b=20;
System.out.println(a/b);
//System.out.println((double)a/b);
//long c=12300000000;
//System.out.println(a+b);
//System.out.println(a+c);
//long 自動轉換式子中容量大的數據類型
//冪運算 2^3 2*2*2=8 double pow = Math.pow(2,3);
// (底數,指數)double型System.out.println(pow);
//8.0
//擴展:筆試題 i=5 s=(i++)+(++i)+(i--)+(--i) s=?
//int i=5; int s=(i++)+(++i)+(i--)+(--i); System.out.println(s); //24
邏輯運算符
- && 邏輯與運算:兩個變量都為真,結果為true
- || 邏輯與運算:兩個變量有一個為真,結果為true
- ! 取反,真變為假,假變為真
//與(and)或(or)非(取反)
boolean a = true;
boolean b = false;
System.out.println(a&&b); //false
System.out.println(a||b); //true
System.out.println(a&&b); //true
int c = 5;
boolean d = (c<5)&&(c++<5); //第一個值為false,后面就不進行判定了
System.out.println(d); //false
System.out.println(c); //5 c++未執行
位運算
/*
A = 0011 1100
B = 0000 1101
A&B 0000 1101 按位與
A|B 0011 1101 按位或
A^B 0011 0001 異或
~B 1111 0010 非
面試題:2*8 怎么算最快? 2<<3
<<左移 *2 效率極高!!
>>右移 /2
*/
System.out.println(2<<3); // 16
三元運算符
int a = 10;
int b = 20;
a += b; //a = a+b;
System.out.println(a);
//字符串連接符 + ,轉化為String類型,然后拼接 注意!
System.out.println(""+a+b); //1020
System.out.println(a+b+""); //30 先進行運算,再轉為String拼接
System.out.println(a+b+"str"); //30str
//x ? y : z //如果x為真,則結果為y,否則為z
//if(x) y; else z;
int score = 80;
String type = score<60?"及格":"不及格";
System.out.println(type); //及格
包機制
- 為了更好地組織類,Java提供了包機制,由於區分類名的命名空間
- 包的語法格式:
package pkg1[.pkg2[.pkg3...]];
- 一般利用公司域名倒置作為包名;com.kuangstudy.www
- 為了能夠使用一個包的成員,需要在Java程序中導入該包
import package1[.package2...].(className|*); //通配符* 導入包下所有的類
- 參考:阿里巴巴Java開發手冊
JavaDoc生成文檔
javadoc命令是用來生成自己API文檔的
參數信息
- @author 作者名
- @version 版本號
- @since 指明最早用的jdk版本
- @param 參數名
- @return 返回值情況
- @throws 異常拋出情況
API文檔:https://docs.oracle.com/javase/8/docs/api/
/**
*@auther kuangshen
*@version 1.0
*@since 1.8
*/
public class Demo05{
String name;
/**
*@auther kuangshen
*@param name
*@return
*@throws Exception
*/
public String test(String name) throws Exception{
return name;
}
}
- 打開某個類所在文件夾下的cmd命令行
- 輸入:javadoc -encoding UTF-8 -charset UTF-8 Doc(類名).java
- 會自動生成該類有關的API文檔,查看文件夾發現多了一些文件
- 打開 index.html(首頁)查看文檔注釋
Java流程控制
用戶交互Scanner
Scanner對象
之前我們學的基本語法並沒有實現程序和人的交互,Java給我們提供了一個工具類,可以獲取用戶的輸入java.util.Scanner是Java5的新特征,我們通過Scanner類來獲取用戶的輸入。
基本語法
Scanner s = new Scanner(System.in);
通過Scanner類的 next()與 nextLine()方法獲取用戶的字符串,讀取前一般用hasNext()與hasNextLine()判斷是否還有輸入的數據。
//創建一個掃描器對象
Scanner scanner = new Scanner(System.in);
System.out.println("使用next方法接收");
//判斷用戶有沒有輸入字符串
if(scanner.hasNext()){ //使用hasNextline()會接收一行"hello world"
//使用next方法接收
String str = scanner.next();
System.out.println("輸入的內容為:"+str);
//input:hello word
//輸出的內容為:hello
}
//凡是屬於IO流的類如果不關閉會一直占用資源
scanner.close();
next():
- 一定要讀取到有效字符后結束輸入
- 對輸入有效字符之前遇到的空白,next()方法會自動將其去掉
- 只有輸入有效字符后才能將后面輸入的空白作為分隔符或者結束符
- next()不能得到帶有空格的字符串
Scanner scanner = new Scanner(System.in);
System.out.println("你輸入的是:");
String str = scanner.nextLine();
System.out.println("輸出:"+str);
scanner.cloase();
nextLine():
- 以enter為結束符,也就是說nextLine()方法返回的是輸入回車之前的所有字符
- 可以獲得空白
Scanner進階
判斷scanner是否輸入的正確
Scanner scanner = new Scanner(System.in);
int i = 0;
System.out.println("請輸入整數");
if(scanner.hasNextInt()){
i = scanner.nextInt();
System.out.println("你輸入的沒錯:"+i);
}else{
System.out.println("請輸入整數");
}
Scanner scanner = new Scanner(System.in);
float a = 0.0f;
System.out.println("請輸入小數");
if(scanner.hasNextFloat()){
a = scanner.nextFloat();
System.out.println("你輸入的是小數沒錯:"+a);
}else{
System.out.println("請輸入小數");
}
scanner.close();
例題:我們可以輸入多個數字,並求其總和和平均數,每輸入一個數字回車確認,通過輸入非數字來結束輸入並輸出執行結果
Scanner scanner = new Scanner(System.in);
float f = 0.0f;
float sum = 0.0f;
float avg = 0.0f;
System.out.println("請輸入多個數字:");
while (scanner.hasNextFloat()){
f = scanner.nextFloat();
sum += f;
avg++;
System.out.println("你輸入了第"+avg+"數字");
}
System.out.println("一共有"+avg+"個數字,和為:"+sum+",平均數為:"+sum/avg);
scanner.close();
switch選擇結構
多選擇結構還有一個實現方式就是switch case語句
switch語句中的變量類型可以是:
- byte、short、int或者char
- 從Java SE7開始
- switch支持字符串String類型了
- 同時case標簽必須為字符串常量或字面量
char grade='C';
switch (grade){
case 'A':
System.out.println("優秀");
break;
case 'B':
System.out.println("良好");
break;
case 'C':
System.out.println("及格");
break;
case 'D':
System.out.println("再接再厲");
break;
default:
System.out.println("未知等級");
}
switch可以支持字符串
String str = "world";
switch (str){
case "hello":
System.out.println("你好");
break;
case "world":
System.out.println("世界");
break;
default:
System.out.println("java");
break;
}
循環結構
- while循環
//計算1+2+3+...+100
int i = 0;
int sum = 0;
while(i<100){
i++;
sum += i;
}
System.out.println(sum); //5050
- do……while循環
//先執行后判斷,至少執行溢出
do{
i++;
sum += i;
}while(i<100) //跟上面效果一樣
- for循環
//(初始化;條件判斷;迭代)
for(int i=0;i<100;i++){
i++;
sum += i;
}
for(; ; ){...} //死循環
- 九九乘法表
for(int i=1;i<=9;i++){
for(int j=1;j<=i;j++){
System.out.print(i+"*"+j+"="+(i*j)+"\t")
}
System.out.println();
}
- 輸出1-1000能被5整除的數,每行輸出3個
//練習:輸出1-1000能被5整除的數,每行輸出3個
for(int i=1;i<=1000;i++){
if(i%5==0){
System.out.print(i+"\t")//輸出完不換行
}
if(i%(3*5)==0){
System.out.println();
}
}
- break & continue
- break可用在任何循環的主體部分,由於強行退出循環,也可以用在switch語句。
- continue用於循環語句中,終止某次循環過程,跳過剩余語句,直接進行下一次循環條件判斷。
- 標簽:后面跟一個冒號的標識符 label:
- 增強for循環
int[] num = {10,12,45,31,2,12};
for(int i=0;i<6;i++){
System.out.println(num[i]);
}
System.out.println("==========================")
for(int x:num){
System.out.println(x);
}
增強for循環可以進行簡寫,簡單方法:如果要循環5次,可以“5.for”就可以在idea中使用
- 打印三角形
for(int i=0;i<6;i++){
for(int j=5;j>i;j--){
System.out.print(" ");
}
for(int j=1;j<=i;j++){
System.out.print("*");
}
for(int j=1;j<i;j++){
System.out.print("*");
}
System.out.println();
}
Java方法詳解
Java方法是語句的集合,他們在一起執行一個功能。
- 方法是解決一類問題的步驟的有序結合
- 方法包含於類或對象中
- 方法在程序中被創建,在其他地方被引用
設計方法的原則:方法的本意是代碼塊,就是實現某個功能的語句塊。我們設計方法的時候,最好保持方法的原子行,就是一個方法只完成1個功能,這樣利於我們后期的擴展。
方法的定義
Java的方法類似於其他語言的函數,是一段用來完成特定功能的代碼片段,一班情況下,定義一個方法包含以下語法:
- 方法包含一個方法頭和一個方法體。下面是一個方法的所有部分
- 修飾符:修飾符,這是可選的,告訴編譯器如何調用該方法,定義了該方法的詢問類型
- 返回值類型:方法可能會返回值,returnValueType是返回值的數據類型,有些方法執行所需的操作,但沒有返回值,在這種情況下,returnValueType是關鍵字void
- 方法名:是方法的實際名稱、方法名和參數共同構成方法簽名
- 參數類型參數像是一個占位符,當方法被調用時,傳遞值給參數,這個值被稱為實參或者變量,參數列表是指方法的參數類型、順序和參數的個數,參數是可選的,方法可以不包含任何參數
//main方法
pubilc static void main(String[] args){
//實際參數:實際調用傳遞給他的參數
int sum=add(5,5);
System.out.println(sum);
}
//加法
//形式參數,用來定義作用的
public static int add()
- 方法體:方法體包含具體的語句定義該方法的功能
修飾符 返回值類型(void不返回) 方法名(參數類型 參數名){
...
方法體
...
return 返回值;
}
Java是值傳遞
方法的重載
-
重載就是在一類中,有相同的函數名稱,但形參不同的函數
-
方法的重載的規則
- 方法名稱必須相同
- 參數列表必須不同(個數不同、或類型不同、參數排列順序不同等)
- 方法的返回類型可以相同也可以不相同
- 僅僅返回類型不同不足以成為方法的重載
-
實現理論:
方法名稱相同時,編譯器會根據調用方法的參數個數、參數類型去逐個匹配,已選擇對應的方法 ,如果匹配失敗,則編譯器報錯
命令行傳參
- 有時候希望運行一個程序時再傳遞給它消息。這要靠傳遞命令行參數給main()函數實現
public static void main(String[] args) {
//args.length 數組長度
for (int i = 0; i < args.length; i++) {
System.out.println("args["+i+"]: "+args[i]);
}
}
找到當前類的文件夾,打開cmd
可變參數
- Jdk1.5開始,Java支持傳遞同類型的可變參數給一個方法。
- 在方法聲明中,在指定參數類型后加一個省略號 (…)。
- 一個方法中只能指定一個可變參數,它必須是方法的最后一個參數。
public static void main(String[] args){
//調用可變參數的方法
printmax(34,45,456,4,6545,44,54,4,54);
printmax(new double[]{1,2,3});
}
public static void printmax(double ...numbers){
if(numbers.length==0){
System.out.println("No argument passed");
return;
}
double result = numbers[0];
//找最大值
for(int i=1;i<numbers.length;i++){
if(numbers[i]>result){
result=numbers[i];
}
}
System.out.println("The max value is" +result)
}
計算器的實現
public static void main(String[] args){
Scanner scanner=new Scanner(System.in);
System.out.println("請輸入第一個數值:");
while(scanner.hasNextDouble()){
double a = scanner.nextDouble();
System.out.println("請輸入操作符");
String srt = scanner.next();
System.out.println("請輸入第二個數值:");
double b=scanner.nextDouble();
switch(str){
case "+":
add(a,b);
break;
case "-":
mius(a,b);
break;
case "*":
multiply(a,b);
break;
case "/":
except(a,b);
break;
default:
System.out.println("輸入的運算符錯誤");
break;
}
}
}
public static void add(double num1,double num2){
System.out.println(num1+num2);
}
public static void mius(double num1,double num2){
System.out.println(num1-num2);
}
public static void multiply(double num1,double num2){
System.out.println(num1*num2);
}
public static void except(double num1,double num2){
if(num2 == 0){
System.out.println("分母不能為0");
}else{
Syste.out.println(num1/num2);
}
}
Java中的數組
數組的簡單實現
- 首先必須聲明數組變量,才能在程序中使用數組。下面是聲明數組變量的語法:
datatype[] arrayRefvar;
int[] num1;
- Java語言使用new操作符來創建數組,語法如下:
datatype[] arrayRevVar=new dataType[arraySize];
-
數組的元素是通過索引訪問的,數組索引從0開始
-
獲取數組長度:array.length
//變量的類型 變量的名字=變量的值;
//數組類型
public static void main(String[] args){
int[] nums;//1.聲明一個數組
nums=new int[10];//2.創建一個數組
int[] nums2=new int[10];//聲明和創建可以放在一起
//3.給數組元素賦值
nums[0]=1;
nums[1]=2;
nums[2]=3;
nums[3]=4;
nums[4]=5;
nums[5]=6;
nums[6]=7;
nums[7]=8;
nums[8]=9;
nums[9]=10;
//計算所有元素的和
int sum=0;
for(int i=0;i<nums.length;i++){
sum += nums[i];
}
System.out.println(sum)
}
數組的四個基本特點
- 其長度是確定的。數組一旦被創建,它的大小就是不可改變的
- 其元素必須是相同類型,不允許出現混合類型
- 數組中的元素可以是任何數據類型,包括基本類型和引用類型
- 數組變量引用類型,數組也可以看成是對象,數組中的每個元素相當於該對象的成員變量。數組本身就是對象,Java中對象是在堆中的,因此數組無論原始類型還是其他對象類型,數組對象本身是在堆中。
- ArrayIndexOutOfBoundsException:數組下標越界異常
數組使用
- 普通的for循環
int[] arrays={1,2,3,45,5};
int sum=0;
for(int i=0;i<arrays.length;i++){
sum += arrays[i];
System.out.println(arrays[i]);
}
- for—Each循環(增強for循環)
int[] arrays={1,2,3,45,5};
for(int array:arrays){
System.out.println(array);
}
- 數組做方法入參(void作為方法入參,可以沒有返回值)
int[] arrays={1,2,3,45,5};
printArray(arrays);
//打印數組元素
public static void printArray(arrays){
for(int i=0;i<arrays.length;i++){
System.out.print(arrays[i] + "");
}
}
- 數組作返回值(反轉數組)
int[] arrays={1,2,3,45,5};
int[] reverse=reverse(arrays);
for(int i=0;.i<reverse.length;i++){
System.out.println(reverse[i]);
}
//反轉數組
public static int[] reverse(int[] arrays){
int[] result=new int[arrays.length];
//反轉操作
for(int i=0;j=result.length-1;i<arrays.length;i++;j--){
result[j]=arrays[i];
}
return result;
}
二維數組
- 二維數組的遍歷
int[][] array={{3,4},{5,6},{6,7}}
//System.out.println(array[1][1]);
//遍歷二維數組的長度
for(int i=0;i<array.length;i++){
for(int j=0;j<array[i].length,j++){
System.out.println(array[i][j]);
}
}
Arrays類
- 數組的工具類是java.utill.Arrays
- 由於數據對象本身並沒有方法可以供我們使用,但是API提供了一個工具類Arrays供我們使用
- Array類中的方法都是static修飾的靜態方法,使用時直接使用類名進行調用,可以不用對象調用
- 常用功能
- 給數組賦值:fill方法
- 排序:sort方法,升序
- 比較數組:equals方法比較數組中元素值是否相等
- 查找數組元素:binarySearch對排序號的數組進行二分法查找操作
int[] array={3,4,5,6,7,2,1,0,8,9,7};
//填充數組
Arrays.fill(array,2,4,0)
//打印數組
System.out.println(Arrays,toString(array));
//排序數組
Arrays.sort(array);
System.out.println(Arrays.toString(array));
//二分法查找 返回的是值得下標
System.out.println(Arrays.binarySearch(array,0));
冒泡排序
- 冒泡排序是八大排序最出名的排序算法。
- 代碼:兩層循環,外層冒泡輪數,里層依次比較。
- 當我們看到嵌套循環,應該立馬就可以得出這個算法的時間復雜度為O(n2)。
public static void main(String[] args){
// 1.比較數組中,兩個相鄰的元素,如果第一個比第二個大,我們就交換他們的位置
// 2.每一次比較,都會產生一個最大或最小的數字
// 3.下一輪,則可以少一次排序
// 4.依次循環,直到結束
int[] a={4,5,6,5,45,54,5,64,54,7};
int[] sort = sort(a);
System.out.println(Arrays.toString(sort));
}
public static int[] sort(int[] array){
//臨時變量
int temp=0;
//外層循環,判斷我們這個要走多少次;
for(int i=0;i<array.length-1;i++){
boolean flag=false;
//內層循環,比較判斷兩個數,如果第一個數比第二個數大,則交換位置
for(j=0;j<array.length-1-i;j++){
if(array[j]>array[j+1]){
//如果第一個數大於第二個數,第二個數放前,第一個數放后
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
flag = true;
}
}
if(flag==false){
break
}
}
return array;
}
稀疏數組
//創建一個二維數組 11*11 0:沒有棋子 1:黑子 2:白子
public static void main(String[] args){
int[][] array=new int[11][11];
array[1][2] = 1;
array[2][3] = 2;
System.out.println("輸出原始的數組");
for(int[] ints:array){
for(int anInt:ints){
System.out.print(anInt = "\t");
}
System.out.println();
}
}
//轉換為稀疏數組保持
//1.獲取有效值得個數
int sum = 0;
for(i = 0;i<11;i++){
for(int j=0;j<11;j++){
if(array[i][j]!=0){
sum++;
}
}
}
System.out.println("=======================");
System.out.println("有效值的個數" + sum);
//2.創建一個稀疏數組的數組
int[][] array2=new int[sum +1][3];
array2[0][0] = 11;
array2[0][1] = 11;
array2[0][2] = sum;
//3.遍歷二維數組,將非零的值,存放在稀疏數組中
int count = 0;
for(int i=0;i<array.length;i++){
for(int j=0;j<array[i].length;j++){
if(array[i][j] != 0){
count++;
array2[count][0] = i;
array2[count][1] = j;
array2[count][2] = array[i][j];
}
}
}
//4.輸出稀疏數組
System.out.println("稀疏數組");
for(int i=0;i<array2.length;i++){
System.out.println(array2[i][0] + "\t" + array2[i][1] + "\t" + array2[i][2] + "\t");
}
System.out.println("====================================")
System.out.ptintln("還原");
//1.讀取稀疏數組
int[][] array3=new int[array2[0][0]][array[0][1]];
//2.給其中的元素還原他的值
for(int i=1;i<array2.length;i++){//注意從1開始,0是頭部信息
array3[array2[i][0]][array2[i][1]]=array2[i][2];
}
//3.打印
System.out.println("輸出還原的數組")
for(int[] ints:array3){
for(int anInt:ints){
System.out.print(anInt + "\t");
}
System.out.println();
}
面向對象編程(OOP)
初識面向對象
- 屬性+方法=類
- 對於描述復雜的事物,為了從宏觀上把握、從整體上合理分析,我們需要使用面向對象來分析整個系統。但是,具體到微觀操作,讓然需要面向過程的思路去處理。
- 面向對象本質就是:以類的方式組織代碼,以對象的組織(封裝)數據。
- 從認識論角度考慮是先有對象后有類
- 三大特性:封裝,繼承,多態。抽象
回顧方法的定義以及調用
定義
- main方法
//main方法
public static void main(String[] args){}
/*
修飾符 返回值類型 方法名(...){
//方法體
return 返回值;
}
*/
public String sayHello(){
return "hello world";
}
public void print(){
return;
}
public int max(int a,int b){
return a>b ?a:b;
}
break:跳出switch循環,結束循環。continue:結束依次循環。return:方法結束,返回類型和返回值相同。
方法名:見名知意,駝峰命名法。參數列表:(參數類型,參數名),...可變參數,數組運用可變參數。
- 靜態方法:
public static void say(){
system.out.print("1111");
}//可直接通過方法名調用,和類一起加載。
- 非靜態方法
public void say(){
System.out.print("1111");
}
//調用
Student student = new Student();//實例化這個類new,對象類型 對象名=對象值;
student.say();
- 形參
public static int add(int a,int b){//int a,int b,形參
return a+b;
}
- 實參
public static void main(String[] args){
int add = Demo03.add(1,3);//1,3:實參
System.out.println(add);
}
- 值傳遞
//值傳遞
public class Demo04{
public static void main(String[] args){
int a=1;
System.out.println(a);
Demo04.change(a);
System.out.println(a);
}
//返回值為空
public static void change(int a){
a=10;
}
}
a=10,返回值為空,a的值還為1。
- 引用傳遞
//引用傳遞:對象,本質還是值傳遞
public class Demo05{
public static void main(String[] args){
Person person = new Person();
System.out.println(person.name);//null
Demo05.change(person);
System.out.println(person,name);//test
}
public static void change(Person person){
//person是一個對象:指向的--->Person person=new Person();這是一個具體的人,可以改變屬性
person.name = "test";
};
}
//定義了一個Person類,有一個屬性:name
class Person{
String name;//null
}
- 基本類型作為參數傳遞時,是傳遞值的拷貝,無論你怎么改變這個拷貝,原值是不會改變的
- 對象作為參數傳遞時,是對象在內存中的地址拷貝一份給了參數
類和對象的關系
- 類是一種沖向的數據類型,它是對某一類事物整體描述/定義,但是並不能代表某一個具體的事物
- 對象是抽象概念的具體實例
創建和初始化對象
- 使用new關鍵字創建的時候,除了分配內存空間之外,還會給創建好的對象進行默認的初始化以及類中構造器的使用
-
一個類即使什么都不寫,它也會存在一個方法
-
構造器:
- 和類名相同
- 沒有返回值
-
核心作用:
- 使用new關鍵字,本質是在調用構造器
- 構造器同來初始化值
-
在無參構造器中,無參構造器可以實例化初始值
- 注意點:
- 有參構造器:一旦定義了有參構造,無參就必須顯示定義
- Alt+Insert
內存分析
小結類與對象
1.類與對象
類是一個模板:抽象,對象是一個具體的實例
2.方法
定義,通用
3.對應的引用
引用類型:基本類型(8)
對象是通過引用來操作的:棧--->堆
4.屬性:字段Field成員變量
默認初始化:
數字:0 0.0
char:u0000
boolean:false
引用:null
修飾符 屬性類型 屬性名=屬性值;
5.對象的創建和使用
必須使用new關鍵字創建對象,構造器Person xiaoming=new Perosn();
對象的屬性 xiaoming.name
對象的方法 xiaoming.sleep()
6.類
靜態的屬性 屬性
動態的行為 方法
封裝
- 該露的露,該藏的藏
- 我們程序設計要追求”高內聚,低耦合“。高內聚就是類的內部數據細節由自己完成,不允許外部干涉;低耦合:僅暴露少量的方法給外部使用。
- 封裝(數據的隱藏)
- 通常,應禁止直接訪問一個對象中數據的實際表示,而應該通過操作接口來訪問,稱為信息隱藏。
- 屬性私有,get/set
//名字
private String name;
//學號
private int id;
//性別
private char sex;
//年齡
private int age;
public int getAge(){
if(age>120 || age<0){
this.age=3;
}else{
this.age=age;
}
return age;
}
public void setAge(int age){
this.age=age;
}
public String getName(){
this.name=name;
}
public void setName(String name){
this.name=name;
}
public int getId(){
return id;
}
public void setId(int id){
this.id=id;
}
public char getSex(){
return sex;
}
public void setSex(char sex){
this.sex=sex;
}
Students s1=new Students();
s1.setAge(1200);
System.out.println(s1.getAge());
- 作用
- 提高程序的安全性,保護數據
- 隱藏代碼的實現細節
- 統一接口
- 系統可維護性增加了
繼承
- 繼承的本質是對某一批類的抽象,從而實現對世界更好的建模
- extends的意思是“擴展”。子類是父類的擴展,使用extends來表示
- Java中只有單繼承,沒有多繼承!一個類只能繼承一個父類
- 繼承是類與類之間的一種關系,此外還有依賴、組合、聚合等
- 繼承關系的兩個類,一個是子類(派生類),一個是父類(基類)子類繼承父類
- 子類繼承了父類,就會擁有父類的全部方法,而private私有屬性及方法無法繼承
- 在Java中,所有類,都默認直接或間接繼承Object類(Ctrl+H可以查看類關系)
- 被final修飾的類,無法繼承(斷子絕孫)
super&this
super注意點:
1.super調用父類的構造方法,必須在構造方法的第一個(默認調用)
2.super必須只能出現在子類的方法或者構造方法中
3.super和this不能同時調用構造方法
VS this
- 代表的對象不同:
- this:本身調用者這個對象
- super:代表父類對象的應用
- 前提
- this:沒有繼承也可以使用
- super:只能在繼承條件下可以使用
- 構造方法
- this():本類的構造
- super():父類的構造
- super與this的區別:super代表父類對象的引用,只能在繼承條件下使用;this調用自身對象,沒有繼承也可以使用
super(); //隱藏代碼,默認調用了父類的無參構造,要寫只能寫第一行
方法的重寫
- 重寫:需要有繼承關系,子類重寫父類的方法!方法名必須相同
- 參數列表必須相同
- 修飾符可以擴大但是不可以縮小
- public>protected>default>private
- 拋出的異常:范圍,可以被縮小,但是不能擴大:ClassNotFoundException-->Exception(大)
- 重寫是方法的重寫,與屬性無關
- 重寫方法只與非靜態方法有關,與靜態方法無關(靜態方法不能被重寫)
- 被static(屬於類,不屬於實例),final(常量方法),private(私有)修飾的方法不能重寫
public class B{
public static void test(){靜態方法
System.out.println("B==>test()")
}
}
public class A extends B{//繼承
public static void test(){
System.out.println("A==>test()")
}
}
public class Application(){
public static void main(String[] args){
//方法的調用只和左邊的定義的類型有關
A a = new A();
a.test();//打印A==>test()
//父類的引用指向了子類,但靜態方法沒有被重寫
B b = new A();
b.test();//打印B==>test()
}
}
修改A.Java,B.java
public class B{
public void test(){//非靜態方法
System.out.println("B==>test()");
}
}
public class A extends B{
@Override //重寫了B的方法
public void test(){
System.out.println("A==>test()");
}
}
//父類的引用指向了子類
B b = new A();
//子類重寫了父類的方法,執行子類的方法
b.test();//打印變成了A==>test()
/*
靜態方法是類的方法,非靜態方法是對象的方法。有static時,b調用了B類的方法,因為b是B類定義的。沒有static時,b調用的是對象的方法,而b是A類new出來的對象,調用A的方法
*/
重寫:子類的方法名必須和父類保持一致,方法體不同
被static(屬於類,不屬於實例),final(常量方法),private(私有)修飾的方法不能重寫
為什么重寫:
- 父類的功能,子類不一定需要,或者不一定滿足
Alt + Insert ; override;
多態
- 即同一方法可以根據發送對象的不同而采用不同的行為方式
- 一個對象的實際類型是確定的,但可以指向對象的引用可以有很多
- 多態存在條件
- 有繼承關系
- 子類重寫父類的方法
- 父類引用指向子類對象
注意點
-
多態是方法的多態,沒有屬性的多態
- 父類和子類,有聯系 類型轉換溢出:ClassCastException
- 存在條件:繼承關系,方法需要重寫,父類引用指向了子類對象
instanceof和類型轉換
- instanceof引用類型比較,判斷一個對象是什么類型
- 類型轉換
- 父類引用指向子類的對象
- 把子類轉換為父類,向上轉型,會丟失自己原來的一些方法
- 把父類轉換為子類,向下轉型,強制轉換,才調用子類方法
- 方便方法的調用(轉型),減少重復的代碼,簡潔
static
- 靜態變量可以直接用類名訪問,也稱類變量
- 靜態變量(或方法)對於類,所有對象(實例)共享
- 靜態變量可以直接調用,但是非靜態變量不可以直接調用
private static int age;
private double score;
public void run(){ }
public static void go(){ }
public static void main(String[] args){
Student s1 = new Student();
System.out.println(Student.age);
System.out.println(Student.score);
System.out.println(s1.ahe);
System.out.println(s1.score);
go();
run();
}
- 靜態區代碼加載類時一起被初始化,最早執行且只執行一次(第一次new)
public class Person{
{
System.out.println("匿名代碼塊");
}
static {
System.out.println("靜態代碼塊");
}
public Person(){
System.out.println("構造方法");
}
public static void main(String[] args){
Person person = new Person();
System.out.println("=====================")
Person person2 = new Person();
System.out.println("=====================")
Person person3 = new Person();
}
}
- Math->隨機數:
//靜態導入包
import static java.lang.Math.random;
public class Application {
public static void main(String[] args) {
//第一種隨機數,不用導包
System.out.println(Math.random());
//0.7562202902634543
//第二種隨機數,靜態導入包
System.out.println(random());
//0.5391606223844663
}
}
抽象類
- abstract修飾的類就是抽象類,修飾的方法就是抽象方法
- 抽象類中可以沒有抽象方法,但有抽象方法的類一定要聲明為抽象類
- 抽象類不能使用new來創建對象,它是用來讓子類繼承的
- 抽象方法只有方法的聲明,沒有實現,讓其子類實現
- 子類繼承抽象類,必須實現抽象類的所有方法, 否則該子類也要聲明為抽象類
- 編譯器給抽象類添加了一個無參構造方法。
接口
接口最能體現OOP的精髓,對 對象 的抽象
在Java編程語言中是一個抽象類型,是抽象對象的集合,對象通常以interface關鍵字來聲明。
- 普通類:只有具體實現
- 抽象類:具體實現和規范(抽象方法)共存
- 接口:只有規范,無法自己實現
- 約束和實現分離->面向接口編程
接口就是規范,定義一組規則,它的本質是契約,制定好之后大家都要遵守。
聲明
[可見度] interface 接口名稱 [extends 其他的接口名] {
// 聲明變量
// 抽象方法
}
/**
*用戶接口,需要實現類
*鍛煉抽象的思維
*/
public interface UserService{
//定義的屬性默認是靜態常量:public static final
int age = 10;
//定義的方法是公共抽象:public abstract
void add(String str);
void delete(String str);
void update(String str);
void query(String str);
}
public interface TimeService{
void timer();
}
特性
- 接口是隱式抽象的,當聲明一個接口的時候,不必使用abstract關鍵字。
- 接口中每一個方法也是隱式抽象的,聲明時同樣不需要abstract關鍵字
- 接口中的方法都是公有的。
實現
/*
抽象類用繼承:extends
接口用實現:implements
類可以實現接口,需要實現所有方法!
利用接口實現偽多繼承~
*/
public class UserServiceImplement implements UserService,TimeService{
@Override
public void add(String str){
}
@Override
public void delete(String str){
}
@Override
public void update(String str){
}
@Override
public void query(String str){
}
@Override
public void timer(){
}
}
類在實現接口的方法時,不能拋出強制性異常,只能在接口中,或者繼承接口的抽象類中拋出該強制性異常
在實現接口的時候,也要注意一些規則:
- 一個類只能繼承一個類,但是能實現多個接口
- 一個接口能繼承另一個接口,這和類之間的繼承比較相似
繼承
接口的繼承使用extends關鍵字,子接口繼承父類接口的方法
//文件名:Sports.java
public interface Sports{
public void setHomeTeam(String name);
public void setVisitingTeam(String name);
}
//文件名:Football.java
public interface Foorball extends Sports{
public void homeTeamScored(int points);
public void visitingTeamScored(int points)
public void endOfQuarter(int quarter);
}
//文件名:Hockey.java
public interface Hockey extends Sports{
public void homeGoalScored();
public void visitingGoalScored();
public void endOfPeriod(int period);
public void overtimePeriod(int ot);
}
多繼承
- 類不允許多繼承
- 接口允許多繼承
public interface Hockey extends Sports,Event
接口與類相似,一個接口可以有多個方法
接口與類的區別
- 接口不能被實例化
- 接口沒有構造方法
- 接口中所有的方法必須是抽象方法
- 接口不能包含成員變量,除了static和final變量
- 接口不是被類繼承,而是被類實現
- 接口支持多繼承(實現類(implements) 可以實現多個接口)
- 實現類必須要重寫接口中的方法
JDK8之后的新特性,支持在接口中實現具體方法,但需要default修飾。default修飾方法只能在接口中使用。
內部類
內部類:在一個類的內部再定義一個類
class A{
class B{
}
}
A是B的外部類,B是A的內部類。
成員內部類
public class Outer{
private int id;
public void out(){
System.out.println("外部類的方法");
}
//成員內部類
public class Inner{
public void inner(){
System.out.println("內部類的方法");
}
//可以直接使用外部類的屬性/方法
public void getOuterId(){
System.out.println("內部類調用外部類屬性和方法");
//創建成員內部類之前肯定要創建外部類對象
//即使id不是靜態變量,out不是靜態方法,但創建外部類對象時已經存在。
System.out.pirntln(id);
out();
}
}
}
匿名內部類
public class Application{
public static void main(String[] args){
//匿名內部類在多線程中使用,到時候再深究
Thread thread = new Thread(new Runnable(){
@Override
public void run(){
System.out.println("匿名內部類實現線程的邏輯操作");
}
});
//開啟操作
thread.start();
}
}
異常
Java把溢出當做對象來處理,並定義了一個基類Java.lang.Throwable作為所有異常的超類。
Java語言定義了許多異常類在Java.lang標准包中,主要分為Error和Exception兩大類。
五個關鍵字try、catch、finally、throw、throws
使用try和catch關鍵字可以捕獲異常。try/catch代碼塊放在異常可能發生的地方。
try/catch代碼塊中的代碼稱為保護代碼。
finally區可以不要,在IO流,資源關閉時使用。
捕獲多個溢出:從小到大!
IDEA快捷鍵:選中健康區域代碼-->Ctrl + Alt + T
public static void main(String[] args) {
int a=1;
int b=0;
try{
System.out.println(a/b);
}catch (Error e){
System.out.println("Error");
}catch(Exception e){
System.out.println("Exception");
}catch (Throwable t){
System.out.println("Throwable");
}finally {
System.out.println("finally");
}
}
public void a(){b();}
public void b(){a();}
拋出異常
throws是用來聲明一個方法可能拋出的所有異常信息,throws是將異常聲明但是不處理,而是將異常往上傳,誰調用我就交給誰處理。而throw則是指拋出的一個具體的異常類型
throws是用在方法名尾部,可以聲明拋出多個溢出,多個溢出之間用逗號隔開。
import java.io.*;
public class className{
public void withdraw(double amount) throws RemoteException,InsufficientFundsException{
//Method implementation
}
//Remainder of class definition
}
throw是用在方法體內,主動拋出異常
public class ThrowTest{
public static void main(String[] args){
int a = 1;
int b = 0;
try{
System.out.println(divide(a,b));
}catch (Exception e){
System.out.println("分母不能為0");
//e.printStackTrace();
}
}
public static double divide(int a,int b){
if(b == 0){
//主動拋出異常
throw new ArithmeticException();
}
return 1.0*a/b;
}
}
自定義異常
//自定義的異常類
public class MyException extends Exception{
private int detail;
public Myexception(int a){
this.detail = a;
}
//異常的處理信息
//tostring
@Override
public String toString(){
return "Myexception{" + "detail=" + detail + "}";
}
}
public class Appcication{
//可能存在異常方法
static void test(int a) throws MyException{
System.out.println("傳遞的參數為:" + a);
if(a>10){
throw new MyException(a);//拋出
}
System.out.println("ok");
}
}
public static void main(String[] args){
try{
test(11);
}catch (MyException e){
System.out.println("MyException=>" + e);
}
}
總結
- 處理運行是異常時,采用邏輯去合理規避,同時輔助try-catch處理
- 在多重catch塊后面,可以加一個catch(Exception)來處理可能會被遺漏的異常
- 對於不確定的代碼,也可以加上try-catch,處理潛在的異常
- 盡量去處理異常,切忌只是簡單的調用printStackTrace()去打印輸出
- 具體如何處理異常,要根據不同的業務需求和異常類型去決定
- 盡量添加finally語句塊去釋放占用的資源。
轉載:https://blog.csdn.net/qq_42186847/article/details/120633189