视频地址: 狂神说Java基础视频
Markdown学习
二级标题
“## 空格”
三级标题
“### 空格”
四级标题
“#### 空格”
字体
HelloWorld
斜体 :两侧加一个*
HelloWorld
加粗 :两侧加两个*
HelloWorld
斜体加粗:两侧加三个*
HelloWorld
划线:两侧加两个~~
引用
选择狂神说
分割线
图片
英文输入法下 !+[]+()
超链接
英文输入法下 []+()
列表
有序列表
1.空格
- A
- B
无序列表
-空格
预科
什么是计算机
- 名称: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
- 记住安装路径
- 配置环境变量
1.我的电脑-》属性-》系统高级设置-》环境变量
2.系统变量 新建–> JAVA_HOME 输入对应的jdk安装路径
3.path变量–>% JAVA_HOME%\bin - 测试是否成功 cmd–>Java -version
Java基础
注释
-
平时我们编写代码,在代码量比较少的时候,我们还可以看懂自己写的,但是当项目结构一旦复杂起来,我们就需要用到注释了。
-
注释并不会被执行,是给我们写代码的人看的
-
书写注释是一个非常好的习惯
-
平时写代码一定要注意规范。
java中的注释有三种:
-
单行注释
-
多行注释
-
文档注释
public class HelloWorld { public static void main(String[] args) { //单行注释 // // 输出一个Hello,World System.out.println("Hello world");//hello //123123123 //123123 //多行注释:可以注释一段文字 /*注释*/ /* 我是多行注释 */ //JavaDoc:文档注释/** */ /** */ } }
标识符和关键字
-
关键字
-
Java 所有的组成部分都需要名字。类名,变量名以及方法名都被称为标识符。
-
所有的标识符都应该以字母(A-Z或者a-z),美元符号($),或者下划线(-)开始
-
首字符之后可以是字母(A-Z或者a-z),美元符号($),或者下划线(-)或数字的任何字符组合
-
不能使用关键字作为变量名或方法名
-
标识符是大小写敏感的
-
合法标识符距离: age,$salary,_value, _1_value
-
非法标识符举例: 123abc,-salary,#abc
-
可以使用中文命名,但一般不建议这样去使用,也不建议用拼音,很low
package base; public class Demo01 { public static void main(String[] args) { String 王者荣耀="百星王者"; //String 王者荣耀="倔强青铜"; System.out.println(王者荣耀); //大小写十分敏感 String Man="qinjiang"; String man="qinjiang"; String 名字="qinjiang"; String Ahello="qinjiang"; String hello="qinjiang"; String $hello="qinjiang"; String _hello="qinjiang"; String _1="qinjiang"; //String class="qinjiang"; //String 1hello="qinjiang"; //String #hello="qinjiang"; //String *hello="qinjiang"; } }
数据类型
-
强类型语言
- 要求变量的使用严格符合规定,所有变量都必须先定义后才能使用
-
弱类型语言
-
Java的数据类型分为两大类
- 基本类型(primitive type)
- 引用类型(reference type)
package base;
public class Demo02 {
public static void main(String[] args) {
//八大基本数据类型
//整数
int num1=10;//最常用
byte num2=20;
short num3=30;
long num4=30L;//Long类型要在数字后面加个L
//小数;浮点数
float num5=50.1F;//float类型要在数字后面加个F
double num6=3.1415926535;
//字符
char name='A';
//字符串String不是关键字,类
//String namea="王润泽";
//布尔值:是,非
boolean flag=true;
//boolean flag=flase;
}
}
package base;
public class Demo03 {
public static void main(String[] args) {
//整数拓展 进制 二进制0b 十进制 八进制0 十六进制0x
int i=10;
int i2=010;//八进制0
int i3=0x11;//十六进制0x 0~9 A~F 16
System.out.println(i);
System.out.println(i2);
System.out.println(i3);
System.out.println("============================================");
//============================================
//浮点数拓展? 银行业务怎么表示? 钱
//BigDecimal 数学工具类
//============================================
//float 有限 离散 舍入误差 大约 接近但不等于
//double
//最好完全使用浮点数进行比较
//最好完全使用浮点数进行比较
//最好完全使用浮点数进行比较
float f=0.1f;//0.1
double d=1.0/10;//0.1
System.out.println(f==d);//false
System.out.println(f);
System.out.println(d);
float d1=231313131313131313f;
float d2=d1+1;
System.out.println(d1==d2);//true
//======================================
//字符拓展?
//======================================
char c1='a';
char c2='中';
System.out.println(c1);
System.out.println((int)c1);//强制转换
System.out.println(c2);
System.out.println((int)c2);//强制转换
//所有的字符本质还是数字
//编码 Unicode 表: (97=a 65=A) 2字节 65536 Excel 2^16=65536
//U0000 UFFFF
char c3='\u0061';
System.out.println(c3);//a
//转移字符
// \t制表符
//\n 换行
//...
System.out.println("Hello\nWorld");
//
System.out.println("=============================");
String sa =new String("hello world");
String sb =new String("hello world");
System.out.println(sa==sb);
String sc="hello world";
String sd="hello world";
System.out.println(sc==sd);
//对象 从内存分析
//布尔值扩展
boolean flag=true;
if(flag==true){}//新手
if(flag){}//老手
//Less is More! 代码要精简易读
}
}
什么是字节
- 位(bit):是计算机内部数据储存的最小单位,11001100是一个八位二进制数。
- 字节(byte):是计算机数据处理的基本单位,习惯上用大写B来表示
- 1B(byte,字节)=8bit(位)
- 字符:是指计算机中使用的字母,数字,字和符号
- 1bit表示一位
- 1Byte表示一个字节 1B=8b.
- 1024B=1kB
- 1024KB=1M
- 1024M=1G
类型转换
-
由于Java是强类型语言,所以要进行有些运算的时候,需要用到类型转换。
低------------------------------------------------------------------------------------------------->高
byte,short, char–>int–>long–>float–>double
-
运算中,不同类型的数据先转化为同一类型,然后进行运算。
-
强制类型转换
-
自动类型转换
package base; public class Demo04 { public static void main(String[] args) { int i=128; //byte b=(byte)i;//内存溢出 double b=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); } }
package base; public class Demo05 { public static void main(String[] args) { //操作比较大的数的时候,注意溢出问题 //Jdk7新特性,数字之间可以用下划线分割 int money=10_0000_0000; System.out.println(money); int years=20; int total= money*years; System.out.println(total);//1474836480,计算的时候溢出了 long total2=money*years; System.out.println(total2);//默认是int,转换之前已经存在问题了 long total3=money*((long)years);//先把一个数转换为long, System.out.println(total3); //L用大写的规范 l } }
变量
- 变量是什么:就是可以变化的量!
- Java是一种强类型语言,每个变量都必须声明其类型。
- Java变量是程序中最基本的储存单元,其要素包括变量名,变量类型和作用域。
type varName [=value] [{,varName[=value]}];
//数据类型 变量名 =值;可以使用逗号隔开来声明多个同类型变量。
- 注意事项:
- 每个变量都有类型,类型可以是基本类型,也可以是引用类型。
- 变量名必须是合法的标识符。
- 变量声明是一条完整的语句,因此每一个声明都必须以分号结束
变量作用域
-
类变量
-
实例变量
-
局部变量
package base; public class Demo07 { //类变量 static static double salary=2500; //属性:变量 //实例变量:从属于对象:如果不自行初始化,这个类型的默认值 0 0.0 u0000 //布尔值:默认是false //除了基本类型,其余的默认值都是null; String name; int age; //main方法 public static void main(String[] args) { //局部变量:必须声明和初始化值 int i=10; System.out.println(i); //变量类型 变量名字==new Demo07(); Demo07 demo07=new Demo07(); System.out.println(demo07.age); System.out.println(demo07.name); //类变量 static System.out.println(salary); } //其他方法 public void add(){ } }
变量的命名规范
- 所有变量,方法,类名:见名知意
- 类成员变量: 首字母小写和驼峰原则:mouthSalary 除了第一个单词以外,后面的单词首字母大写 lastname lastName
- 局部变量:首字母小写和驼峰原则
- 常量:大写字母和下划线:MAX_VALUE
- 类名:首字母大写和驼峰原则:Man,GoodMan
- 方法名:首字母小写和驼峰原则:run(),runRun()
常量
-
常量(Constant):初始化(initialize)后不能再改变值!不会变动的值。
-
所谓常量可以理解成一种特殊的变量,它的值被设定后,在程序运行过程中不允许被改变。
final 常量名=值;
final double PI=3.14;
-
变量名一般使用大写字符。
运算符
-
java语言支持如下运算符: 优先级()
-
算数运算符:+,—,*,/,++,——
-
赋值运算符=
-
关系运算符:>,<,>=,<=,==,!= instanceof
package operator; public class Demo01 { public static void main(String[] args) { //二元运算符 //ctrl+D: 复制当前行到下一行 int a=10; int b=20; int c=25; int d=25; System.out.println(a+b); System.out.println(a-b); System.out.println(a*b); System.out.println(a/(double)b); } }
package operator; public class Demo02 { public static void main(String[] args) { long a=123123123123123L; int b=123; short c=10; byte d=8; System.out.println(a+b+c+d);//Long System.out.println(b+c+d);//Int System.out.println(c+d);//Int } }
package operator; public class Demo03 { public static void main(String[] args) { //关系运算符的返回结果: 正确,错误 布尔值 //if int a=10; int b=20; int c=21; //取余,模运算 System.out.println(c%a);//c/a 21/10=2.....1 System.out.println(a>b); System.out.println(a<b); System.out.println(a==b); System.out.println(a!=b); } }
package operator; public class Demo04 { public static void main(String[] args) { //++ --,自增,自减 一元运算符 int a=3; int b=a++;//执行完这行代码后,先给b赋值,再自增 // a=a+1; System.out.println(a); // a=a+1 int c=++a;//执行完这行代码前,先自增,再给b赋值 System.out.println(a); System.out.println(b); System.out.println(c); //幂运算 2^3 2*2*2 =8 很多运算我们会使用一些工具类来操作 double pow=Math.pow(3,2); System.out.println(pow); } }
-
逻辑运算符:&&,||,!
package operator; //逻辑运算符 public class Demo05 { public static void main(String[] args){ //与(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); System.out.println(c); } }
-
位运算符:&,|,^,~,>>,<<,>>>(了解!!!)
package operator; public class Demo06 { public static void main(String[] args) { /* A= 0011 1100 B= 0000 1101 ----------------------- A&B=0000 1100 A|B=0011 1101 A^B=0011 0001 ~B=1111 0010 2*8=16 2*2*2*2 效率极高!!! << *2 >> /2 0000 0000 0 0000 0000 1 0000 0010 2 0000 0011 3 0000 0100 4 0000 1000 8 0001 0000 16 */ System.out.println(2<<3); } }
-
条件运算符?:
package operator; //三元运算符 public class Demo08 { public static void main(String[] args) { // x ? y : z //如果x==true,则结果为y,否则结果为z int score =80; String type=score<60?"不及格":"及格";//必须掌握 //if System.out.println(type); } }
-
拓展赋值运算符:+=,—=,*=,/=
package operator; public class Demo07 { public static void main(String[] args) { int a= 10; int b= 20; a+=b;//a=a+b a-=b;//a=a-b System.out.println(a); //字符串连接符 + ,String System.out.println(""+a+b); System.out.println(a+b+""); } }
包机制
-
为了更好组织类,java提供了包机制,用于区别类名的命名空间
-
包语句的语法格式为:
package pkg1[.pkg2[.pkg3…]];
-
一般利用公司域名倒置作为包名; www.baidu.com com.baidu.www
-
为了能使用某一个包的成员,我们需要在java程序中明确导入该包。使用"import"语句可完成此功能
import package1[.package2…].(classname|*);
JavaDoc
-
Javadoc命令是用来生成自己API文档的
-
参数信息
-
@author作者名
-
@version版本号
-
@since 指明需要最早使用的jdk版本
-
@param参数名
-
@return返回值情况
-
@throws异常抛出情况
package com.kuang.base; /** * @author Kuangshen * @version 1.0 * @since 1.8 */ public class Doc { String name; /** * @author Kuangshen * @param name * @return * @throws Exception */ public String test(String name) throws Exception{ return name; } }
Java流程控制
Scanner对象
-
之前我们学习的基本语法中我们并没有实现程序和人的交互,但是Java给我们提供了这样一个工具类,我们可以获取用户的输入。java.util.Scanner是Java5的新特征,我们可以通过Scanner类来获取用户的输入。
-
基本语法
Scanner s=new Scanner(System,in);
-
通过Scanner类的next()与nextLine()方法获取输入的字符串,在读取前我们一般需要使用hasNext()与hasNextLine()判断是否还有输入的数据。
-
next():
- 一定要读取到有效字符后才可以结束输入。
- 对输入有效字符之前遇到的空白,next()方法会自动将其去掉。
- 只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。
- next()不能得到带有空格的字符串。
package com.kuang.scanner;
import java.util.Scanner;
public class Demo01 {
public static void main(String[] args) {
//创建一个扫描器对象,用与接受键盘数据
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();
}
}
- nextLine():
- 以Enter为结束符,也就是说nextLine()方法返回的是输入回车之前的所有字符。
- 可以获得空白。
package com.kuang.scanner;
import java.util.Scanner;
public class Demo02 {
public static void main(String[] args) {
//从键盘接收数据
Scanner scanner=new Scanner(System.in);
System.out.println("使用nextLine方式接受:");
//判断是否还有输入
if(scanner.hasNextLine()){
String str=scanner.nextLine();
System.out.println("输入的内容为"+str);
}
scanner.close();
}
}
package com.kuang.scanner;
import java.util.Scanner;
public class Demo03 {
public static void main(String[] args) {
//从键盘接收数据
Scanner scanner=new Scanner(System.in);
System.out.println("请输入数据:");
String str=scanner.nextLine();
System.out.println("输入的内容为"+str);
scanner.close();
}
}
package com.kuang.scanner;
import java.util.Scanner;
public class Demo04 {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
//从键盘接受数据
int i=0;
float f=0.0f;
System.out.println("请输入整数: ");
//如果...那么
if(scanner.hasNextInt())
{
i=scanner.nextInt();
System.out.println("整数数据: "+i);
}
else{
System.out.println("你输入的不是整数数据! ");
}
System.out.println("请输入小数: ");
//如果...那么
if(scanner.hasNextFloat())
{
f=scanner.nextFloat();
System.out.println("小数数据: "+f);
}
else{
System.out.println("你输入的不是小数数据! ");
}
scanner.close();
}
}
package com.kuang.scanner;
import java.util.Scanner;
public class Demo05 {
public static void main(String[] args) {
//我们可以输入多个数字,并求其总和与平均数,每输入一个数字用回车确认,通过输入非数字来结束输入并输出执行结果。
Scanner scanner=new Scanner(System.in);
//和
double sum=0;
//计算输入了多少个数字
int m=0;
//通过循环判断是否还有输入,并在里面对每一次进行求和统计
while(scanner.hasNextDouble()){
double x=scanner.nextDouble();
m=m+1;//m++
sum=sum+x;
System.out.println("你输入了第"+m+"个数据,然后当前结果sum:"+sum);
}
System.out.println(m+ "个数的和为"+sum);
System.out.println(m+"个数的平均值是"+(sum/m));
scanner.close();
}
}
顺序结构
-
JAVA的基本结构就是顺序结构,除非特别指明,否则就按照顺序一句一句执行。
-
顺序结构是最简单的算法结构。
-
语句与语句之间,框与框之间是按从上到下的顺序进行的,它是由若干个依次执行的处理步骤组成的,它是任何一个算法都离不开的一种基本算法结构。
package com.kuang.struct; public class ShunXuDemo { public static void main(String[] args) { System.out.println("hello1"); System.out.println("hello2"); System.out.println("hello3"); System.out.println("hello4"); System.out.println("hello5"); } }
选择结构
- if单选择结构
- if双选择结构
- if多选择结构
- 嵌套的if结构
- switch多选择结构
if单选择结构
-
我们很多时候需要去判断一个东西是否可行,然后我们才去执行,这样一个过程在程序中用if语句来表示
-
语法:
if(布尔表达式){
//如果布尔表达式为true将执行的语句
}
package com.kuang.struct;
import java.util.Scanner;
public class IfDemo01 {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
System.out.println("请输入内容");
String s= scanner.nextLine();
//eqaus:判断字符串是否相等
if(s.equals("Hello")){
System.out.println(s);
}
System.out.println("End");
scanner.close();
}
}
if双选择结构
- 那现在有个需求,公司要收购一个软件,成功了,给人支付100万元,失败了,自己找人开发。这样的需求用一个if就搞不定了,我们需要有两个判断,需要一个双选择结构,所以就有了if-else结构。
- 语法
if(布尔表达式){
//如果布尔表达式的值为true
}else{
//如果布尔表达式的值为false
}
package com.kuang.struct;
import java.util.Scanner;
public class IfDemo02 {
public static void main(String[] args) {
//考试分数大于60分就是及格,小于60分就不及格。
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){
//如果布尔表达式1的值为true执行代码
}else if(布尔表达式2){
//如果布尔表达式2的值为true执行代码
}else if(布尔表达式3){
//如果布尔表达式3的值为true执行代码
}else{
//如果以上布尔表达式的值都不为true执行代码
}
package com.kuang.struct; import java.util.Scanner; public class IfDemo03 { public static void main(String[] args) { //考试分数大于60分就是及格,小于60分就不及格。 Scanner scanner=new Scanner(System.in); /* if语句至多有1个esle语句,else语句在所有的if else语句之后。 if语句可以有若干个else if语句,它们必须在else语句之前。 一旦其中一个else if语句检测为true,其他的else if以及else语句都将跳过执行。 */ 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结构
-
使用嵌套的if···else语句是合法的。也就是说你可以在另一个if或者else if语句中使用if或else if语句。你可以像if语句一样嵌套else if···else。
-
语法:
if(布尔表达式1){
//如果布尔表达式1的值为true执行代码
if(布尔表达式2){
//如果布尔表达式2的值为true执行代码
}
}
-
思考?我们需要寻找一个数,在1~100之间。
switch多选择结构
-
多选择结构还有一个实现方式就是switch case语句。
-
switch case语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支。
-
switch语句中的变量类型可以是:
- byte,short,int,或者char。
- 从Java SE 7开始
- switch支持字符串String类型了
- 同时case标签必须为字符串常量或字面量。
-
语法:
switch(expression){
case value:
//语句
break;//可选
case value:
//语句
break;//可选
//你可以有任意数量的case语句
default: //可选
//语句
}
package com.kuang.struct; public class SwitchDemo01 { public static void main(String[] args) { //case 穿透 //switch 匹配一个具体的值 char grade='A'; 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("未知等级"); } } }
package com.kuang.struct;
public class SwitchDemo02 {
public static void main(String[] args) {
String name="狂神";
//JDK7的新特性,表达式结果可以是字符串!!!
//字符的本质还是数字
//反编译 java---class(字节码文件)-----反编译(IDEA)
switch(name){
case"秦疆":
System.out.println("秦疆");
break;
case"狂神":
System.out.println("狂神");
break;
default:
System.out.println("弄啥嘞!");
}
}
}
循环结构
- while循环
- do…while循环
- for循环
- 在Java5中引入了一种主要用于数组的增强型for循环。
while循环
-
while是最基本的循环,它的结构为:
while(布尔表达式){
//循环内容
}
-
只要布尔表达式为true,循环就会一值执行下去。
-
我们大多数情况是会让循环停止下来的,我们需要一个让表达失败的方式来结束循环。
-
少部分情况需要循环一直执行,比如服务器的请求响应监听等。
-
循环结构一直为true就会造成无限循环[死循环],我们正常的业务编程中应该尽量避免死循环。会影响程序性能或者造成程序卡死崩溃!
-
思考:计算1+2+3+···100=?
package com.kuang.struct;
public class WhileDemo01 {
public static void main(String[] args) {
//输出1~100
int i=0;
while(i<100){
i++;
System.out.println(i);
}
}
}
package com.kuang.struct;
public class WhileDemo02 {
public static void main(String[] args) {
//死循环
while(true){
//等待客户端连接
//定时检查
//...
}
}
}
package com.kuang.struct;
public class WhileDemo03 {
public static void main(String[] args) {
//计算1+2+3+···100=?
//高斯的故事
int i = 0;
int sum = 0;
while (i <= 100) {
sum = sum + i;
i++;
}
System.out.println(sum);
}
}
do…while循环
-
对于while语句而言,如果不满足条件,则不能进入循环。但有时候我们需要即使不满足条件,也至少执行一次。
-
do…while循环和while循环相似,不同的是,do…while循环至少会执行一次。
do{
//代码语句
}while(布尔表达式);
-
While和do…While的区别:
- while先判断后执行。dowhile是先执行后判断!
- Do…while总是保证循环体会被至少执行一次!这是他们的主要差别。
package com.kuang.struct;
public class DoWhileDemo01 {
public static void main(String[] args) {
int i = 0;
int sum = 0;
do {
sum = sum + i;
i++;
} while (i <= 100);
System.out.println(sum);
}
}
package com.kuang.struct;
public class DOWhileDemo02 {
public static void main(String[] args) {
int a=0;
while(a<0){
System.out.println(a);
a++;
}
System.out.println("========================");
do {
System.out.println(a);
a++;
}while(a<0);
}
}
For循环
-
虽然所有循环结构都可以用while或者do…while表示,但Java提供了另一种语句——for循环,使一些循环结构变得更加简单。
-
for循环语句是支持迭代的一种通用结构,是最有效,最灵活的循环结构。
-
for循环执行的次数是在执行前就确定的。语法格式如下:
for(初始化;布尔表达式;更新){
//代码语句
}
-
练习1:计算0到100之间的奇数和偶数的和。
-
练习2:用while或for循环输出1-1000之间能被5整除的数,并且每行输出3个
-
练习3:打印九九乘法表
package com.kuang.struct; public class ForDemo01 { public static void main(String[] args) { int a = 1;//初始化条件 while (a <= 100) {//条件判断 System.out.println(a);//循环体 a += 2;//迭代 } System.out.println("while循环结束!"); //初始化条件/条件判断//迭代 for(int i=1;i<=100;i++){ System.out.println(i); } System.out.println("for循环结束!"); /* 关于for循环有以下几点说明: 最先执行初始化步骤,可以声明一种类型,但可初始化一个或者多个循环控制变量,也可以是空语句。 然后,检测布尔表达式的值,如果为true,循环体被执行,如果为false,循环终止,开始执行循环体后面的语句。 执行一次循环后,更新循环控制变量(迭代因子控制循环变量的增减)。 再次检测布尔表达式,循环执行上面的过程。 */ //死循环 for(;;){ } } }
package com.kuang.struct;
public class ForDemo02 {
public static void main(String[] args) {
//计算0到100之间的奇数和偶数的和。
int oddSum=0;
int evenSum=0;
for (int i = 0; i < 100; i++) {
if(i%2!=0){//奇数
oddSum+=i;//oddSum=oddSum+i;
}else{//偶数
evenSum+=i;
}
}
System.out.println("奇数的和"+oddSum);
System.out.println("偶数的和"+evenSum);
}
}
package com.kuang.struct;
public class ForDemo03 {
public static void main(String[] args) {
//用while或for循环输出1-1000之间能被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();
//System.out.println("\n");
}
}
//println 输出完会换行
//print 输出完不会换行
}
}
package com.kuang.struct;
/*
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
*/
public class ForDemo04 {
public static void main(String[] args) {
//打印九九乘法表
//1.我们先打印第一列,这个大家应该都会
//2.我们把固定的1再用一个循环包起来
//3.去掉重复项:i<=j
//4.调整样式
for (int j = 1; j <= 9; j++) {
for (int i = 1; i <= j; i++) {
System.out.print(i+"*"+j+"="+(j*i)+"\t");
}
System.out.println();
}
}
}
增强for循环
-
这里我们先只是见一面,做个了解,之后数组我们重点使用
-
Java5引入了一种主要用于数组或集合的增强型for循环。
-
Java增强for循环语法格式如下:
for(声明语句:表达式){
//代码句子
}
-
声明语句:声明新的局部变量,该变量的类型必须和数组元素的类型匹配。其作用域限定在循环语句块,其值与此时数组元素的值相等。
-
表达式:表达式是要访问的数组名,或者是返回值为数组的方法。
package com.kuang.struct;
public class ForDemo05 {
public static void main(String[] args) {
int[] numbers={10,20,30,40,50};//定义了一个数组
for(int i=0;i<5;i++){
System.out.println(numbers[i]);
}
System.out.println("=================");
//遍历数组的元素
for(int x:numbers){
System.out.println(x);
}
}
}
break continue
-
break在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环,不执行循环中剩余的语句。(break语句也在switch语句中使用)
-
continue语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定。
-
关于goto关键字
-
goto关键字很早就在程序设计语言中出现,尽管goto仍是Java的一个保留字,但并未在语言中得到正式使用;Java没有goto,然而,在break和continue这两个关键字上,我们仍然能看出一些goto的影子···带标签的break和continue。
-
“标签"是指后面跟一个冒号的标识符,例如:label:
-
对Java来说唯一用到标签的地方是在循环语句之前。而在循环之前设置标签的唯一理由是:我们希望在其中嵌套另一个循环,由于break和continue关键字通常只中断当前循环,但若随同标签使用,他们就会中断到存在标签的地方。
package com.kuang.struct; public class BreakDemo { public static void main(String[] args) { int i=0; while(i<100){ i++; System.out.println(i); if(i==30){ break; } } System.out.println("123"); } }
-
package com.kuang.struct;
public class ContinueDemo {
public static void main(String[] args) {
int i=0;
while(i<100){
i++;
if(i%10==0){
System.out.println();
continue;
}
System.out.print(i);
}
//break在任何循环语句的主体部分,均可用break控制循环的流程。
// break用于强制退出循环,不执行循环中剩余的语句。(break语句也在switch语句中使用)
//
//continue 语句用在循环语句中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定。
}
}
package com.kuang.struct;
public class LabelDemo {
public static void main(String[] args) {
//打印101~150之间所有的质数
//质数是指在大于1的自然数中,除了1和它本身以外不再有其他因素的自然数。
int count=0;
//不建议使用
outer: for(int i=101;i<150;i++){
for(int j=2;j<i/2;j++){
if(i%j==0){
continue outer;
}
}
System.out.print(i+" ");
}
}
}
流程控制练习
package com.kuang.struct;
public class TestDemo {
public static void main(String[] args) {
//打印三角形 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方法详解
何谓方法?
- System.out.println(),那么它是什么呢?
- Java方法是语句的集合,它们在一起执行一个功能。
- 方法是解决一类问题的步骤的有序组合
- 方法包含于类或对象中
- 方法在程序中被创建,在其他地方被引用
- 设计方法的原则:方法的本意是功能块,就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,就是一个方法只能完成一个功能,这样利于我们后期的扩展。
- 回顾:方法的命名规则?
package com.kuang.method;
public class Demo01 {
//main方法
public static void main(String[] args) {
int sum=add(1,2);
System.out.println(sum);
}
//加法
public static int add(int a,int b){
return a+b;
}
}
package com.kuang.method;
public class Demo01 {
//main方法
public static void main(String[] args) {
//实际参数:实际调用传递给他的参数
int sum = add(1, 2);
System.out.println(sum);
// test();
}
//加法
//形式参数,用来定义作用的
public static int add(int a, int b) {
return a + b;
}
public static void test() {
for (int i = 0; i <= 1000; i++) {
if (i % 5 == 0) {
System.out.print(i + "\t");
}
if (i % (5 * 3) == 0) {//每行
System.out.println();
//System.out.println("\n");
}
}
}
}
方法的定义
-
Java的方法类似于其它语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义一个方法包含以下语法:
-
方法包含一个方法和一个方法体,下面是一个方法的所有部分:
-
修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。
-
返回值类型:方法可能会返回值。returnValueType是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType是关键字void。
-
方法名:是方法的实际名称。方法名和参数表共同构成方法签名。
-
参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型,顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
- 形式参数:在方法被调用时用于接受外界输入的数据。
- 实参:调用方法时实际传给方法的数据。
-
方法体:方法体包含具体的语句,定义该方法的功能。
修饰符 返回值类型 方法名(参数类型 参数名){
-
···
方法体
···
return 返回值;
}
方法调用
-
调用方法:对象名,方法名(实参列表)
-
Java支持两种调用方法的方式,根据方法是否返回值来选择。
-
当方法返回一个值的时候,方法调用通常被当做一个值。例如:
int larger =max(30,40);
-
如果方法返回值是void,方法调用一定是一条语句。
System.out.println(“Hello,kuangshen!”);
-
课后拓展了解:值传递(Java)和引用传递
package com.kuang.method;
public class Demo02 {
public static void main(String[] args) {
int max=max(10,10);
System.out.println(max);
}
//比大小
public static int max(int num1,int num2){
int result=0;
if(num1==num2){
System.out.println("num1==num2");
return 0;//终止方法
}
if(num1>num2){
result=num1;
}else{
result=num2;
}
return result;
}
}
方法的重载
-
重载就是在一个类中,有相同的函数名称,但形参不同的函数。
-
方法重载的规则:
- 方法名称必须相同。
- 参数列表必须不同(个数不同,或类型不同,参数排列顺序不同等)。
- 方法的返回值类型可以相同也可以不相同。
- 仅仅返回类型不同不足以成为方法的重载。
-
实现理论:
- 方法名称相同时,编译器会根据调用方法的参数个数,参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错。
package com.kuang.method; public class Demo02 { public static void main(String[] args) { int max=max(10,10); System.out.println(max); } //比大小 public static double max(double num1,double num2){ double result=0; if(num1==num2){ System.out.println("num1==num2"); return 0;//终止方法 } if(num1>num2){ result=num1; }else{ result=num2; } return result; } //比大小 public static int max(int num1,int num2){ int result=0; if(num1==num2){ System.out.println("num1==num2"); return 0;//终止方法 } if(num1>num2){ result=num1; }else{ result=num2; } return result; } }
命令行传参
-
有时候你希望运行一个程序时候再给它消息。这要靠传递命令行参数给main()函数实现。
package com.kuang.method; public class Demo03 { public static void main(String[] args) { //arrg.lengh 数组长度 for (int i = 0; i < args.length; i++) { System.out.println("args["+i+ "]:"+args[i]); } } }
可变参数
-
JDK 1.5开始,Java支持传递同类型的可变参数给一个方法。
-
在方法声明中,在指定参数类型后加一个省略号(···)。
-
一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。
package com.kuang.method; public class Demo04 { public static void main(String[] args) { Demo04 demo04= new Demo04(); demo04.test(0,1,2,3,4,5,6); } public void test(int x,int...i){ System.out.println(i[0]); System.out.println(i[1]); System.out.println(i[2]); System.out.println(i[3]); System.out.println(i[4]); System.out.println(i[5]); } }
package com.kuang.method;
public class Demo04 {
public static void main(String[] args) {
//调用可变参数的方法
printMax(34,3,3,2,56.5);
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 = 0; i < numbers.length; i++) {
if(numbers[i]>result){
result=numbers[i];
}
}
System.out.println("The max value is "+ result);
}
}
递归
- A方法调用B方法,我们很容易理解!
- 递归就是:A方法调用A方法!就是自己调用自己
- 利用递归可以用简单的程序来解决一些复杂的问题。它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模比较小的问题来求解,递归策略只需要少量的程序就可以描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。
- 递归结构包括两个部分:
- 递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。
- 递归体:什么时候需要调用自身方法。
package com.kuang.method;
public class Demo05 {
public static void main(String[] args) {
Demo05 test=new Demo05();
test.test();
}
public void test(){
test();
}
}
package com.kuang.method;
public class Demo06 {
//递归思想
public static void main(String[] args) {
System.out.println(f(5));
}
public static int f(int n){
if(n==1){
return 1;
}else{
return n*f(n-1);
}
}
}
数组
数组的定义
-
数组是相同类型数据的有序集合。
-
数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。
-
其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们。
数组声明创建
-
首先必须声明数组变量,才能在程序中使用数组。下面是声明数组变脸的语法:
dataType[] arrayRefVar; // 首选的方法
或
dataType[]arrayRefVar[]; //效果相同,但不是首选方法
-
Java语言使用new操作符来创建数组,语法如下:
dataType[] arrayRefVar =new dataType[arraySize];
-
数组的元素是通过索引访问的,数组索引从0开始。
-
获取数组长度: arrays.length
!
package com.kuang.Array;
public class ArrayDemo01 {
// 变量的类型 变量的名字 =变量的值;
public static void main(String[] args) {
int [] nums;//1.声明一个数组
nums=new int[10];//2.创建一个数组
//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=sum+nums[i];
}
System.out.println("总和为"+sum);
}
}
内存分析
- Java内存分析:
- 写代码画图分析内存!
三种初始化
-
静态初始化
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= new int[2];
a[0]=1;
a[1]=2;
-
数组的默认初始化
- 数组是引用类型,它的元素相当于类的实例变量,因此数组已经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。
package com.kuang.Array;
public class ArrayDemo02 {
public static void main(String[] args) {
//静态初始化
int[]a={1,2,3,4,5,6,7,8};
System.out.println(a[0]);
for(int i=0;i<a.length;i++){
System.out.println(a[i]);
}
//动态初始化
int[]b=new int [10];
b[0]=10;
b[1]=10;
System.out.println(b[0]);
System.out.println(b[1]);
System.out.println(b[2]);
System.out.println(b[3]);
}
}
数组的四个基本特点
- 其长度是确定的。数组一旦被创建,它的大小就是不可以改变的。
- 其元素必须是相同类型,不允许出现混合类型。
- 数组中的元素可以是任何数据类型,包括基本类型和引用类型。
- 数组变量属于引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。
数组边界
-
下标的合法区间:[0,length-1],如果越界就会报错;
public static void main(String[] args){ int[] a=new int[2]; System.out.println(a[2]); }
-
ArrayIndexOutOfBoundsException: 数组下标越界异常!
-
小结:
- 数组是相同数据类型(数据类型可以为任意类型)的有序集合
- 数组也是对象。数组元素相当于对象的成员变量
- 数组长度的确定的,不可变的。如果越界,则报:ArrayIndexOutoofBounds
package com.kuang.Array;
public class ArrayDemo03 {
public static void main(String[] args) {
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="+sum);
System.out.println("=========");
//查找最大元素
int max= arrays[0];
for(int i=0;i<arrays.length;i++){
if(arrays[i]>max){
max=arrays[i];
}
}
System.out.println("max="+max);
}
}
数组使用
-
普通的For循环
-
For-Each循环
-
数组作方法入参
-
数组作返回值`
package com.kuang.Array; public class ArrayDemo04 { public static void main(String[] args) { int[] arrays ={1,2,3,4,5}; //JDk1.5,没有下标 for (int array : arrays) { System.out.println(array); } // printArray(arrays); int [] reverse =reverse(arrays); printArray(reverse); } //打印数组元素 public static void printArray(int[] arrays){ for(int i=0;i<arrays.length;i++) { System.out.print(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; } }
package com.kuang.Array; public class ArrayDemo04 { public static void main(String[] args) { int[] arrays ={1,2,3,4,5}; //JDk1.5,没有下标 for (int array : arrays) { System.out.println(array); } // printArray(arrays); int [] reverse =reverse(arrays); printArray(reverse); } //打印数组元素 public static void printArray(int[] arrays){ for(int i=0;i<arrays.length;i++) { System.out.print(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; } }
多维数组
-
多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一位数组。
-
二维数组
int a[][]=new int[2][5];
-
解析:以上二维数组a可以看成一个两行五列的数组。
-
思考:多维数组的使用?
num[1][0];
package com.kuang.Array;
public class ArrayDemo05 {
public static void main(String[] args) {
//[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]);
}
}
/*printArray(array[0]);
System.out.println(array.length);
System.out.println(array[0].length);*/
}
//打印数组元素
public static void printArray(int[] arrays) {
for (int i = 0; i < arrays.length; i++) {
System.out.print(arrays[i] + " ");
}
}
}
Arrays类
-
数组的工具类java.util.Arrays
-
由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个·工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作。
-
查看JDK帮助文档
-
Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而“不用”使用对象来调用(注意:是“不用”而不是“不能”)
-
具有以下常用功能:
- 对数组赋值:通过fill方法。
- 对数组排序:通过sort方法,按升序。
- 比较数组:通过equals方法比较数组中元素值是否相等。
- 查找数组元素:通过binarySearch方法能对排序好的数组进行二分查找法操作。
package com.kuang.Array; import java.util.Arrays; public class ArrayDemo06 { public static void main(String[] args) { int[] a = {1, 2, 3, 4, 9090, 312341, 32, 534, 21, 3, 23}; System.out.println(a);//[I@723279cf //打印数组元素 //System.out.println(Arrays.toString(a)); //printArray(a); Arrays.sort(a);//数组进行排序,升序 System.out.println(Arrays.toString(a)); Arrays.fill(a,2,4,0);//数组填充 System.out.println(Arrays.toString(a)); } public static void printArray(int[] a) { for (int i = 0; i < a.length; i++) { if (i == 0) { System.out.print("["); } if (i== a.length-1) { System.out.print(a[i] + "]"); } else { System.out.print(a[i] + ", "); } } } }
冒泡排序
-
冒泡排序无疑是最为出名的排序算法之一,总共有八大排序。
-
冒泡的代码还是相当简单的,两层循环,外层冒泡轮数,里层依次比较,江湖中人人尽皆知。
-
我们看到嵌套循环,应该立马就可以得出这个算法的时间复杂度为O(n2)。
-
思考:如何优化?
package com.kuang.Array; import java.util.Arrays; public class ArrayDemo07 { public static void main(String[] args) { int[]a={1,2,3,46,7,3,865,85}; 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++){ boolean flag=false;//通过flag标识位减少没有意义的比较 //内层循环,比较判断两个数,如果第一个数,比第二个数大,则交换位置 for(int j=0;j< array.length-1;j++){ if(array[j+1]<array[j]){ temp=array[j]; array[j]=array[j+1]; array[j+1]=temp; flag=true; } } if(flag==false) { break; } } return array; } }
稀疏数组
- 需求:编写五子棋游戏中,有存盘退出和续上盘的功能。
- 分析问题:因为该二维数组的很多值是默认值0,因此记录了很多没有意义的数据。
- 解决:稀疏数组
稀疏数组介绍
-
当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组。
-
稀疏数组的处理方式是:
- 记录数组一共有几行几列,有多少个不同值
- 把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模
-
如下图:左边是原始数组,右边是稀疏数组
package com.kuang.Array;
public class ArrayDemo08 {
public static void main(String[] args) {
//1.创建一个二维数组 11*11 0:没有棋子 1:黑棋 2:白棋
int[][] array1 = new int[11][11];
array1[1][2] = 1;
array1[2][3] = 1;
//输出原始的数组
System.out.println("输出原始的数组");
for (int[] ints : array1) {
for (int anInt : ints) {
System.out.print(anInt + "\t");
}
System.out.println();
}
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.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 : array3) {
for (int anInt : ints) {
System.out.print(anInt + "\t");
}
System.out.println();
}
}
}
面向对象编程
面向过程&面向对象
- 面向过程思想
- 步骤清晰简单,第一步做什么,第二步做什么.·····
- 面对过程适合处理一些较为简单的问题
- 面向对象思想
- 物以类聚,分类的思想模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。
- 面向对象适合处理复杂的问题,适合处理需要多人协作的问题!
- 对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。
什么是面向对象
-
面向对象编程(Object-Oriented Programming,OOP)
-
面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据。
-
抽象:编程思想!持续的学习,茅塞顿开!多实践,多测试大脑中的想法!实践出真知~
-
三大特性:
- 封装
- 继承
- 多态
-
从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象
-
从代码运行角度考虑是先有类后有对象。类是对象的模板。
回顾方法及加深
- 方法的定义
- 修饰符
- 返回类型
- break:跳出switch,结束循环和return的区别
- 方法名:注意规范就OK 见名知意
- 参数列表:(参数类型,参数名)···
- 异常输出:疑问,后面讲解
- 方法的调用: 递归
- 静态方法
- 非静态方法
- 形参和实参
- 值传递和引用传递
- this关键字
package com.kuang.oop.demo01;
import java.io.IOError;
import java.io.IOException;
//Demo01 类
public class Demo01 {
//main 方法
public static void main(String[] args) {
}
/*
修饰符 返回值类型 方法名(...){
//方法体
return 返回值;
}
*/
//return 结束方法, 返回一个结果!
public String sayHello(){
return "hello,world";
}
public void print(){
return ;
}
public int max(int a,int b){
return a>b? a : b;//三元运算符!
}
//数组下标越界: Arrayindexoutofbounds
public void readFile(String file) throws IOException{
}
}
package com.kuang.oop.demo01;
public class Demo02 {
public static void main(String[] args) {
//实例化这个类 new
//对象类型 对象名= 对象值
Student student = new Student();
student.say();
}
//和类一起加载的
public static void a(){
b();
}
//类实例化 之后才存在
public void b(){
}
}
package com.kuang.oop.demo01;
//学生类
public class Student {
//非静态方法
public void say(){
System.out.println("学生说话了");
}
}
package com.kuang.oop.demo01;
public class Demo03 {
public static void main(String[] args) {
//实际参数和形式参数的类型要对应!
int add=Demo03.add(1,2);
System.out.println(add);
}
public static int add(int a,int b){
return a+b;
}
}
package com.kuang.oop.demo01;
//值传递
public class Demo04 {
public static void main(String[] args) {
int a=1;
System.out.println(a);
Demo04.change(a);
System.out.println(a);//1
}
//返回值为空
public static void change(int a){
a=10;
}
}
package com.kuang.oop.demo01;
//引用传递:对象,本质还是值传递
//对象,内存!
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);//秦疆
}
public static void change(Person person){
//person是一个对象:指向的--->erson person = new Person();这是一个具体的人,可以改变属性!
person.name="秦疆";
}
}
//定义了一个Person类,有一个属性;name
class Person{
String name;//null
}
类与对象的关系
- 类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物。
- 动物、植物、手机、电脑·····
- Person类、Pet类、Car类等,这些类都是用来描述/定义某一类具体的事物应该具备的特点和行为
- 对象是抽象概念的具体实例
- 张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例。
- 能够体现出特点、展现出功能的是具体的实例,而不是一个抽象的概念。
创建与初始化对象
- 使用new关键字创建对象
- 使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。
- 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:
- 1.必须和类的名字相同
- 2.必须没有返回类型,也不能写void
- 构造器必须要掌握
package com.kuang.oop.demo02;
//学生类
public class Student {
//属性: 字段
String name;//null
int age;//0
//方法
public void study(){
System.out.println(this.name+"在学习");
}
}
//学程序好? 对世界进行更好的建模!---宅! 音乐,旅游
package com.kuang.oop.demo02;
//一个项目应该只有一个main方法
public class Application {
public static void main(String[] args) {
//类:抽象的,实例化
//类实例化后会返回一个自己的对象!
//student对象就是Student类的具体实例!
Student xiaoming=new Student();
Student xiaohong=new Student();
xiaoming.name="小明";
xiaoming.age=3;
System.out.println(xiaoming.name);
System.out.println(xiaoming.age);
xiaohong.name="小红";
xiaohong.age=3;
System.out.println(xiaohong.name);
System.out.println(xiaohong.age);
}
}
package com.kuang.oop.demo02;
//java--->class
public class Person {
//一个类即使什么都不写,它也会存在一个方法
//显示的定义构造器
String name;
int age;
//alt + insert
//实例化初始值
//1,使用new关键字,本质是在调用构造器
//2,用来初始化值
public Person(){
}
//有参构造:一旦定义了有参构造,无参构造就必须是显示定义
public Person(String name) {
this.name = name;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
/*
package com.kuang.oop.demo02;
//一个项目应该只有一个main方法
public class Application {
public static void main(String[] args) {
//new 实例化了一个对象
Person person = new Person("kuangshen",23);
System.out.println(person.name);//qinjiang
}
}
构造器:
1.和类名相同
2.没有返回值
作用:
1.new 本质在调用构造方法
2.初始化对象的值
注意点;
1.定义了有参构造之后,如果想使用无参构造,显示的定义一个无参的构造
Alt+Insert
this.=
*/
package com.kuang.oop.demo03;
public class Pet {
public String name;
public int age;
//无参构造
public void shout(){
System.out.println("叫了一声");
}
}
/*
package com.kuang.oop;
import com.kuang.oop.demo03.Pet;
public class Application {
public static void main(String[] args) {
Pet dog=new Pet();
dog.name="旺财";
dog.age=3;
dog.shout();
System.out.println(dog.name);
System.out.println(dog.age);
Pet cat=new Pet();
}
}
*/
package com.kuang.oop;
public class Application {
public static void main(String[] args) {
/*
1.类与对象
类是一个模板,对象是一个具体的实例
2.方法
定义,调用!
3.对应的引用
引用类型: 基本类型(8)
对象是通过引用来操作的:栈------>堆
4.属性:字段Field成员变量
默认初始化:
数字: 0 0.0
char: u0000
boolean:false
引用:null
修饰符 属性类型 属性名=属性值!
5.对象的创建和使用
-必须使用new关键字创造对象,构造器 Person kuangshen=new Person();
-对象的属性 kuangshen.name
-对象的方法 kuangshen.sleep()
6.类:
静态的属性 属性
动态的行为 方法
封装、继承、多态
*/
}
}
封装
- 该露的露,该藏的藏
- 我们程序设计要追求:“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。
- 封装(数据的隐藏)
- 通常,应禁止直接访问一个对象中的数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。
- 记住这句话就够了:属性私有,get/set
package com.kuang.oop.demo04;
//类 private:私有
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 +insert
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;
} else{
this.age=age;
}
}
}
/*
package com.kuang.oop;
1.提高程序的安全性,保护数据
2.隐藏代码的实现细节
3.统一接口
4.提高系统的可维护性
import com.kuang.oop.demo04.Student;
public class Application {
public static void main(String[] args) {
Student s1=new Student();
s1.setName("秦疆");
//方法名,参数列表
System.out.println(s1.getName());
s1.setAge(-1);//不合法的
System.out.println(s1.getAge());
}
}
*/
继承
- 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
- extands的意思是“扩展”。子类是父类的扩展。
- JAVA类中只有单继承,没有多继承! 一个儿子只能有一个爸爸,但是一个爸爸可以有多个儿子
- 继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
- 继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示。
- 子类和父类之间,从意义上讲应该具有“is a”的关系。
- object类
package com.kuang.oop.demo05;
//在Java中,所有的类,都默认直接或者间接继承object
//Person 人:父类
public class Person /*extends Object*/{
}
package com.kuang.oop.demo05;
//学生 is 人:派生类,子类
//子类继承了父类,就会拥有父类的全部方法!
public class Student extends Person {
//Ctrl+H
}
package com.kuang.oop.demo05;
//Teacher is 人:派生类,子类
public class Teacher extends Person{
}
package com.kuang.oop;
import com.kuang.oop.demo05.Person;
import com.kuang.oop.demo05.Student;
public class Application {
public static void main(String[] args) {
Person person = new Person();
}
}
- super-this
package com.kuang.oop.demo05;
//在Java中,所有的类,都默认直接或者间接继承object
//Person 人:父类
public class Person /*extends Object*/{
public Person() {
System.out.println("Person无参执行了");
}
protected String name="kuangshen";
//私有的东西无法被继承!
public void print(){
System.out.println("Person");
}
}
package com.kuang.oop.demo05;
//学生 is 人:派生类,子类
//子类继承了父类,就会拥有父类的全部方法!
public class Student extends Person {
public Student() {
//隐藏代码,调用了父类的无参构造
super();//调用父类的构造器,必须要在子类构造器的第一行
System.out.println("Student无参执行了");
}
//Ctrl+H
private String name="qinjiang";
public void print(){
System.out.println("Student");
}
public void test1(){
print();//Student
this.print();//Student
super.print();//Person
}
public void test(String name){
System.out.println(name);//秦疆
System.out.println(this.name);//qinjiang
System.out.println(super.name);//kuangshen
}
}
package com.kuang.oop.demo05;
//Teacher is 人:派生类,子类
public class Teacher extends Person{
}
package com.kuang.oop;
import com.kuang.oop.demo05.Person;
import com.kuang.oop.demo05.Student;
public class Application {
public static void main(String[] args) {
Student student = new Student();
// student.test("秦疆");
// student.test1();
}
}
super注意点:
1.super调用父类的构造方法,必须在构造方法的第一个
2.super必须只能出现在子类方法或者构造方法中!
3.super和this不能同时调用构造方法!
VS this:
代表的对象不同:
this: 本身调用者这个对象
super: 代表父类对象的应用
前提
this:没有继承也可以使用
super:只能在继承条件才可以使用
构造方法:
this():本类的构造
super():父类的构造!
- 方法重写:重点—>多态
package com.kuang.oop.demo05;
//继承
public class A extends B{
//Override 重写
@Override//注解:有功能的注释!
public void test() {
System.out.println("A=>test()");
}
}
package com.kuang.oop.demo05;
//重写都是方法的重写,和属性无关
public class B {
public void test(){
System.out.println("B=>test()");
}
}
package com.kuang.oop;
import com.kuang.oop.demo05.A;
import com.kuang.oop.demo05.B;
public class Application {
//静态的方法和非静态的方法区别很大!
//静态方法: //方法的调用只和左边,定义的数据类型有关
//非静态:重写
public static void main(String[] args) {
A a=new A();
a.test();//A
//父类的引用指向了子类
B b=new A();//子类重写了父类的方法
b.test();//B
}
}
重写:需要有继承关系,子类重写父类的方法!
1、方法名必须相同
2、参数列表必须相同
3、修饰符:范围可以扩大:public >Protected>Default>private
4、抛出的异常:范围,可以被缩小,但不能扩大:ClassNotFoundExdeption---->Exception(大)
重写:子类的方法和父类必须一致,方法体不同!
为什么需要重写:
1.父类的功能,子类不一定需要,或者不一定满足!
Alt+Insert: override;
多态
- 即同一个方法可以根据发送对象的不同而采用多种不同的行为方式。
- 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多(父类,有关系的类)
- 多态存在的条件
- 有继承关系
- 子类重写父类方法
- 父类引用指向子类对象
- 注意:多态是方法的多态,属性没有多态。
- instanceof (类型转换)引用类型,判断一个对象是什么类型
package com.kuang.oop.demo06;
public class Person {
public void run(){
System.out.println("run");
}
}
/*
多态注意事项:
1.多态是方法的多态,属性没有多态
2.父类和子类,有联系 类型转换异常! ClassCastException!
3.存在条件: 继承关系; 方法需要重写,父类的引用指向子类对象! Father f1=new Son();
1.static 方法:属于类,它不属于实例
2.final 常量
3.private 方法:
*/
package com.kuang.oop.demo06;
public class Student extends Person{
@Override
public void run() {
System.out.println("son");
}
public void eat(){
System.out.println("eat");
}
}
package com.kuang.oop;
import com.kuang.oop.demo06.Person;
import com.kuang.oop.demo06.Student;
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
//new Student();
//new Person();
//可以指向的引用类型就不确定了:父类的引用指向子类
//Student 能调用的方法都是自己的或者继承父类的!
Student s1 = new Student();
//Person 父类型 可以指向子类,但是不能调用子类独有的方法
Person s2 = new Student();
Object s3 = new Student();
//对象能执行哪些方法,主要看对象左边的类型,和右边关系不大!
((Student)s2).eat();//子类重写了父类的方法,执行子类的方法
s1.eat();
}
}
package com.kuang.oop.demo06;
public class Person {
public void run(){
System.out.println("run");
}
}
/*
多态注意事项:
1.多态是方法的多态,属性没有多态
2.父类和子类,有联系 类型转换异常! ClassCastException!
3.存在条件: 继承关系; 方法需要重写,父类的引用指向子类对象! Father f1=new Son();
1.static 方法:属于类,它不属于实例
2.final 常量
3.private 方法:
*/
/*
package com.kuang.oop;
import com.kuang.oop.demo06.Person;
import com.kuang.oop.demo06.Student;
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
//new Student();
//new Person();
//可以指向的引用类型就不确定了:父类的引用指向子类
//Student 能调用的方法都是自己的或者继承父类的!
Student s1 = new Student();
//Person 父类型 可以指向子类,但是不能调用子类独有的方法
Person s2 = new Student();
Object s3 = new Student();
//对象能执行哪些方法,主要看对象左边的类型,和右边关系不大!
((Student)s2).eat();//子类重写了父类的方法,执行子类的方法
s1.eat();
}
}
*/
package com.kuang.oop.demo06;
public class Student extends Person{
public void go(){
System.out.println("go");
}
}
/*
//Object > String
//Object > Person >Teacher
//Object > Person >Student
Object object = new Student();
//System.out.println(X instanceof Y);//能不能编译通过!
System.out.println(object instanceof Student);//true
System.out.println(object instanceof Person);//true
System.out.println(object instanceof Object);//true
System.out.println(object instanceof Teacher);//False
System.out.println(object instanceof String);//False
System.out.println("===================================");
Person person = new Student();
System.out.println(person instanceof Student);//true
System.out.println(person instanceof Person);//true
System.out.println(person instanceof Object);//true
System.out.println(person instanceof Teacher);//False
// System.out.println(person instanceof String);//编译报错!
System.out.println("===================================");
Student student = new Student();
System.out.println(student instanceof Student);//true
System.out.println(student instanceof Person);//true
System.out.println(student instanceof Object);//true
// System.out.println(student instanceof Teacher);//编译报错!
// System.out.println(student instanceof String);//编译报错!
}
*/
package com.kuang.oop.demo06;
public class Teacher extends Person{
}
package com.kuang.oop;
import com.kuang.oop.demo06.Person;
import com.kuang.oop.demo06.Student;
public class Application {
public static void main(String[] args) {
//类型之间的转换: 父 子
//高 //低
//子类转换为父类,可能丢失自己本来的一些方法!
Student student = new Student();
student.go();
Person person=student;
}
}
/*
1.父类引用指向子类的对象
2.把子类转换为父类,向上转型;
3.把父类转换为子类,强制转换
4.方便方法的调用,减少重复的代码!简洁
抽象:封装、继承、多态! 抽象类、接口、
*/
- static关键字详解
package com.kuang.oop.demo07;
//static:
public class Student {
private static int age;//静态的变量 多线程!
private double score;//非静态的变量
public void run(){
}
public static void go(){
}
public static void main(String[] args) {
go();
}
}
package com.kuang.oop.demo07;
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 person1 = new Person();
System.out.println("==============");
Person person2 = new Person();
}
}
package com.kuang.oop.demo07;
//静态导入包
import static java.lang.Math.random;
import static java.lang.Math.PI;
public class Test {
public static void main(String[] args) {
System.out.println(random());
System.out.println(PI);
}
}
抽象类
- abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。
- 抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。
- 抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。
- 抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
- 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。
package com.kuang.oop.demo08;
//abstract 抽象类:类extends: 单继承~ (接口可以多继承)
public abstract class Action {
//约束~有人帮我们实现~
//abstract ,抽象方法,只有方法名字,没有方法的实现!
public abstract void doSomething();
//1,不能new这个抽象类,只能靠子类去实现它,约束
//2,抽象类中可以写普通的方法
//3,抽象的抽象,约束~
//思考题? new ,存在构造器吗?
// 存在的意义 抽象出来~ 提高开发效率
}
package com.kuang.oop.demo08;
//抽象类的所有方法,继承了它的子类,都必须要实现它的方法~除非~
public class A extends Action {
@Override
public void doSomething() {
}
}
接口
-
普通类:只有具体实现
-
抽象类:具体实现和规范(抽象方法)都有!
-
接口:只有规范!自己无法写方法专业的约束!约束和实现分离:面向接口编程
-
接口就是规范,定义的是一组规则,体现了现实世界中”如果你是……则必须能……“的思想,如果你是天使,则必须能飞。如果你是汽车,则必须能跑。如果你是好人,则必须干掉坏人;如果你是坏人,则必须欺负好人。
-
接口的本质是契约,就像我们人间的法律一样,制定好后大家都遵守。
-
接口的精髓,是对对象的抽象,最能体现这一点的就是接口。为什么我们讨论设计模式都只针对具备了抽象能力的语言(比如c++,java,c#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。
声明类的关键字是class,声明接口的关键字是interface
package com.kuang.oop.demo09;
public interface TimeService {
void timer();
}
package com.kuang.oop.demo09;
//抽象的思维~ Java 架构师~
//interface 定义的关键字,接口都需要有实现类
public interface UserService {
//接口中的所有定义其实都是抽象的 public abstract
//常量~ public static final
int AGE=99;
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
package com.kuang.oop.demo09;
//抽象类:extends~
//类 可以实现接口 implements 接口
//实现了接口的类,就需要重写接口中的方法~
//多继承~利用接口实现多继承~
public class UserServiceImp1 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,定义一些方法,让不同的人实现~ 10------->1
3,public abstract
4,public static final
5,接口不能被实例化~,接口中没有构造方法~
6,implements可以实现多个接口
7,必须要重写接口中的方法~
8,总结博客~
内部类
- 内部类就是在一个类的内部再定义一个类,比如,A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了。
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类
package com.kuang.oop.demo10;
public class Outer {
}
package com.kuang.oop.demo10;
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");
}
}
interface UserService{
void hello();
}
package com.kuang.oop;
import com.kuang.oop.demo10.Outer;
public class Application {
public static void main(String[] args) {
}
}
异常机制
什么是异常
- 实际工作中,遇到的情况不可能是非常完美的。比如:你写的某个模块,用户输入不一定符合你的需求、你的程序要打开某个文件,这个文件可能不存在或者文件格式不对,你要读取数据库的数据,数据可能是空的等。我们的程序再跑着,内存或硬盘可能满了。等等。
- 软件程序在运行过程中,非常可能遇到刚刚提到的这些异常问题,我们叫异常,英文是:Exception,意思是例外。这些,例外情况,或者叫异常,怎么让我们写的程序做出合理的处理。而不至于程序崩。
- 异常指程序运行中出现的不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等。
- 异常发生在程序运行期间,它影响了正常的程序执行流程。
简单分类
-
要理解Java异常处理是如何工作的,你需要掌握以下三种类型的异常:
-
异常处理框架
-
检查性异常:最具代表的检查性异常时用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
-
运行时异常:运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略.
-
错误:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译时也检查不到。
异常体系结构
-
Java把异常当作对象来处理,并定义一个基类Java.lang.Throwable作为所有异常的超类。
-
在Java API中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception。
Error
- Error类对象由Java虚拟机生成并抛出,大多错误与代码编写者所执行的操作无关。
- Java虚拟机运行错误(Virtual MachinError),当JVM不再具有继续执行操作所需的内存资源时,将出现OutOfMemoryError.这些异常发生时,Java虚拟机(JVM)一般会选择线程终止;
- 还有发生在虚拟机试图执行应用时,如类定义错误(NoClassDefFoundError),链接错误(LinkageError).这些错误是不可察的,因为它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况。
Exception
- 在Exception分支中有一个重要的子类RuntimeException(运行时异常)
- ArrayIndexOutOfBoundsException(数组下标越界)
- NullPointerException(空指针异常)
- ArithmeticException(算数异常)
- MissingResourException(丢失资源)
- ClassNotFoundException(找不到类)等异常,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。
- 这些异常一般都是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生;
- Error和Exception的区别:Error通常是灾难性的致命错误,是程序无法控制和处理的,当出现这些异常时,Java虚拟机(JVM)一般会选择终止线程;Exception通常情况下时可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。
异常处理机制
- 抛出异常
- 捕获异常
- 异常处理五个关键字
- try,catch.finally,throw,throws
package com.kuang.exception;
public class Test {
public static void main(String[] args) {
try {
new Test().test(1,0);
} catch (ArithmeticException e) {
e.printStackTrace();
}
}//假设这方法中,处理不了这个异常,方法上抛出异常
public void test(int a,int b)throws ArithmeticException{
if(b==0){//主动的抛出异常 throw throws
throw new ArithmeticException();//主动的抛出异常,一般在方法中使用
}
}
}
/*
//假设要捕获多个异常,从小到大!
try {//try监控区域
}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 可以不要finally,假设IO,资源,关闭!
*/
package com.kuang.exception;
public class Test2 {
public static void main(String[] args) {
int a=1;
int b=0;
//ctrl+Alt+T
try {
System.out.println(a/b);
} catch (Exception e) {
e.printStackTrace();//打印错误的栈信息
} finally {
}
}
}
自定义异常
- 使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常。用户自定义异常类,只需继承Exception类即可。
- 在程序中使用自定义异常类,大体可以分为以下几个步骤:
- 创建自定义异常类。
- 在方法中通过throw关键字抛出异常对象。
- 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作。
- 在出现异常方法的调用者中捕获并处理异常。
package com.kuang.exception.demo02;
//自定义的异常类
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 +
'}';
}
}
package com.kuang.exception.demo02;
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(11);
} catch (MyException e) {
System.out.println("MyException"+e);
}
}
}
实际应用中的经验总结
- 处理运行时异常时,采用逻辑去合理规避同时辅助try-cath处理
- 在多重catch快后面,可以加一个catch(Exception)来处理可能会被遗漏的异常
- 对于不确定的代码,也可以加上try-catch,处理潜在的异常
- 尽量去处理异常,切忌只是简单地调用printStackTrace()去打印输出
- 具体如何处理异常,要根据不同的业务需求和异常类型去决定
- 尽量添加finally语句块去释放占用的资源IO~ Scanne~