学习java
在这里插入图片描述
1:常用的DOS命令
- 查看当前文件目录 dir
- 切换目录 cd change dierctory
- cd…
- 清理屏幕 cls(clear screen)
- 退出中单 exit
- 查看电脑的ip ipconfig
#打开应用
calc
mspaint
notpead
#ping 命令
ping www.baidu,con (可以得到IP地址)
#文件操作
md 目录名
rd 目录名
cd>文件名
del 文件名
2:计算机语言发展史
-
机器语言
- 二进制:
- 这种代码是直接输入给计算机使用的,不经过任何转换
-
汇编语言
- 逆向工程
- 机器人
- 病毒
-
第三代语言
- C语言
- C++
- JAVA
- C#
- Python ,PHP ,JavaScript
-
1972年C诞生
- 贴近硬件,运行极快,效率极高
- 操作系统,编译器,数据库,网络系统
- 指针和内存管理
-
1982年C++诞生
- 面向对象
- 兼容C
- 图形领域,游戏等。
3 Java初生
- 1995年的网页简单而粗糙,缺乏互动性
- 图形界面的程序Applet
- Bill Gates 说:这是迄今为止设计的最好的语言
- java 2 标准版(J2SE):去占领桌面
- Java 2 移动版(J2ME):去占领手机
- Java 2 企业版(J2EE):去占领服务器
- 大量的巨头加入
1.JAVA发展
- 他们基于JAVA开发了巨多的平台,系统,工具
- 构建工具:Ant,Maven,Jekins
- 应用服务器:Tomcat,jetty,Jboss,Websphere,weblogic
- web开发:Struts,Spring,Hibernat,MyBatis
- 开发工具:Eclipse,Netbean,intellij idea, Jbullder
- 2006 : Hadoop(大数据领域)
- 2008:Andeoid(手机端)
4 JAVA特性与优势
- 简单性
- 面向对象
- 可移植性
- 高性能
- 分布式
- 动态性
- 多线程
- 安全性
- 健壮性
思考:java为什么能够成功?
5.Java三大版本
- write Onec ,Run AnyWhere
- JavaSE : 标准版(桌面程序,控制台开发)
- JavaME:嵌入式开发(手机,小家电)
- JavaEE:E企业级开发(Web。服务器开发)
6.JDK,JRE,JVM
- JDK:java Devenlopmebt Kit
- JRE:java Runtime Environment
- JVM: java Virtual Machine
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gB8o8TDA-1623677352184)
7.安装JDK
JDK 安装与环境变量配置(Win10详细版)
https://blog.csdn.net/qq_38436214/article/details/105071088?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162086635416780357216289%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=162086635416780357216289&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_positive~default-2-105071088.first_rank_v2_pc_rank_v29&utm_term=jdk%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E9%85%8D%E7%BD%AE
JDK 安装与环境变量配置(Win10详细版)
https://www.bilibili.com/video/BV12J41137hu?p=17&spm_id_from=pageDriver
卸载JDK
- 删除java的安装目录
- 删除JAVA_HOME
- 删除path下关于java的目录
- java -version
8.Java程序运行机制
- 编译性
- 解释性
- 程序运行机制
9.IDE的优化一级快捷键
https://blog.csdn.net/qq_40990306/article/details/102841692?spm=1001.2014.3001.5501
10.注释
- 注释,标识符,关键字
- 数据类型
- 类型转换
- 变量,常量
- 运算符
- 包机制,javaDoc
10.1 注释
- 平时我们编写代码,在代码量比较少的时候可以看懂自己写的,但是项目结构复杂起来,我我们就需要用到注释了
- 注释并不会被执行,是写给开发人员自己看的
- 书写注释是一个非常好的习惯
- java中的注释有三种
- 多行注释
- 单行注释
- 文档注释
10.2 标识符
- Java所有组成的部分都需要名字。类名、类名、变量名以及方法名都被称为标识符
10.2.1 标识符注意点
- 所有的标识符都应该以字母(A-Z或者a-z),美元符($)、或者下划线(_)开始
- 首字符之后可以是字母(A-Z或者a-z),美元符($)、或者下划线(_)或数字的任何字符组合
- 不能使用关键字作为变量名或者方法名
- 标识符是大小写敏感的
- 合法标识符举例,age,$salary,value,_1_value
- 非法标识符举例:123abc,-salary,#abc
- 可以使用中文命名,但是不建议
10.3 数据类型
-
强类型语言
- 要求变量的使用严格符合规定,所有变量都必须先定义后才能使用
-
弱类型语言
-
Java的数据类型分为两大类
基本类型(primitive type)
- 数值类型
- 整数类型
- byte 占用一个字节 :-128-127
- short 占用2个字节范围:-32768-32767
- int 占用4个字节范围:-2147483648-2147483647
- long 占用8个字节:-9223372036854775808-9223372036854775807
- 浮点类型
- float 占用4个字节
- double 占用8个字节
- 字符类型
- char 占用2个字节
- 整数类型
- Boolean类型,占1位字节,有false和true两个值
引用类型(reference type)
- 类
- 接口
- 数组
- 数值类型
10.3.1什么是字节
位(bit):是计算机内存数据存储的最小的单位,
字节(Byte):是计算机中数据处理的基本单位,习惯用大写B来表示
1B(Byte,字节)= 8bit(位)
字符:是指计算机中使用的字母、数字、字和符号
- 1bit表示1位
- 1Byte表示一个字节 1B=8b
- 1024B=1KB
- 1024KB = 1M
- 1024M =1G
10.4 数据类型以及面试题
举例
//布尔值扩展
boolean flag = true;
if(true == flag){} //新手
if(flag){} //老手
//Less is More 代码要精简已读
10.5 类型转换
//由于java是强类型语言,所以要进行有些运算的时候的,需要用到强类型转换
//低---------------------------------高
//byte,short,char-> int -> long -> float ->double
//运算中,不同类型的数据先转换为同一类型,然后进行运算
//强制类型转换
//自动类型转换
int i = 128;
byte b = (byte)i;//内存溢出
//强制转换(类型)变量名 高--低
//自动转换 低--高
System.out.println(i);
System.out.println(b);
/*
注意点:
1.不能对布尔值进行转换
2. 不能把对象类型转换为不相干的类型
3. 在把高容量转换到低容量的时候,强制转换
4. 在转换的时候可能存在内存溢出,或者精度问题
*/
System.out.println("=============================");
System.out.println((int)23.7); //23
System.out.println((int)-45.89f); //-45
System.out.println("=============================");
char c = 'a';
int d = c+1;
System.out.println(d);
System.out.println((char)d);
//操作比较大的时候,注意溢出问题
//JDK新特性,数字之前可以用下划线分割
int money = 10_0000_0000;
int years = 20;
int total = money * years; //-1474836480,计算的时候溢出
long total2 = money * years;//,默认是int,转换之前已经存在问题了
long total3 = money*((long)years);//先把一个数转换为Long
System.out.println(total3);
10.6 变量
- 变量是什么:就是可以变化的量
- Java是一种强类型语言,每个变量都必须声明气类型
- Java变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域
type varName [=value] [{,varname[=value]}];
//数据类型 变量名 = 值; 可以使用都好隔开来声明多个同类型变量
- 注意事项:
- 每个变量都有类型,类型可以是基本类型,也可以是引用类型
- 变量名必须是合法的标书符
- 变量声明是一条完整的语句,因此每一个声明都必须以分号结束
//int a,b,c
//int a=1,b=2,c=3; //java需要程序可读性
String name = "beibei";
char x = 'X';
double pi = 3.14;
10.6.1 变量作用域
- 类变量
- 实例变量
- 局部变量
10.6.2变量
//类变量 static(讲JVM的时候去讲)
static double salary = 2500;
// 属性:变量
//实例变量: 从属于对象; 如果不进行初始化,就变成默认值 0 0.0
//布尔值:默认是false
//除了基本类型,其余都是默认值
String name;
int age;
//main方法
public static void main(String[] args) {
//局部变量:必须声明和初始化值
int i = 10;
System.out.println(i);
//变量类型 变量名字 = new Demo05
Demo05 demo05 = new Demo05();
System.out.println(demo05.age);
System.out.println(demo05.name);
}
//其他方法
public void add(){
}
10.6.3 常量
- 常量(Constant):初始化(initialize)后不能在改变值!不会变动的值
- 所谓常量可以理解成一种特殊的变量,它的值被设定后,在程序运行过程中是不允许被修改的
final 常量名 = 值;
final double PI = 3.14;
- 常量名一般使用大写字符
//修饰符好,不存在先后顺序
static final double PI = 3.14;
public static void main(String[] args) {
System.out.println(PI);
10.6.4 变量的命名规范
- 所有的变量、方法、类名:见名知意
- 类成员变量:首字母小写和驼峰原则:monthSalary
- 局部变量:首字母小写和驼峰原则
- 常量:大写字母和下划线:MAX_VALUE
- 类名:首字母大写和驼峰原则:Man,GoodMan
- 方法名:首字母小写和驼峰原则:run(),runRun()
11.运算符
- Java语言支持如下运算符号
- 算术运算符:+,-,*,/,%,++,–
- 赋值运算符: =
- 关系运算符号:>,<,>=,<=,==,!= instanceof
- 逻辑运算符号:&&, ||, !
- 位运算符号:&, |, ^, ~, >>, << , >>>(了解!!!)
- 条件运算符号: ?
- 扩展赋值运算符号:+=,-=,*=,/=
12.自增自减运算符
//二元运算符
//Ctrl + D 复制当前到下一行
//++ -- 自增,自检,一元运算符
int a = 3;
int b = a++; //执行完成这行代码后先给b赋值,在自增
System.out.println(a); //4
//a = a+1;
int c = ++a; //执行完成这行代码前,先自增,在给B赋值
System.out.println(a); //5
System.out.println(b); //3
System.out.println(c); //5
//幂预算 2^3 2*2*2 = 8 很多运算,我们会使用一些工具类来操作
double pow = Math.pow(3,2);
System.out.println(pow); //9.0
13.逻辑运算符
//逻辑运算符号
//与(and) 或(or) 非(取反)
boolean a = true;
boolean b = false;
System.out.println("a && b"+(a&&b));//逻辑与运算:两个变量都为真,结果才为true
System.out.println("a || b"+(a||b));//逻辑或预算:两个变量有一个为真,则结果为true
System.out.println("!(a && b)"+!(a&&b));//如果是真,则变为假,如果是假则为真
//短路运算
int c =5;
boolean d = (c<4)&&(c++<4);
System.out.println(d); //false
System.out.println(c); //5
/**
* A = 0011 1100
* B = 0000 1100
* A&B = 0000 1100
* A|B = 0011 1101
* A^B = 0011 0001
* ~B = 1111 0010
* 2*8 = 16 2*2*2*2
* 效率极高
* <<
* >>
* 0000 0000 0
* 0000 0001 1
* 0000 0010 2
* 0000 0011 3
* 0000 0100 4
* 0000 1000 8
* 0001 0000 16
*
*/
14:三元运算符
int a = 10;
int b = 20;
a+=b; //a =a+b
a-=b; //a = a-b
//字符串连接符 +,String
System.out.println(""+a+b);
System.out.println(a+b+"");
//三元运算符
// X ? y : z
//如果X == true ,则结果为y ,否则结果为z
int score = 80;
String type = score <60 ?"不及格":"及格";//必须掌握
System.out.println(type);
15:包机制
- 为了更好地组织类,Java提供了包机制,用于区别类名的命名空间
- 包的语法格式为:
package pkg1[.pak2[.pkg3...]]
-
一般利用公司域名倒置作为包名;
-
为了能够使用某一个包的成员,我们需要在Java程序中明确导入该包。使用“import”语句即可导入
import pkg1[.pak2[.pkg3...]]
16:JavaDoc文档
- javadoc 命令是用来生成自己API文档
- 参数信息
- @author 作者名
- @version 版本号
- @since 指明需要最早使用的jdk
- @param 参数名
- @return 返回值情况
- @thows 异常抛出情况
17: Java流程控制
17.1:用户交互Scannner
- 之前我们学习的基本语法中我们并没有实现程序和人的交互,但是java给我们提够了这样一个工具类,我们可以获取用户的输入。java.util.Scanner是Java的新特征,我们可以通过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()){
//使用next方式接收
String str = scanner.next();
System.out.println("输出的内容为:"+str);
}
//凡是属于IO流的类如果不关闭会一直占用资源,要养成好的习惯用完就关
scanner.close();
==================================================================
//创建一个扫描器对象,用于接受键盘数据
Scanner scanner = new Scanner(System.in);
System.out.println("使用nextLine方式接收:");
//判断是否还有输入
if (scanner.hasNextLine()){
String str = scanner.nextLine();
System.out.println("输出的内容为:"+str);
}
scanner.close();
-
next():
- 一定要读取到有效字符后才可以结束输入
- 对输入有效符之前遇到的空白,next() 方法会自动将其去掉
- 只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符
- next()不能得到带有空格的字符串
-
nextLine():
- 以Enter为结束符,也就是说nextLine()方法返回的是输入回车之前的所有字符。
- 可以获得空白。
//我们可以输入多个数字,并求其总和与平均数,每输入一个数字用回车确认,通过输入非数字结束输入并输出执行结果
Scanner scanner = new Scanner(System.in);
//和
double sum = 0;
//计算输入了多少个数字
int m = 0 ;
//通过判断循环是否还有输入,并在里面对每一次进行求和和统计
while(scanner.hasNextDouble()){
double x = scanner.nextDouble();
m = m + 1;
sum = sum + x;
System.out.println("你输入了第"+m+"个数据,然后当前结果sum="+sum);
}
System.out.println(m+"个数的和为:"+sum);
System.out.println(m+"个数的平均数为:"+(sum/m));
scanner.close();
17.2:顺序结构
- JAVA的基本结构就是顺序结构,除非特别指明,否则就按照顺序一句一句执行
- 顺序结构是最简单的算法结构
- 语句与语句之间,框与框之间是按从上到下的顺序进行的,它是若干个依次执行的处理步骤组成的,它是任何一个算法偶离不开的一种基本算法结构。
17.3:选择结构
- if单选择结构
- 我们很多时候需要判断一个东西是否可行,我们才去执行,这样一个过程在程序中用if语句来表示
语法:
if(布尔表达式){
//如果布尔表达式为true将执行的语句
}
例子:
Scanner scanner = new Scanner(System.in);
String s = scanner.nextLine();
//equals :判断字符串是否相等
if (s.equals("Hello")){
System.out.println(s);
}
System.out.println("End");
scanner.close();
-
if双选择结构
-
问题,现在公司有个需求,公司要收购一个软件,成功了,给人支付100万元,失败了,自己找人开发。这样的需求用一个if就搞不定了,我们需要有两个判断,需要一个双选择结构,所以就有了if-else结构。
语法: if(布尔表达式){ //如果表达式的值为true }else(布尔表达式){ //如果表达式的值为false } Scanner scanner = new Scanner(System.in); System.out.println("请输入成绩"); int score = scanner.nextInt(); if (score > 60){ System.out.println("及格"); }else{ System.out.println("不及格"); } scanner.close();
-
-
if多选择结构
- 我们发现刚才的代码不符合实际情况,真实的情况还可能存在ABCD,存在区间多级判断,比如90-100就是A,80-90就是B…等等,在生活中我们很多时候地选择也不仅仅只有两个,所以我们需要一个多选择结构来处理这些问题
语法:
if(布尔表达式){
//如果表达式1的值为true执行代码
}else if(布尔表达式){
//如果表达式2的值为true执行代码
}else if(布尔表达式){
//如果表达式3的值为true执行代码
}else (布尔表达式){
//以上表达式都不为true执行代码
}
举例
Scanner scanner = new Scanner(System.in);
System.out.println("请输入成绩");
int score = scanner.nextInt();
if (score == 100){
System.out.println("恭喜满分");
}else if (score <100 && score >= 90 ){
System.out.println("A");
}else if (score <90 && score >= 80 ){
System.out.println("B");
}else if (score <80 && score >= 70 ){
System.out.println("C");
}else if (score <70 && score >= 60 ){
System.out.println("D");
}else if(score <60 && score >= 0){
System.out.println("成绩不及格");
} else{
System.out.println("成绩不合法");
}
scanner.close();
-
嵌套的if结构
-
switch多选择结构
- 多选择结构还有一个实现的方式就是switch case语句
- switch case 语句判断一个变量与一系列值中某个值是否相等,每一个值称为分支
-
switch 语句中的变量类型可以是
-
byte,short,int,char
-
从javaSE 7开始
-
switch支持字符串String类型了
-
同时case标签必须为字符串常量或者字面量
-
switch(){ case value: //语句 break; //可选 case value: //语句 break; //可选 //你可以有任意数量的case语句 default://可选 //可选 }
//case 穿透 //switch匹配一个具体的值 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; case 'E': System.out.println("挂科"); break; default: System.out.println("未知等级"); }
-
-
17.4:循环结构
while循环
- while最基本的循环,它的结构为:
while(布尔表达式){
//循环内容
}
- 只要布尔表达式true,循环则就会一直执行下去
- 我们大多数情况是会让循环停止下来,我们正常的业务编程中应该尽量避免死循环。会影响程序性能或者造成程序卡死崩溃
do… while循环
int i = 0;
int sum = 0;
do {
sum = sum + i;
}while (i<=100);
System.out.println(sum);
for循环
-
虽然所有循环结构可以用while或者do…while表示,但Java提供了另一种语句-----for循环,是一些循环结构变得更加简单
-
for循环语句是支持迭代的一种通用结构,是最有效,最灵活的循环结构
-
for循环执行的次数是在执行前就确定的,语法格式如下
-
for(初始化;布尔表达式;更新){ //代码语句 } //初始化判断条件 int a = 1; //条件判断 while (a<=100){ //循环体 System.out.println(a); //迭代 a+=2; } System.out.println("while循环结束!"); //初始化;条件判断;迭代 for (int i = 0; i <= 100; i++) { System.out.println(i); } System.out.println("for循环结束"); /** * 关于for循环有以下几点说明: * 最先执行初始化步骤,可以声明一种类型,但可初始化一个或多个循环控制变量,也可以是空语句。 * 然后,检测布尔表达式的值,如果为true,循环体被执行,如果为false,循环终止 * 再次检测布尔表达式,循环执行上面的过程 */ for (int i = 0; i < 100; i++) { }
练习1:计算0到100之间的奇数和偶数的和
//练习1:计算0到100之间的奇数和偶数的和 //定义一个奇数变量 int oddSum = 0; //定义一个偶数变量 int evenSum = 0; for (int i = 0; i < 100; i++) { //奇数 if(i%2!=0){ oddSum+=i; }else{ //偶数 evenSum+=i; } } System.out.println("奇数的和:"+oddSum); System.out.println("偶数的和:"+evenSum);
练习2:用while或for循环输出1-10000之间能被5整除的书,并且每行输出3个
// 练习2:用while或for循环输出1-10000之间能被5整除的书,并且每行输出3个 for (int i = 0; i < 1000; i++) { if (i%5==0){ System.out.print(i+"\t"); } if(i%(5*3)==0){ System.out.println("\n"); } }
练习3:打印九九乘法表
//练习3:打印九九乘法表 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(); }
在Java5中引入了一种主要用于数组的增强for循环
//增强for循环
int [] numbers = {10,20,30,40,50};
for (int x: numbers) {
System.out.println(x);
}
17.5:break&continue
- break在任何循环语句的主体部分,均可用break循环控制流程。break用于强行退出循环,不执行循环中剩余的语句。(break语句在Switch语句中使用)
- continue 语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环判定
17.6:练习题
打印三角形
//打印三角形 5行
for (int i = 1; i <=5 ; 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的方法详解
1:何为方法?
-
System.out.println();那么它是什么呢?
-
Java方法是语句的集合,它们在一起执行一个功能。
- 方法是解决一类问题的步骤的有序组合
- 方法包含与类或对象中
- 方法在程序中被创建,在其他地方被引用
-
设计方法的原则:方法的本意是功能块,就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,就是一个方法只完成一个功能,这样利于我们后期的发展。
-
//main方法 public static void main(String[] args) { int add = add(1, 2); System.out.println(add); } //加法 public static int add(int a, int b){ return a+b; }
2:方法的定义和调用
- Java的方法类似于其它语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义一个方法包含一下语法:
- 方法包含一个方法头和一个方法体。下面是一个方法的所有部分:
- 修饰符:修饰符,这是可选的,告诉编译器如何调用该方法,定义了该方法的访问类型。
- 返回值类型:方法可能会返回值。returnValueType是方法返回值的数据类型,有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType是关键字vold
- 方法名:是方法的实际名称,方法名和参数表共同构成方法签名。
- 参数类型:参数像是一个占位符,当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型,顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
- 形式参数:在方法被调用时用于接收外界输入的数据
- 实参:调用方法时实际传给方法的数据
- 方法体:方法体包含具体的语句,定义该方法的功能。
方法调用
-
调用方法:对象名.方法名(实参列表)
-
Java支持两种调用方法的方式,根据方法是否返回值来选择。
-
当方法返回一个值的时候,方法调用通常被当做一个值。例如
-
int larger = max(30,40);
-
如果方法返回值是void,方法调用一定是一条语句
-
System.out.println("Hello,kuangshen");
3:方法的重载
- 重载就是在一个类中,有相同的函数名称,但是形参不同的函数
- 方法重载的规则
- 方法名必须相同
- 参数列表不同(个数不同,类型不同,参数排列顺序不同等)
- 方法的返回类型可以相同也可以不相同
- 仅仅返回类型不同不足以成为方法的重载
- 实现理论
- 方法名称相同时,编译器会根据调用的方法的参数个数,参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错。
4:可变参数
- JDK1.5 开始,Java支持传递同类型的可变参数给一个方法。
- 在方法声明中,在指定参数类型后加一个省略号(…)
- 一个方法中只能指定一个可变参数,他必须是方法的最后一个参数。任何普通的参数必须在他之前声明。
5:递归讲解
- A方法调用B方法,我们很容易理解
- 递归就是:A方法调用A方法,就是自己调用自己
- 利用递归可以用简单的程序来解决一些复杂的问题。它通常吧一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需要少量的程序就可描述出阶梯过程需要多次重复计算,大大减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。
- 递归结构包含两个部分:
- 递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。
- 递归体:什么时候需要调用自身方法。
什么是数组?
1:数组的概述
数组的定义:
- 数组是相同类型数据的有序集合
- 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成
- 其中,每一个数据称作为一个数组元素,每个数组元素可以通过一个下标访问它们
2:数组的声明创建
-
首先必须声明数组变量,才能在程序中使用数组。下面是声明数组变量的语法:
-
dateType[] arrayRefVar; //首选的方法 或 dateType arrayRefVar[];//效果相同,但不是首选的方法
-
Java语言使用new操作符来创建数组:语法如下:
-
dateType[] arrayRefVal = new dateType[arrSize];
-
数组的元素是通过索引访问的,数组索引从0开始。
-
获取数组的长度:array.length
//变量的类型 变量的名字 = 变量的值
//数组类型
//1.声明一个数组
int [] nums ;
//2.创建一个数组
nums = 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;
//获取数组长度:arrays.length
for (int i = 0; i <nums.length ; i++) {
sum = sum+i;
}
System.out.println("总和为:"+sum);
三种初始化
-
静态初始化
-
int [] a = {1,2,3}; Man[] mans = {new Man(1,1),new Man(2,2)}
-
动态初始化
-
int[] a = new int[2]; a[0] = 1; a[1] = 2;
-
数组的默认初始化
-
数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。
-
//静态初始化:创建+赋值 int [] a = {1,2,3,4,5,6,7}; //动态初始化:包含默认初始化 int [] b = new int[10]; b[0] = 10; System.out.println(b[0]); System.out.println(b[1]); System.out.println(b[2]); System.out.println(b[3]); System.out.println(b[4]); System.out.println(b[5]);
-
数组的四个基本特点
- 其长度是确定的,数组一旦被创建,它的大小就是不可以改变的。
- 其元素必须是相同类型,不允许出现混合类型
- 数组中的元素可以是任何数据类型,包括基本类型和引用类型
- 数组变量引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。
数组边界
-
下标的合法区间:[0,length-1],如果越界就会报错;
-
public static void main(String[] args){ int [] a = new int[2]; System.out.println(a[2]); }
-
ArraylndexOutOfBoundsException: 数组下标越界异常!
-
小结:
- 数组是相同数据类型(数据类型可以为任意类型)的有序集合
- 数组也是对象。数组元素相当于对象的成员变量
- 数组的长度是确定的,不可变得。如果越界,则报:ArraylndexOutOfBoundsException
3:数组的使用
-
For-Each 循环
-
//定义一个数组 int[] arrays = {1,2,3,4,5}; //打印全部的数组元素 for (int i = 0; i < arrays.length ; i++) { System.out.println(arrays[i]); } System.out.println("============================="); //计算所有元素的和 int sum = 0 ; for (int i = 0; i <arrays.length ; i++) { sum += arrays[i]; } System.out.println("总和为:"+sum); //查找最大元素 int max = arrays[0]; for (int i = 0; i <arrays.length ; i++) { if(arrays[i]> max){ max = arrays[i]; } } System.out.println("最大值为:"+ max); //JDK1.5 没有下标 for (int array:arrays) { System.out.println(array); }
-
数组作方法入参
-
数组作返回值
-
//定义一个数组 int[] arrays = {1,2,3,4,5}; printArray(arrays); } public static void printArray(int[] arrays){ for (int i = 0; i <arrays.length ; i++) { System.out.println(arrays[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; }
4:多维数组
-
多维数组可以看成是数组的数组,比如二维数组就是一个特殊的数组,其中每一个元素都有一个一维数组
-
二维数组
-
int a[][] new int [2][5];
-
解析:二维数组a 可以看成一个两行三列的数组。
-
思考:多维数组的使用?
-
//[4][2] 四行两列 /** * 1,2 array[0] * 2,3 array[1] * 3,4 array[2] * 4,5 array[3] */ int[][] array = {{1,2},{2,3},{3,4},{4,5}}; for (int i = 0; i <array.length ; i++) { for (int j = 0; j <array[i].length ; j++) { System.out.println(array[i][j]); } } } //打印数组元素 public static void printArray(int[] arrays){ for (int i = 0; i <arrays.length ; i++) { System.out.println(arrays[i]+""); }
5:Arrays类
- 数组的工具类java.util.Arrays
- 由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作
- 查看JDK帮助文档
- Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类型进行调用,而“不用”使用对象来调用(注意:是“不用”而不是“不能”)
- 具有以下常用功能:
- 给数组赋值:通过fill方法
- 给数组排序:通过sort方法,按照升序。
- 比较数组:通过equals 方法比较数组中元素值是否相等
- 查找数组元素:通过binarySearch方法对排序好的数组进行二分查找法操作。
冒泡排序
-
冒泡排序无疑是最为出名的排序算法之一,总共有八大排序!
-
冒泡排序的代码还是相当简单的,两层循环,外层冒泡轮数,里层依次比较
-
我们看到嵌套循环,应该立马就可以得出这个算法的时间复杂度为o(n2)
-
思考:如何优化?
-
int[] a = {1,5,6,84,45,66,12,55,69,78,65,44,33}; //调用我们自己写的排序方法以后,返回一个排序后的数组 int[] sort = sort(a); System.out.println(Arrays.toString(sort)); } /** * 冒泡排序 * 1.比较数组中,两个相邻的元素,如果第一个数比第二个数大,我们就交换他们的位置 * 2.每一轮比较,都会产出一个最大的,或者最小的数字 * 3.下一轮则可以少一次排序 * 4.依次循环,直到结束 */ public static int[] sort(int[] array){ //临时变量 int temp = 0; //外层循环,判断我们要走多少次 for (int i = 0; i <array.length-1 ; i++) { //内层循环,比较判断两个数,如果第一个数比第二个数大,则交换位置 for (int j = 0; j <array.length-1-i; j++) { if (array[j+1]>array[j]){ temp = array[j]; array[j] = array[j+1]; array[j+1] =temp; } } } return array; }
6:稀疏数组
-
需求:编写五子棋游戏中,有存盘退出和续上盘的功能
-
分析问题:因为该二维数组的很多值默认值0.因此记录了很多没有意义的数据
-
解决:稀疏数组
-
` //1.创建一个二维数组11*11 0:没有棋子,1:黑棋,2:白棋
int[][] array1 = new int[11][11];
array1[1][2] = 1;
array1[2][3] = 2;
//输出原始数组
System.out.println(“输出原始数组”);
for (int [] ints: array1) {
for (int anInt: ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}//转换为稀疏数组保存 //获取有效值的个数 int sum = 0; for (int i = 0; i <11 ; i++) { for (int j = 0; j < 11; j++) { if (array1[i][j]!=0){ sum++; } } } System.out.println("有效值的个数:"+sum); //2.创建一个稀疏数组的数组 int[][] array2 = new int[sum+1][3]; array2[0][0] = 11; array2[0][1] = 11; array2[0][2] = sum; //遍历二维数组,将非零的值,存放到稀疏数组中 int count = 0; for (int i = 0; i <array1.length ; i++) { for (int j = 0; j <array1[i].length ; j++) { if (array1[i][j]!=0){ count++; array2[count][0] = i; array2[count][1] = j; array2[count][2] = array1[i][j]; } } }
//输出稀疏数组
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.println(“还原”);
//1.读取稀疏数组
int[][] array3 = new int[array2[0][0]][array2[0][1]];//2.给其中的元素还原它的值 for (int i = 1; i <array2.length ; i++) { array3[array2[i][0]][array2[i][1]] = array2[i][2]; } //3.打印 System.out.println("输出还原的数组"); for (int [] ints:array1) { for (int anInt: ints) { System.out.print(anInt+"\t"); } System.out.println(); }`
面向对象编程
java的核心思想就是OOP
1:初识面向对象
1.1:面向过程&面向对象
- 面向过程思想
- 步骤清晰简单,第一步做什么,第二步做什么
- 面对过程适合处理一些较为简单的问题
- 面向对象
- 物以类聚,分类的思维模式,思考问题首先会解决问题需要那些分类,然后对这些分类单独思考。最后,才对某个分类下的细节进行面向过程的思索。
- 面向对象适合处理复杂的问题,适合处理需要多人协作的问题!
- 对于描述复杂的事务,为了从宏观上把握,从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,任然需要面向过程的思路去处理。
1.2:什么是面向对象
- 面向对象编程(Object-Orientend Programming,OOP)
- 面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据
- 抽象
- 三大特性:
- 封装
- 继承
- 多态
- 从认识的角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象
- 从代码运行角度考虑是先有类后有对象。类是对象的模板。
2:方法回顾和加深
- 方法的定义
- 修饰符
- 返回类型
- break:跳出switch,结束循环,和return的区别
- 方法名:注意规范,见名知意
- 参数列表:(参数类型,参数名)
- 异常抛出:【后面详细讲解】
//Demo01类
public class Demo01 {
//main方法
public static void main(String[] args) {
}
/**
* 修饰符 返回值 方法名(...){
* //方法体
* return 返回值;
* }
* return 结束方法
* @return
*/
public String sayHello(){
return "hello,world";
}
public int max(int a, int b ){
//三元运算符
return a>b ? a:b;
}
//数组下标越界:Arrayindexoutofbounds 这也是一个异常
public void readFile(String file)throws IOException{
}
-
方法的调用
-
静态方法
-
//和类一起加载的 public static void a(){ }
-
非静态方法
-
//类实例化之后才存在的 public void b(){ }
-
形参和实参
-
int add = Demo03.add(1, 2);
System.out.println(add);
}
//形式参数
public static int add(int a,int b){
return a+b;
}
-
值传递和引用传递
-
值传递
//值传递 int a = 1; System.out.println(a); //调用change方法,只没有返回值。 Demo04.change(a); System.out.println(a); } //返回值为空 public static void change(int a){ a = 10;
-
引用传递
//引用传递:对象本质还是值传递 Perosn perosn = new Perosn(); System.out.println(perosn.name); Demo05.change(perosn); System.out.println(perosn.name); } public static void change(Perosn perosn){ //perosn是一个对象:指向的 ====> Perosn perosn = new Person();这是一个具体的人,可以改变属性 perosn.name = "张三"; } } //定义了一个Perosn类,有一个属性叫:name。注意:类下的 class Perosn{ String name; }
-
-
this关键字
3:对象的创建分析
3.1:类和对象的关系
- 类是一种抽象的数据类型,它是对某一类事务整体描述/定义,但是并不能代表某一个具体的事务。
- 动物,职务,手机,电脑…
- Person类,Pet类,Car类等,这些类都是用来描述/定义某一类具体的事务应该具备的特点和行为
- 对象是抽象概念的具体实例
- 张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例
- 能够体现出特点,展现出功能的是一个具体的实例,而不是一个抽象的概念
3.2:创建与初始化对象
- 使用new关键字创建对象
- 使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行磨人的初始化以及对类中构造器的调用
- 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有一下两个特点:
- 1.必须和类的名字相同
- 2.必须没有返回类型,也不能写void
- 构造器必须要掌握
//案例
//一个项目应该只存在一个main方法
public class Applicatior {
public static void main(String[] args) {
//类:抽象的,实例化
//类实例化后会返回一个自己的对象
//student对象就是一个
Student zhangsan = new Student();
Student lisi = new Student();
zhangsan.name = "张三";
zhangsan.age = 3;
lisi.name = "李四";
lisi.age = 4 ;
System.out.println(zhangsan.name+zhangsan.age);
System.out.println(lisi.name+lisi.age);
}
}
=============================================
//学生类
public class Student {
//属性:字段
String name;
int age;
//方法
public void study(){
System.out.println(this.name+"在学习");
}
}
## 4:面向对象的三大特性
### 4.1:封装
- 该露的露,该藏的藏
- 我们程序设计要追求“高内聚,低耦合”高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。
- 封装(数据的隐藏)
- 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这成为信息隐藏。
- 记住这句话就够了:属性私有,get/set
```java
public static void main(String[] args) {
/**
* 1.封装的意义:提高程序的安全性,保护数据
* 2.隐藏代码的实现细节
* 3.统一接口
* 4.提高系统的可维护性
*/
Student student = new Student();
student.setName("lisi");
System.out.println(student.getName());
student.setAge(999);
System.out.println(student.getName());
}
--------------------------------------------------------------
public class Student {
//定义一个学生类,属性私有
//名字
private String name;
//学号
private int id;
//性别
private char sex;
//年龄
private int age;
//提供一些可以操作这些私有属性的方法
//提供一些public 的get,set方法
//get 获得这个数据
public String getName(){
return this.name;
}
//set给这个数据设置值
public void setName(String name){
this.name = name;
}
//快速生成alt+insrt
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;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age > 120 || age < 0){
this.age = 3;
}
this.age = age;
}
4.2:继承
- 继承的本质是对某一批类的抽象,从而实现对显示世界更好的建模。
- extands的意思是“扩展”。子类是父类的扩展。
- Java中类只有单继承,没有多继承!
- 继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖,组合,聚合等。
- 继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extands
- 子类和父类之间,从意义上讲应该具有“is a”的关系
- object类
- super
- super调用父类的构造方法,必须在构造方法的第一个
- super必须只能出现在子类的方法或者构造方法中
- super和this不能同事调用构造方法!
- This
- 代表的对象不同
- this:本身调用这个对象
- super:代表父类对象的应用
- 前提
- this:没有继承也可以使用
- super:只能在继承条件才可以使用
- 构造方法
- this();本类的构造
- super();父类的构造
- 方法重写
public class Application {
/**
* 静态方法和非静态的方法区别很大
* 静态方法:方法的调用只和左边,定义的数据类型有关
* 非静态方法:重写
* @param args
*重写:需要有继承关系,子类重写父类的方法
* 1.方法名必须相同
* 2.参数列表必须相同
* 3.修饰符:范围可以扩大 private>protected>public
* 4.抛出的异常:范围可以被缩小,但不能扩大;ClassNotFoundExcetion--->Excetion(大)
*
* 重写,子类的方法和父类的必要一致:方法体不同!
*
* 为什么需要重写:
* 1.父类的功能,子类不一定需要,或者不一定满足!
* Alt + Insert : override;
*
*/
public static void main(String[] args) {
//方法的调用只和左边,定义的数据类型有关
A a = new A();
a.test();
//父类的引用指向了子类
//子类重写了父类的方法
B b = new B();
b.test();
}
=======================================================================
public class A extends B{
//Override 重写
@Override //注解:有功能的注释
public void test() {
System.out.println("A=>test()");
}
=======================================================================
public class B {
public void test(){
System.out.println("B=>test()");
}
}
4.3:多态
即同一方法可以根据发送对象的不同而采用多种不同的行为方式
一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多
多态存在的条件
- 有继承关系
- 子类重写父类方法
- 父类引用指向子类对象
注意:多态是方法的多态,属性没有多态性
public class Application {
/**
* 多态注意事项
* 1.多态是方法的多态,属性没有多态。
* 2.父类和子类,有联系。类型转换异常!ClassCastException
* 3.存在条件:继承关系,方法需要重写,父类引用指向子类对象!
* 那些方法不能被重写?
* 1.static 方法,属于类,它不属于实例;
* 2.final 常量;
* 3.private 方法;
* @param args
*/
public static void main(String[] args) {
//一个对象的实际类型是确定的
//new Student();
//new Person();
//可以指向的引用类型就不确定了,父类的引用指向子类
Student s1 = new Student();
Person s2 = new Student();
Object s3 = new Student();
s2.run();//子类重写父类的方法,执行子类的方法
s1.run();
//对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
((Student) s2).eat();//子类重写了父类的方法,执行子类的方法。这个是强制转换,高转低
s1.eat();
}
---------------------------------------------------------------------
public class Person {
public void run(){
}
}
-------------------------------------------------------------------------
public class Student extends Person{
@Override
public void run() {
System.out.println("Person=>son");
}
public void eat(){
System.out.println("eat");
}
}
-
instanceof(类型转换)引用类型
- 父类引用指向子类
- 把子类转换为父类,向下转型;
- 把父类转换为子类,向下转型;强制转换
- 方便方法的调用,减少重复的代码
-
static
-
public class Person { //2. { System.out.println("匿名代码块儿"); } //1 static{ System.out.println("静态代码块儿"); } //3. public Person(){ System.out.println("构造方法"); } public static void main(String[] args) { Person person01 = new Person(); System.out.println("================="); Person person02 = new Person(); /** * 输出顺序 * 静态代码块儿 * 匿名代码块儿 * 构造方法 * ================= * 匿名代码块儿 * 构造方法 */ } -------------------------------------------------------------- //静态导入包 import static java.lang.Math.random; public class Test { public static void main(String[] args) { System.out.println(random()); }
-
5:抽象类和接口
5.1抽象类
-
abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类
-
抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类
-
抽象类,不能使用new关键字来创建对象,它是用来让子类继承的
-
抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
-
子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类
-
//abstract 抽象类:类 extends : 单继承 (接口可以多继承) public abstract class Action { //约束 ~ 有人帮我们实现 //abstract 抽象方法,只有方法名字,没有方法的实现 public abstract void doSometing(); //1.抽象类不能new出来,只能靠子类实现它,约束! //2.抽象类可以有一些正常的方法 //3.抽象方法必须在抽象类中 //抽象的抽象 } ------------------------------------------------------- //抽象类的所有方法,继承了它的子类,都必须要实现它的方法 public class A extends Action{ @Override public void doSometing() { }
5.2:接口
- 普通类:只有具体实现
- 抽象类:具体实现和规范(抽象方法)都有
- 接口:只有规范
- 接口就是规范,定义的是一组规则,体现了现实世界中“如果你是…则必须能…”的思想。如果你是天使,则必须能飞。如果你是汽车,则必须能跑。
- 接口的本质是契约,就像我们人间的法律一样,制定好后大家都能遵守
- OO的精髓,是对对象的抽象,最能体现这一点的就是接口。
- 声明类的关键字是class,声明接口的关键字是interface
接口 public interface UserService { //常量 public static final int AGE = 99; //接口中的所有定义的方法其实都是抽象的 public void add(String name); void delete(String name); void update(String name); void query(String name); } ------------------------------------------------- public interface TimeService { void timer(); } ---------------------------------------------------------------------- 实现接口 // //类 可以实现接口 implements // public class UserServiceImpl implements UserService,TimeService { @Override public void add(String name) { } @Override public void delete(String name) { } @Override public void update(String name) { } @Override public void query(String name) { } @Override public void timer() { } /** * 1.约束 * 2.定义一些方法,让不同的人实现 * 3.public abstract * 4.public static final * 5.接口不能被实例化,接口中没有构造方法 * 6.接口可以实现多个接口 * 7.implements必须要重写接口中的方法 */
6:内部类及OOP实战
6.1:内部类
- 内部类就是在一个类的内部在定义一个类,比如,A类中定义一个B类,那么B类相对于A类来说就是内部类,而A类相对于B类来说就是外部类。
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类
public class Outer {
private int id = 10;
public void out(){
System.out.println("这是外部类方法");
}
class Inner{
public void in(){
System.out.println("这是内部类");
}
//获得外部类的私有属性
public void getID(){
System.out.println(id);
}
}
}
----------------------------------------------------------------------------
public class Application {
public static void main(String [] args){
//new
Outer outer = new Outer();
//通过这个外部类来实例化内部类
Outer.Inner inner = outer.new Inner();
inner.getID();
}
}
--------------------------------------------------------------------------
/一个Java类中可以有多个class类,但是只能有一个public class类
public class Outer {
//局部内部类
public void method(){
class Inner{
public void in(){
}
}
}
}
----------------------------------------------------------------------------
public class Test {
public static void main(String[] args) {
//没有名字初始化类
new Apple().eat();
UserService userService = new UserService(){
@Override
public void hello() {
}
};
}
}
class Apple{
public void eat(){
System.out.println("1");
}
}
四:异常机制(Error与Exception)
1:什么是异常
- 实际工作中,遇到的情况不可能是非常完美的。比如:你写的某个模块,用户输入不一定符合你的要求,你的程序要打开某个文件,这个文件可能不存在或者文件格式不对,你要读取数据库的数据,数据可能是空的等。我们的程序在跑着,内存或硬盘可能满了,等等
- 软件在运行过程中,非常可能遇到刚刚提到的这些异常问题,我们叫异常,英文是:Exception,意识是例外。这些,例外的情况或者叫异常,怎么让我们写的程序作出合理的处理,而不至于程序崩溃。
- 异常指程序运行中出行的不齐而齐的各种情况:如:文件找不到,网络连接失败,非法参数等。
- 异常发生在程序运行期间,它影响了正常的程序执行流程。
2:简单分类异常
- 要理解java异常处理是如何工作的,你需要掌握以下三种类型的异常
- 检查性异常:最具代表性的检查异常是用户错误或问题引起的异常。这是程序员无法预见的。例如要打开一个不存在的文件时,一个异常就发生了,这些异常在编译时候不能被简单的忽略
- 运行时异常:运行时异常是可能被程序员避免的异常,与检查性异常相反,运行时异常可以在编译时候被忽略。
- 错误:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
2:异常的体系结构
2.1 Error
- Error类对象由Java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关
- Java虚拟机运行错误(Virtual MachineError),当JVM不在有继续执行操作所需的内存资源时,将出现OutOfMemoryError。这些异常发生时,java虚拟机(JVM)一般会选择线程终止;
- 还有发生在虚拟机试图执行应用时,如类定义错误(NoClassDefFoudError),连接错误(LinkageError)。这些错误是不可查的,因为他们在应用程序的控制和处理能力之外,而且大多数程序运行时不允许出现的状况。
2.2 Exception
- 在Exception分支中有一个重要的子类RuntimeException(运行时异常)
- ArraylndexOutOfBoundsException(数组下标越界)
- NullPointerException(空指针异常)
- AritheticException(算术异常)
- MissingResourceException(丢失资源)
- ClassNotFoundException(找不到类)等异常,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。
- 这些异常一般是由程序逻辑错误引起的,程序应该是从逻辑角度尽可能避免这类异常的发生;
- Error和Exception的区别:Error通常是灾难性的致命错误,是程序无法控制和处理的,当出现这些异常时,java虚拟机(JVM)一般会选择终止线程;Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。
3:Java异常处理机制
3.1异常处理机制
- 抛出异常
- 捕获异常
- 异常处理五个关键字
- try,catch,finally,throw,throws
4:处理异常
int a = 1 ;
int b = 0;
try { //监控区
System.out.println(a/b);
}catch (ArithmeticException e){ //catch 捕获异常
System.out.println("程序出现异常,变量不能为0");
}finally { //处理善后工作
System.out.println("finally");
}
//finally 可以不要,假设IO,资源,关闭!
}
---------------------------------------------------------------------------
public static void main(String[] args) {
int a = 1 ;
int b = 0;
//假设要捕获多个异常,从小到大去捕获!Ctrl+alt+T
try { //监控区
System.out.println(a/b);
}catch (Error e){ //catch(想要捕获的异常类型!) 捕获异常,也可以捕获多个异常
System.out.println("Error");
}catch(Exception e){
System.out.println("Exception");
}catch(Throwable t){
System.out.println("Throwable");
} finally { //处理善后工作
System.out.println("finally");
}
//finally 可以不要,假设IO,资源,关闭!
}
----------------------------------------------------------------------------
public static void main(String[] args) {
int a = 1 ;
int b = 0;
//假设要捕获多个异常,从小到大去捕获!Ctrl+alt+T
try { //监控区
System.out.println(a/b);
}catch (Error e){ //catch(想要捕获的异常类型!) 捕获异常,也可以捕获多个异常
//e.printStackTrace();//打印错误的栈信息
//手动结束异常
System.exit(0);
}finally { //处理善后工作
System.out.println("finally");
}
//finally 可以不要,假设IO,资源,关闭!
}
}
----------------------------------------------------------------------------
public static void main(String[] args) {
try {
new demo12().test(1,0);
} catch (ArithmeticException e) {
e.printStackTrace();
}
}
public void test(int a , int b) throws ArithmeticException{
if (b==0){
throw new ArithmeticException();
}
System.out.println(a/b);
}
/**
* //假设要捕获多个异常,从小到大去捕获!Ctrl+alt+T
* try { //监控区
* //主动抛出异常 thorw thorws
* if (b==0){
* throw new ArithmeticException();
* }
* }catch (Error e){ //catch(想要捕获的异常类型!) 捕获异常,也可以捕获多个异常
* System.out.println("Error");
* }catch(Exception e){
* System.out.println("Exception");
* }catch(Throwable t){
* System.out.println("Throwable");
* } finally { //处理善后工作
* System.out.println("finally");
* }
*
* //finally 可以不要,假设IO,资源,关闭!
* }
*/
5:自定义异常
- 使用java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常。用户自定义异常类,只需要继承Exception即可。
- 在程序中使用自定义异常类,大体可分为一下几个步骤:
- 1.创建自定义异常类
- 2.在方法中通过thorw关键字抛出异常对象
- 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过thorws关键字致命要抛出给方法调用者的异常,继续进行下一步操作。
- 在出现异常方法的调用者中捕获并处理异常。
public class MyException extends Exception {
//传递数字>10
private int detail;
public MyException(int a){
this.detail = a;
}
//toString: 异常的打印信息
@Override
public String toString(){
return "MyException{"+"detail="+detail +'}';
}
}
---------------------------------------------------------------------------
public class Test {
//可能会存在异常的方法
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(1);
} catch (MyException e) {
//可以增加一些异常处理的代码块儿
System.out.println("MyException=>"+e);
}
}
}
6:总结
6.1实际应用中的经验总结
- 处理运行时异常时,采用逻辑去合理规避同事辅助try-catch处理
- 在多重catch块后面,可以加上一个catch(Exception)来处理可能会被遗漏的异常
- 对于不确定的代码,也可以加上try-catch,处理潜在的异常
- 尽量去处理异常,切记只是简单的调用printStackTrace()去打印输出
- 具体如何处理异常,要根据不同的业务需求和异常类型去决定
- 尽量添加finally语句块去释放占用的资源