JavaSE
0 前言
0.1 冯·诺依曼体系结构
冯·诺依曼体系结构:
0.2 计算机软件
- 计算机软件可以使计算机按照 事先预定好的顺序 完成特定的功能
- 计算机软件按照其功能划分为 系统软件 与 应用软件
系统软件:DOS(Disk Operating System), WIndows…
应用软件:微信,QQ…
0.3 电脑常用快捷键
0.4 Dos命令
打开cmd的方式:
- 开始+系统+命令提示符
- Win+R 输入cmd
- 在任意文件夹下面,按住shift键+鼠标右键点击,在此处打开命令行窗口
- 资源管理器的地址前面加上cmd地址
常用的dos命令
1.#盘符切换:
2.#查看当前目录下所有的文件 dir
3.#切换目录 cd change directory(前面加/d可以实现跨盘符切换)
4.cd ..
5.#清理屏幕 cls(clear screen)
6.#退出终端 exit
7.#查看ip地址 ipconfig
8.#打开应用 calc(计算器) mspaint(画图工具) notepad(记事本)
9.# ping命令 ping www.baidu.com
10.#文件操作
创建文件夹 md 文件名
移除文件夹 rd 文件名
创建文件 cd> 文件名
删除文件 del 文件名
0.5 计算机语言发展史
-
机器语言
计算机基本计算方式是基于二进制的方式
-
汇编语言
解决人类无法读懂机器语言的问题
指令代替二进制
-
高级语言
大体分为:面向过程和面向对象两大类
C语言是典型的面向过程的语言。C++,java是典型的面向对象的语言
1 初识Java
- C&&C++
1972年C诞生,贴近硬件,运行极快,效率极高。指针和内存管理
1982年C++诞生,面向对象,兼容C 用于图形领域,游戏等
1995年java诞生
- SE 标准
- ME 移动
- EE 企业版
1.1 Java发展
三高:高可用,高并发,高性能
基于java开发了居多的平台,系统,工具:
- 构建工具: ant,Maven,Jekins
- 应用服务器:Tomcat,Jetty,Jboss,weblogic
- Web开发:Struts,Spring,Hibernate,myBatis
- 开发工具:Eclipse,NetBean,intellij idea,Jbuilder
2006: Hadoop(大数据领域)
2008: Android(手机端)
1.2 Java特性和优势
- 简单性
- 面向对象
- 可移植性 write once,run anywhere
- 高性能
- 分布式
- 动态性
- 多线程
- 安全性
- 健壮性
1.3 Java三大版本
- JavaSE:标准版
- JavaME:嵌入式开发
- JavaEE:企业级开发
1.4 JDK、JRE、JVM
JDK:Java Development Kit
JRE: Java Runtime Environment
JVM: Java Virtual Machine
1.5 Java 程序运行机制
-
编译型 compile
将源代码一次性转换成目标代码的过程
-
解释型
将源代码逐条转换成目标代码同时逐条运行的过程。
2 Java 基础语法
2.1 注释
- 平时我们编写代码,在代码量比较少的时候,我们还可以看懂自己写的,但是当项目机构一旦复杂起来,我们就需要用到注释了。
- 注释并不会被执行,是给我们写代码的人来看的
- 书写注释是一个很好的习惯
2.1.1 三种注释
-
单行注释 //
-
多行注释 /* */
-
文档注释 JavaDoc
/**
*/
2.2 标识符
- 关键字
- Java 所有组成部分都需要名字。类名。变量名以及方法名都被称为标识符
标识符注意点:
- 所有标示符都应该以字母,美元符($),或者下划线(_)开始
- 首字母之后可以是字母,美元符,下划线或者数字的任何字符组合
- 不能使用关键字作为方法名或者变量名
- 标识符是大小写敏感的
- 可以使用命名,但是一般不建议这样去使用,也不建议用拼音,很Low
2.3 数据类型
强数据类型:
要求变量的使用要严格规定,所有变量都必须先定义后才能使用
2.3.1 基本类型
基本类型(primitive type)
分为数值类型:整数类型(byte 1个字节,short2字节,int 4个字节,long8个字节),浮点类型(float4字节,double8字节),字符类型(2字节)
boolean类型:占1位其值只有true和false两个
引用类型(reference type)
#Long类型要在数字后面加个L
#float类型要在数字后面加个F
#字符串,String不是关键字,类
什么是字节:
#位(bit):是计算机 内部数据 储存的最小单位,11001100是一个八位二进制数
#字节(byte):是计算机中 数据处理 的基本单位,习惯上用大写B来表示
1B (byte,字节)=8bit(位)
#字符:是指计算机中使用的字母、数字、字和符号
# 1bit 表示1位
#1024B=1KB
整数拓展:
二进制0b
十进制
八进制0
十六进制0x
float:有限 离散 舍入误差 大约 接近但不等于
double
BigDecimal
所有字符本质上数字
编码 Unicode 表:(97=a,65=A) 2字节
2字节 0-65536
2.4 变量
-
变量是什么:就是可以变化的量!
-
Java是一种强类型语言,每个变量都必须声明其类型
-
Java变量是程序中最基本的存储单位,其要素要包括变量名,变量类型和作用域
type varName[=value][{,varname=[=value]}]; //数据类型 变量名=值;可以使用逗号隔开来声明多个同类型变量
注意事项:
- 每个变量都有类型,类型可以是基本类型,也可以是引用类型
- 变量名必须是合法的标识符
- 变量声明是一条完整的语句,因此每一个声明都必须以分号结束
2.4.1 变量作用域
- 类变量
- 实例变量
- 局部变量
/**
* @author Yx
* @create 2021/2/23-11:07
*/
public class HelloWorld {
//类变量 static
static double salary=2500;
//属性:变量
//实例变量:从属于对象;如果不自行初始化, 这个类型的默认值 0 0.0
//布尔值:默认是false
//除了基本数据类型,其余的默认值都是null;
String name;
int age;
//main 方法
public static void main(String[] args) {
//局部变量;必须声明和初始化值
int i =10;
System.out.println(i);
//变量类型 变量名字=new Demo08();
HelloWorld helloWorld = new HelloWorld();
System.out.println(helloWorld.age);
System.out.println(helloWorld.name);
//类变量 static
System.out.println(salary);
}
//其他方法
public void add(){
System.out.println();
}
}
2.4.2 变量命名规范
- 所有变量、方法、类名:见名知意
- 类成员变量:首字母小写和驼峰原则:monthSalary 除了第一个单词以外,后面的单词首字母大写 lastName lastname
- 局部变量:首字母小写和驼峰原则
- 常量:大写字母和下划线:MAX_VALUE
- 类名:首字母大写和驼峰原则:Man,GoodMan
- 方法名:首字母小写和驼峰原则:run(),runRun()
2.5 常量
常量(Constant):初始化(initialize)后不能再改变值!不会变动的值。
所谓变量可以理解成一种特殊的值,他的值设定后,在程序运行过程中不允许被改变
public class Demo01 {
//修饰符,不存在先后顺序
static final double PI=3.14;//常量名一般用大写
public static void main(String[] args) {
System.out.println(PI);
}
}
2.6 运算符
- 算数运算符:+,-,*,/,%
- 自增自减 :++ ,–
- 赋值运算符 : = ,+=,-=,*=,/=
- 关系运算符 : >,<,>=,<=,== ,!=instanceof
- 逻辑运算符: & ,| ,! ,&& ,||
- 位运算符
- 条件运算符
public class Demo01 {
public static void main(String[] args) {
//二元运算符
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);//除出来小数要注意范围
}
}
public class Demo02 {
public static void main(String[] args) {
long a=1231351564654L;
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
//类型转换:byte,short,char用运算符运算后会自动转型为int类型
}
}
public class Demo03 { public static void main(String[] args) { //关系运算符返回的结果:正确, 错误 布尔值 int a =10; int b =10; int c =10; //取余,模运算 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); }}
public class Demo04 { public static void main(String[] args) { //++ -- 自增,自减 一元运算符 int a=3; int b=a++;//执行完这行代码后,先给b赋值,再自增 //a++ a=a+1 System.out.println(a); int c=++a;//执行完这行代码后,先自增,再给b赋值, System.out.println(a); System.out.println(b); System.out.println(c); //幂运算 2^3 =8 double pow=Math.pow(3,2); System.out.println(pow); }}
public class Demo05 { public static void main(String[] args) { //与(and) 或9(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); }}
public class Demo06 { public static void main(String[] args) { /* A =0011 1100 B =0000 1101 A&B =0000 1100 (0,1取0,两个1才为1) A|B =0011 1101 ( 0,1取1,两个0才为0) A^B =0011 0001(两个相同是0,不相同取1) ~B =1111 0010 (全取反) 0000 0000 0 0000 0001 1 0000 0010 2 0000 0011 3 0000 0100 4 0000 1000 8 0001 0000 16 << *2 >> /2 效率极高!!! */ System.out.println(2<<3);//16(2进制左移3位) }}
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);// 1020 System.out.println(a+b+"");// 30 //字符串在前面会进行拼接,如果在前面,则会进行运算 }}
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);//及格 }}
2.7 包机制
为了更好地组织类,Java提供了包机制,用于区别类名的命名空间。
包语句的语法格式为:
package pkg1[.pkg2[.pkg3]]
- 一般利用公司域名倒置作为包名
- 为了能够使用某一个包的成员,我们需要在Java程序种明确导入该包。使用"import"语句可完成此功能
import package1[.package2…].(classname|*);
2.8 JavaDoc
- javadoc命令是用来生成自己的api文档
/** * @author Yx * @create 2021/7/7-16:21 */
@author 作者名@version 版本号@since 指明需要最早使用的jdk版本@param 参数名@return 返回值情况@throws 异常抛出情况
javadoc -encoding UTF-8 -charset UTF-8 Doc.java//生成javadoc
3 Java流程控制
3.1 用户交互Scanner
之前我们学的基本语法中我们并没有实现程序和人的交互,但是java给我们提供了这样一个工具类,我们可以获取用户的输入。java.util.Scaner 是Java5的新特性,我们可以通过Scanner类来获取用户的输入
基本语法:
Scanner s=new Scanner(System.in);
- 通过Scanner类的next()与nextLine()方法获取输入的字符串,在读取前我们一般需要 使用 hasNext()和hasNextLine()判断是否还有输入的依据
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); } scanner.close();//凡是属于IO流的类如果不关闭会一直占用资源,要养成好习惯,用完就关掉 }}
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.hasNext()){ String str=scanner.nextLine(); System.out.println("输入的内容为"+str); } scanner.close(); }}
next():
- 一定要读取到有效字符后才可以结束输入
- 对输入有效字符之前遇到的空白,next()方法会自动将其去掉
- 只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符
- next()不能得到带有空格的字符+串
nextLine():
- 以Enter 为结束符,也就是说nextLIne()方法返回的是输入回车之前的所有字符
- 可以获得空白
import java.util.Scanner;/** * @author Yx * @create 2021/7/8-14:18 */public class Demo03 { 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("输入的不是整数数据!"); } if(scanner.hasNextFloat()){ f=scanner.nextFloat(); System.out.println("小数数据"+f); }else{ System.out.println("输入的不是小数数据!"); } }}
import java.util.Scanner;/** * @author Yx * @create 2021/7/8-14:25 */public class Demo05 { public static void main(String[] args) { double sum=0; int num=0; double f=0.0; Scanner scannner=new Scanner(System.in); System.out.println("请输入"); while (scannner.hasNextDouble()){ f=scannner.nextDouble(); num++; sum+=f; System.out.println("你输入了第"+num+"个数,当前结果sum="+sum); } System.out.println("输入错误,结束输入"); System.out.println("你输入的数字总和是"+sum); System.out.println("你输入的数字平均数是"+sum/num); scannner.close(); }}
3.2 顺序结构
-
Java 的基本结构就是顺序结构,除非特别指明,否则就按照顺序一步一步执行。
-
顺序结构是最简单的算法结构
-
语句和语句之间,框与框之间是按从上到下的顺序进行的,它是由若干个依次执行的处理步骤组成的,它是任何一个算法都离不开的一种基本算法结构
3.3 选择结构
-
if单选择结构
-
我们很多时候需要去判断一个东西是否可行,然后我们才去执行,这样一个过程在程序中用if语句来表示
-
语法:
if(布尔表达式){
//如果布尔表达式为true
}
-
-
if双选择结构
-
我们需要两个判断,则需要一个双选择机构,所以就有了if-else结构;
-
语法:
if(布尔表达式){
//如果布尔表达式为true
}else{
//如果布尔表达式为false
}
-
-
if多选择结构
-
选择不仅仅只有两个的时候,我们需要用多选择结构来处理
-
语法:
if(布尔表达式1){
//如果布尔表达式1为true,执行代码
}elseif(布尔表达式2){
//如果布尔表达式2为true,执行代码
}elseif(布尔表达式3){
//如果布尔表达式3为true,执行代码
}else{
//如果以上布尔表达式都不为true,执行代码
}
-
-
嵌套的if结构
-
在一个if里面嵌套另一个if
-
语法:
if(布尔表达式1){
//如果布尔表达式1为true,执行代码
if(布尔表达式2){
//如果布尔表达式2为true,执行代码
}
-
-
switch多选择结构
-
多选择结构还有一个实现方式就是switch case 语句
-
Switch case 语句判断一个变量与一系列值中的某个值是否相等,每个值成为一个分支
-
Switch 语句的变量类型可以是:
- byte,short,int或者是char
- 从javaSE7开始
- switch支持字符串String类型
- 同时case标签必须为字符串常量或字面量
switch(expression){ case value: //语句 break;//可选 case value: //语句 break;//可选 //你可以有任意数量的case语句 default://可选 //语句}
/** * @author Yx * @create 2021/7/8-14:51 */public class Demo01 { public static void main(String[] args) { //JDK 7的新特性,表达式结果可以是字符串; //字符的本质还是数字 //反编译,java - class (字节码) -----反编译(IDEA) 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 ( "未知等级" ); } }}
-
3.4 循环结构
- while 循环
- do…while循环
- for 循环
- 在java5中引入了一种主要用于数组的增强型for循环
3.4.1 while 循环
-
while是最基本的循环,他的机构为
while(布尔表达式){
//循环内容
}
-
只要布尔表达式为true,循环就会一直执行下去
-
我们大多数情况是会让循环停止下来,我们需要一个让表达式失效的方式来结束循环
-
少部分情况需要循环一直执行,比如服务器的请求响应监听等。
-
循环条件一直为true就会造成无限循环【死循环】,我们正常的业务编程中应该尽量避免死循环,会影响程序性能或者造成系统卡死崩溃!
public class whileDemo1 { public static void main(String[] args) { int i =0; int sum=0; while (i<100){ i++; sum+=i; } System.out.println (sum); }}
3.4.2 do…while循环
-
对于while语句而言,如果不满足条件,则不能进入循环。但有时候我们需要即使不满足条件,也至少执行一次。
-
do…while循环和 while 循环类似,不同的是,do…while循环至少会执行一次
do{
//代码语句
}while(布尔表达式)
-
while 和 do…while的区别:
- while先判断后执行,dowhile是先执行后判断!
- Do…while总是保证循环体会被至少执行一次,这是他们的主要差别
public class whileDemo02 { public static void main(String[] args) { int i=0; while (i<100){ System.out.println (i); i++; } System.out.println ("================="); do{ System.out.println (i); i++; }while (i<0); }}
3.4.3 For循环
-
虽然所有循环结构都可以用While或者 do … while 表示,但Java提供了另一种语句——for循环,使一些循环结构变得更加简单。
-
for循环语句是支持迭代的一种通用结构,是最有效,最灵活的循环结构
-
for循环执行的次数是在执行前就确定的,语法格式如下:
for(初始化;布尔表达式;更新){
//代码语句
}
public class ForDemo01 { public static void main(String[] args) { int oddSum = 0; int evenSum=0; for (int i = 0; i <=100; i++) { if(i%2==1){ oddSum+=i; } if(i%2==0){ evenSum+=i; } } System.out.println ("奇数的和"+oddSum); System.out.println ("偶数的和"+evenSum); }}
public class forDemo02 { public static void main(String[] args) { for (int i = 0; i <= 1000; i++) { if(i%5==0){ System.out.print (i+"\t"); } if(i%(5*3)==0){ System.out.println (); } } }}
public class forDemo03 { public static void main(String[] args) { for (int i = 1; i <= 9; i++) { for (int j = 1; j <= 9; j++) { if(i>=j) System.out.print (i+"*"+ j+"="+i*j+"\t"); } System.out.println (); } }}
3.4.4 增强for循环
-
java5引入了一种主要用于数组或集合的增强型for循环
-
Java增强for 循环语法格式如下:
for(声明语句:表达式){
//代码句子
}
-
声明语句:声明新的局部变量,该变量的类型必须和数组元素的类型匹配,其作用域限定在循环语句块,其值与此时数组元素的值相等
-
表达式:表达式是要访问的数组名,或者是返回值为数组的方法
public class forDemo04 { 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); } }}
3.5 break& continue
-
break在任何循环语句的主体部分,均可用break控制循环的流程,break用于强行退出循环,不执行循环中剩余的语句。(break语句也在switch语句中使用)
-
continue 语句用在循环语句体中,用于终止某次循环的过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定
-
关于goto关键字
- goto关键字很早就在程序设计语言中出现,尽管goto仍是java的一个保留字,但并未在语言中得到正式使用;java没有goto,然而,break和continue这两个关键字的身上,我们仍然能看出一些goto的影子—带标签的break和continue
- "标签"是指后面跟一个冒号的标识符,例如:label:
- 对Java来说唯一能用到标签的地方是在循环语句之间,而在循环之前设置标签的唯一理由是:我们希望在其中嵌套另一个循环,由于break和continue关键字通常只中断当前循环,但若随同标签使用,它们就会中断到存在标签的地方
public class breakDemo { public static void main(String[] args) { int i =0; while (i<100){ System.out.println (i); i++; if(i>30){ break; } } }}
public class continueDemo { public static void main(String[] args) { int i =0; while (i<10){ i++; if(i==5){ continue; } System.out.println (i); } }}
3.6 练习
打印三角形
* ***
public class TestDemo {
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
for (int i1 = 5; i1 >i; i1--) {
System.out.printf ( " " );
}
for (int i2 =0; i2<=i; i2++) {
System.out.printf ( "*" );
}
for(int i3=0;i3<i;i3++){
System.out.printf ( "*" );
}
System.out.println ();
}
}
}
4 Java方法详解
4.1何谓方法
- java方法是语句的集合,他们在一起执行一个功能。
- 方法是解决一类问题的步骤的有序组合
- 方法包含于类或对象中
- 方法在程序中被创建,在其他地方被引用
设计方法的原则:方法的本意是功能块,就是实现某个功能的语句块的集合,我们设计方法的时候,最好要保持方法的原子性,就是一个方法只完成一个功能,这样有利于我们后期的扩展
- Java的方法类似于其他语言的函数,是一段用来完成特定功能的代码段,一般情况下,定义一个方法包含以下语法:
一个方法包含一个方法头和一个方法体,下面是一个方法的所有部分:
- 修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型
- 返回值类型:方法可能会返回值。returnValueType是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值,在这种情况下,returnValueType是关键字void
- 方法名:是方法的实际名称、方法名和参数表共同构成方法签名
- 参数类型:参数像是一个占位符,当方法被调用时,传递值给参数,这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不含任何参数
-
- 形式参数:在方法被调用时用于接收外界输入的数据。
- 实参:调用方法时实际传给方法的数据。
- 方法体:方法体包含具体的语句,定义该方法的功能
修饰符 返回值类型 方法名(参数类型 参数名){
...
方法体
...
return 返回值
}
4.2方法定义和调用
-
调用方法:对象.方法名(实参列表)
-
Java支持两种调用方法的方式,根据方法是否返回值来选择。
-
当方法返回一个值的时候,方法调用通常被当做一个值。例如:
int larger=max(30,40);
-
如果方法返回值是void ,方法调用一定是一条语句
System.out.println("Hello");
package com.study.method; public class Demo02 { public static void main(String[] args) { int max=max ( 10,20 ); System.out.println (max); } //比大小 public static int max(int num1,int num2){ int result=0; if(num1==num2){ System.out.println ("num=1=num2"); return 0; } if(num1>num2){ result=num1; }else{ result=num2; } return result; } }
4.3 方法的重载
-
重载就是在一个类中,有相同的函数名称,但形参不同的函数。
-
方法的重载的规则:
-
- 方法名称必须相同
- 参数列表必须不同(个数不同、或类型不同、参数排列顺序不同等)。
- 方法的返回类型可以相同也可以不相同
- 仅仅返回类型不同不足以成为方法的重载
实现理论:
- 方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错
package com.study.method;
/**
* @author Yx
* @create 2022/1/2-12:05
*/
public class Demo02 {
public static void main(String[] args) {
double max=max ( 10,200 );
System.out.println (max);
}
public static double max(double num1,double num2){
double result=0;
if(num1==num2){
System.out.println ("num=1=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 ("num=1=num2");
return 0;
}
if(num1>num2){
result=num1;
}else{
result=num2;
}
return result;
}
}
4.4 命令行传参
- 有时候你希望运行一个程序时候再传递给它消息,这要靠传递命令行参数给main()函数实现。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sOScYKmY-1642230845128)(C:\Users\11953\Desktop\笔记\Java\01.java基础\image-20220102131818322.png)]
package com.study.method;
/**
* @author Yx
* @create 2022/1/2-13:12
*/
public class Demo03 {
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
System.out.println ( "args[ " +i+"] ="+ args[i] );
}
}
}
4.5可变参数
- JDK 1.5开始,Java支持传递同类型的可变参数给一个方法
- 在方法声明中,在指定参数类型后加一个省略号(…).
- 一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。
package com.study.method;
/**
* @author Yx
* @create 2022/1/2-13:23
*/
public class Demo04 {
public static void main(String[] args) {
printMax ( 34,1,3,5,56 );
printMax ( new double[]{1,2,3} );
}
public static void printMax(double ... number)
{
if (number.length==0){
System.out.println ("No argument passed");
return;
}
double result=number[0];
for (int i = 0; i < number.length; i++) {
if(number[i]>result){
result=number[i];
}
}
System.out.println ( "the max value result = " + result );
}}
4.6 递归
- 递归就是:A方法调用A方法!就是自己调用自己
- 利用递归可以用简单的程序来解决一些复杂的问题,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大减少了程序的代码量,递归的能力在于用有限的语句来定义对象的无线集合。
递归结构包括两个部分:
- 递归头:什么时候不调用自身方法,如果没有头,将陷入死循环。
- 递归体:什么时候需要调用自身方法
package com.study.method;/** * @author Yx * @create 2022/1/2-20:49 */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 ); } }}
计算器:
package com.study.method;
import java.util.Scanner;
/**
* @author Yx
* @create 2022/1/2-20:57
*/
public class Demo07 {
public static void main(String[] args) {
Cala();
}
private static void Cala(){
double result;
Scanner scanner=new Scanner (System.in);
System.out.println ("请输入一个数字");
while(scanner.hasNextDouble ()){
double a=scanner.nextDouble ();
System.out.println ("请输入运算符号");
String symbol=scanner.next ();
System.out.println ("请输入第二个数字");
double b=scanner.nextDouble ();
switch (symbol){
case"+":
System.out.println (result=a+b);
break;
case"-":
System.out.println (result=a-b);
break;
case"*":
System.out.println (result=a*b);
break;
case"/":
System.out.println (result=a/b);
break;
}
}
}
}
5 数组
5.1 数组的定义
- 数组是相同类型数据的有序集合
- 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成
- 其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问他们
5.2 数组声明和创建
-
首先必须声明数组变量,才能在程序中使用数组,下面是声明数组变量的语法:
dataType [] arrayRefVar //首选的方法或dataType arrayRefVar[] //效果相同,但不是首选的方法
-
Java语言使用new操作符来创建数组,语法如下:
dataType[] arrayRefVar =new dataType[arraySize];
-
数组的元素是通过索引访问的,数组索引从0开始
-
获取数组的长度: arrays.length
package com.study.array;
/**
* @author Yx
* @create 2022/1/2-22:31
*/
public class Demo01 {
//变量的类型 变量的名字=变量的值
//数组类型
public static void main(String[] args) {
int[] nums;//1.声明一个数组
nums=new int[10];//2.创建一个数组
// 这里面可以存放10个int类型的数字
//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]+sum;
}
System.out.println (sum);
}
}
5.3 内存分析
-
java 内存分析:
堆:
1.存放new的对象和数组。可以被所有的线程共享,不会存放别的对象
2.存放new的对象和数组。可以被所有的线程共享,不会存放别的对象
栈:
1.存放基本变量类型(会包含这个基本类型的具体数值)
2.引用对象的变量(会存放这个引用在堆里面的具体地址)
方法区:
1.可以被所有的线程共享
2.包含了所有的class和static变量
数组的默认初始化:
数组是引用类型,他的元素相当于类的实例变量,因此数组一经分配空间, 其中的每个元素也被按照实例变量同样的方式被隐式初始化。
5.4 数组基本特点
- 其长度是去确定的,数组一旦被创建,它的大小就是不可以改变的
- 其元素必须是相同类型,不允许出现混合类型
- 数组中的元素可以是任何数据类型,包括基本类型和引用类型
- 数组变量属于引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始数据还是其他对象类型,数组对象本身是在堆中的
下标的合法区间:[0,length-1]
ArrayIndexOutOfBoundsException:数组下标越界异常!
小结:
- 数组是相同数据类型(数据类型可以为任意类型)的有序集合
- 数组也是对象,数组元素相当于对象的成员变量
- 数组长度是确定的,不可变的,如果越界,则报:ArrayIndexOutOfBounds
5.5 数组的循环
package com.study.array;
/**
* @author Yx
* @create 2022/1/3-22:47
*/
public class Demo02 {
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);
//查找最大元素
int max =arrays[0];
for (int i = 0; i < arrays.length; i++) {
if(arrays[i]>max){
max=arrays[i];
}
}
System.out.println ("max=="+max);
}
}
package com.study.array;/** * @author Yx * @create 2022/1/3-22:47 */public class Demo02 { public static void main(String[] args) {int []arrays={1,2,3,4,5};//array.fotr: 没有下标 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.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; }}
5.6 多维数组
- 多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组
- 二维数组:
int a[] [][][]=new int [] []
package com.study.array;
import com.sun.org.apache.bcel.internal.generic.NEW;
/**
* @author Yx
* @create 2022/1/3-23:18
*/
public class Demo03 {
public static void main(String[] args) {
int [][]arrays= {{1, 2}, {2, 3}, {3, 4}, {4, 5}};
for (int i = 0; i < arrays.length; i++) {
for (int j = 0; j < arrays[i].length; j++) {
System.out.println (arrays[i][j]);
}
}
}
}
5.7 Arrays 类
-
数组的工具类:java.util.Arrays
-
由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作。
-
Arrays类中的方法都是static修饰的静态方法,在使用的时候,可以直接使用类名进行调用,而不用使用对象来调用
具有以下常用功能:
- 给数组赋值:通过fill方法
- 给数组排序:通过sort方法,按升序
- 比较数组:通过equals方法比较数组中元素值是否相等
- 查找数组元素:通过binarySearch方法能对排序好的数组进行二分法查找法操作
package com.study.array;
import java.util.Arrays;
import java.util.Arrays.*;
/**
* @author Yx
* @create 2022/1/4-21:59
*/
public class Demo04 {
public static void main(String[] args) {
int []a={1,2,3,4,5,6,7,454,78,878,4,545465};
System.out.println ( Arrays.toString ( a ) );
Demo04 a1=new Demo04 ();
a1.printArray ( a );
Arrays.sort ( a );//对数组排序
System.out.println ( Arrays.toString ( a ) );//升序排序
Arrays.fill ( a,0 );
System.out.println ( Arrays.toString ( a ) );
Arrays.fill ( a,2,4,1);//2-4填充(第三个和第四个变成1)
System.out.println ( Arrays.toString ( a ) );
}
public 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]+", ");}
}
}
}
5.8 冒泡排序
时间复杂度 O(n2)
package com.study.array;import java.util.Arrays;/** * @author Yx * @create 2022/1/9-11:45 */public class Demo05 { //冒泡排序 //1.比较数组中,两个相邻的元素,如果第一个数比第二个数大,我们就交换他们的位置 //2.每一次比较,都会产生一个最大或者最小的的数字 //3.下一轮可以少一次排序 //4.依次循环,直到结束 public static void main(String[] args) { int[] a={1,4,5,6,48,74,56,465,486,748,46}; sort ( a ); System.out.println ( Arrays.toString ( a ) ); } public static int[] sort(int []array){ int temp=0; //for循环,判断我们这个要走多少次 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; }}
5.9 稀疏数组
当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组。
稀疏数组的处理方式是:
- 记录数组一共有几行几列,有多少不同值
- 把具有不同值的元素和行列及值纪录在一个小规模的数组中,从而缩小程序的规模
package com.study.array;
import java.lang.reflect.Array;
/**
* @author Yx
* @create 2022/1/9-12:07
*/
public class Demo06 {
public static void main(String[] args) {
//创建一个二维数组 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]=11;
//遍历二维数组,将非0的值。存放在稀疏数组中
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 ( "还原" );
//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 ();
}
}
}
6 面向对象
6.1 什么是面向对象
面向过程思想:步骤清晰简单,第一步做什么,第二步做什么…
面向过程适合处理一些较为简单的问题
面向对象思想:
-
物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程思索。
-
面向对象适合处理复杂的问题,适合处理需要多人协作的问题
对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统,但是,具体到微观操作,仍然需要面向过程的思路去处理
- 面向对象编程(Object-Oriented Programming,OOP)
- 面向对象编程的本质是:以类的方式组织代码,以对象的组织(封装)数据。
- 抽象
- 三大特性 :封装,继承,多态
- 从认识论角度考虑是现有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象
- 从代码运行角度考虑是现有类后有对象。类是对象的模板
6.2 回顾方法的定义和调用
package com.study.oop;
/**
* @author Yx
* @create 2022/1/9-14:13
*/
public class Demo01 {
public static void main(String[] args) {
//main方法
}
/*
* 修饰符 返回值类型 方法名(...){
* //方法体
* return 返回值
*
* }
*
*
* */
//return 结束方法 返回一个结果
public String sayHello(){
return "hello world";
}
public int max(int a ,int b){
return a>b?a : b;//三元运算符
}
}
package com.study.oop;
import java.security.PublicKey;
/**
* @author Yx
* @create 2022/1/9-15:17
*/
public class Demo05 {
public static void main(String[] args) {
Person person=new Person ();
System.out.println (person.name);
Demo05.change ( person );
System.out.println (person.name);
}
public static void change(Person person){
//person 是一个对象, 是一个具体的人 可以改变
person.name="yx";
}
//定义了一个Person类,有一个属性name;
}
class Person{
String name;
}
6.3 类和对象的关系
- 类是一种抽象的数据类型,它是对某一类事物整体的描述/定义,但是并不能代表某一个具体的事物。
- 对象是抽象概念的具体实例。能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念
package com.study.oop2;
/**
* @author Yx
* @create 2022/1/9-16:32
*/
public class Student {
//属性 :字段
String name;
int age;
//方法
public void study(){
System.out.println (this.name+"在学习");
}
}
package com.study.oop2;
/**
* @author Yx
* @create 2022/1/9-16:34
*/
public class Application {
public static void main(String[] args) {
//类:抽象化,实例化
//类实例化后会返回一个自己的对象
//student对象就是一个Student类的具体实例
Student xiaoming=new Student ();
Student xiaohong=new Student();
xiaoming.name="小明";
xiaoming.age=18;
xiaohong.name="小红";
xiaohong.age=19;
System.out.println (xiaoming.name);
System.out.println (xiaoming.age);
System.out.println (xiaohong.name);
System.out.println (xiaohong.age);
}
}
创建与初始化对象:
- 使用new关键字创建对象
- 使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象,进行默认的初始化以及对类中构造器的调用
- 类中的构造器也称为构造方法,是进行创建对象的时候必须要调用的。并且构造器有以下两个特点
- 1.必须和类的名字相同
- 2.必须没有返回类型,也不能写void
package com.study.oop2;
/**
* @author Yx
* @create 2022/1/9-16:47
*/
public class Person {
//一个类即使什么都不写,它也会存在一个方法
//显示的定义构造器
String name;
//实例化初始值
//1.使用new关键字,本质是在调用构造器
//2.用来初始化值
public Person(){
this.name="yx";
}
//有参构造:一旦定义了有参构造,无参就必须显示定义
public Person(String name ){
this.name=name;
}
//alt+insert 生成构造器
}
/*
* public static void main(String[] args) {
//new实例化对象
Person person=new Person ("yx66");
System.out.println ( person.name );}
构造器:1.和类名相同
2.没有返回值
作用:1.new本质在调用构造方法
* 2.初始化对象的值
注意点:
* 1.定义有参构造之后,如果想使用无参构造,显示定义一个无参的构造
Alt +insert
* constructor
*
* */
package com.study.oop2;/** * @author Yx * @create 2022/1/9-17:07 */public class Pet { public String name; public int age; //无参构造 public void shout(){ System.out.println ("shout once "); }}
package com.study.oop2;/** * @author Yx * @create 2022/1/9-16:34 */public class Application { public static void main(String[] args) { Pet dog = new Pet (); dog.age=3; dog.name="旺财"; System.out.println ( dog.name ); System.out.println ( dog.age ); dog.shout (); }}
6.4 小结
package com.study.oop2;/** * @author Yx * @create 2022/1/9-16:34 */public class Application { public static void main(String[] args) { /* 1.类与对象 类是一个模板;抽象,对象是一个具体得实例 2.方法 定义、调用 3.对应的引用 引用类型:基本类型 对象是通过引用来操作的,栈->堆 4.属性: 字段field 成员变量 数字:0 0.0 char: u000 boolean:false 引用:null 修饰符 属性类型 属性名=属性值! 5.对象的创建和使用 必须使用New关键字创造对象,构造器, Person kuangshen =new Person(); 对象的属性 kaungshen.name; 对象的方法 kuangshen.sleep(); 6.类: 静态的属性 属性 动态的行为 方法 ‘封装 继承 多态’ */ }}
6.5 封装
我们程序设计要追求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉。低耦合:仅暴露少量方法给外部使用
封装:数据的隐藏
通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称之为信息隐藏。
package com.study.oop3;/** * @author Yx * @create 2022/1/10-21:46 */public class Application { public static void main(String[] args) { /* 1.提高程序的安全性,保护数据 2.隐藏代码的实现细节 3.统一接口 4.系统可维护性增加*/ Student student=new Student (); student.setName ( "yx" ); System.out.println (student.getName ()); }}
package com.study.oop3;
/**
* @author Yx
* @create 2022/1/10-21:45
*/
public class Student {
//名字
private String name;
//学号
private int id;
//性别
private char sex;
//学习
//睡觉
public String getName() {
return 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;
}
}
6.6 继承
- 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模
- extends 的意思是扩展,子类是父类的扩展
- Java中类只有单继承,没有多继承
- 继承是类和类之间的一种关系,除此之外,类和类之间的关系还有依赖、组合、聚合等
- 继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示
- 子类和父类之间,从意义上将应该具有 “is a” 的关系
super注意点
- super调用父类的构造方法,必须在构造方法的第一个
- super必须只能出现在子类的方法或者构造方法中
- super和this不能同时调用构造方法
Vs this:
- 代表的对象不同
- this:本身调用者的这个对象
- super:代表父类对象的应用
- 前提:
- this:没有继承也可以使用
- super:只能在继承的条件下才能使用
- 构造方法:
- this():本类的构造
- super():父类的构造
package com.study.oop4;/** * @author Yx * @create 2022/1/10-22:00 *///学生is 人public class Student extends Person { private String name="qinjiang"; public Student() { //隐藏代码:调用了父类的无参构造 super(); //调用父类的构造器,必须要在子类的第一行 System.out.println ("Student无参执行"); } public void print(){ System.out.println ("Student"); } public void test(String name){ System.out.println (name);// 秦疆 System.out.println (this.name);//qinjiang System.out.println (super.name);//kuangshen } public void test2(){ print ();//Student this.print ();// Student super.print ();// Person }}
package com.study.oop4;/** * @author Yx * @create 2022/1/10-22:01 *///老师是人public class Teacher extends Person{ public Teacher() { System.out.println ("Teacher无参执行"); } public void print(){ System.out.println ("Teacher"); }}
package com.study.oop4;/** * @author Yx * @create 2022/1/10-22:00 *///在Java中,所有的类都直接或者间接继承Object //私有的无法被继承public class Person { public Person() { System.out.println ("Person无参执行"); } protected String name="kuangshen"; public void print(){ System.out.println ("Person"); }}
package com.study.oop4;/** * @author Yx * @create 2022/1/10-22:05 */public class Application { public static void main(String[] args) { Student student=new Student (); student.test ( "秦疆" ); student.test2 (); }}
重写:需要有继承关系,子类重写父类的方法!
- 方法名必须相同
- 参数列表必须相同
- 修饰符:范围可以扩大但不能缩小 public>protected>default>private
- 抛出的异常:范围可以被缩小,但不能扩大 ClassNotFoundException—>Exception(大)
重写,子类的方法和父类必须要一致:方法体不同!
为什么需要重写:
1.父类的功能,子类不一定需要,或者不一定满足!
Alt+insert: override;
package com.study.oop5;
/**
* @author Yx
* @create 2022/1/10-22:30
*/
public class A extends B {
public static void test(){
System.out.println ("A=>test()");
}
}
package com.study.oop5;
/**
* @author Yx
* @create 2022/1/10-22:30
*/
public class B {
public static void test(){
System.out.println ("B=>test()");
}
}
package com.study.oop5;/** * @author Yx * @create 2022/1/10-22:31 */public class application { public static void main(String[] args) { //静态方法和非静态的方法区别很大 //静态方法://方法的调用只和左边,定义的数据类型有关 //非静态:重写 A a=new A (); a.test ();//A //父类的引用指向了子类 B b=new A ();//子类重写了父类的方法 b.test ();//B }}
6.7 多态
- 动态编译:类型:可扩展性
- 即同一个方法可以根据发送对象的不同而采用多种不同的行为方式
- 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多
多态存在的条件:
- 有继承关系
- 子类重写父类方法
- 父类引用指向子类对象
多态是方法的多态,属性没有多态
package com.study.oop6;
/**
* @author Yx
* @create 2022/1/10-22:47
*/
public class Student extends Person{
@Override
public void run() {
System.out.println ("son");
}
public void eat(){
System.out.println ("eat");
}
}
package com.study.oop6;
/**
* @author Yx
* @create 2022/1/10-22:46
*/
public class Person {
public void run(){
System.out.println ("run");
}
}
package com.study.oop6;
/**
* @author Yx
* @create 2022/1/10-22:47
*/
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
//new Person();
//new Student();
//可以指向的引用类型就不确定了:父类的引用指向子类
Student s1=new Student ();
Person s2=new Student ();//Person父亲型,可以指向子类,但是不能调用子类独有的方法
Object s3=new Student ();
//Student 能调用的方法都是自己的或者继承父类的
s2.run ();//子类重写了父类的方法,执行子类的方法
s1.run ();
//对象能执行哪些方法,主要看对象左边的类型,和右边关系不大!
((Student)s2).eat();//强制转换成Student 才能使用子类的方法
s1.eat ();
}
}
/*
多态注意事项:
1.多态是方法的多态,属性没有多态
2.父类和子类,有联系,类型转换异常! ClassCastExceptiopn
3.存在条件:继承关系,方法需要重写,父类引用子类对象! father f1=new son();
1.static 方法,属于类,它不属于实例
2.final 常量
3.private
*/
son
son
eat
eat
6.8 instance of关键字
instanceof 是 Java 的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型
package com.study.oop7;
/**
* @author Yx
* @create 2022/1/14-18:42
*/
public class Application {
public static void main(String[] args) {
//Object>String
//Object>Person>Student
//Object>Person>Student
Object object=new Student ();
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 Person ();
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);//编译报错
System.out.println ("==========================");
//高 低
Person student1=new Student ();
//student 将这个对象转换为Student类型,我们就可以使用Student 类型的方法了
Student student2=(Student) student1;
student2.go();
((Student)student1).go ();//等价
//子类转换为父类,可以会丢失自己本来的一些方法
Student student3=new Student ();
student.go ();
Person person1=student3;
//person1.go(); 丢失自己的方法
person.run ();
}
}
/*
1.父类引用子类的对象
2.把子类转换为父类,向上转型
3.把父类转换为子类,向下转型,强制转换
4.方便方法的调用,减少重复的代码
*/
package com.study.oop7;
/**
* @author Yx
* @create 2022/1/14-18:41
*/
public class Student extends Person{
public void go(){
System.out.println ("go");
}
}
package com.study.oop7;
/**
* @author Yx
* @create 2022/1/14-18:41
*/
public class Teacher extends Person {
}
package com.study.oop7;
/**
* @author Yx
* @create 2022/1/14-18:41
*/
public class Person {
public void run(){
System.out.println ("run");
}
}
6.9 Static
package com.study.oop8;
/**
* @author Yx
* @create 2022/1/14-19:04
*/
public class Student {
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 ( s1.score );
System.out.println ( Student.age );//;类变量
// System.out.println ( Student.score );//非静态变量,报错
System.out.println ( s1.age );
System.out.println ( s1.score );
go ();
Student.go ();
}
}
package com.study.oop8;
/**
* @author Yx
* @create 2022/1/14-19:03
*/
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 person=new Person ();
System.out.println ("============");
Person person2=new Person ();
}
/*
静态代码块
匿名代码块
构造方法
============
匿名代码块
构造方法*/
}
package com.study.oop8;
import static java.lang.Math.random;
/**
* @author Yx
* @create 2022/1/14-19:12
*/
public class Test {
public static void main(String[] args) {
System.out.println (Math.random ());
System.out.println (random ());//import static java.lang.Math.random;
//加了static 之后,直接可以使用方法
}
}
6.10 抽象类
-
abstract 修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法,如果修饰类,那么该类就是抽象类
-
抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类
-
抽象类,不能使用new 关键字来创建对象,它是用来让子类继承的
-
抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的
-
子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。
package com.study.oop8;/** * @author Yx * @create 2022/1/14-19:04 */public class Student { 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 ( s1.score ); System.out.println ( Student.age );//;类变量 // System.out.println ( Student.score );//非静态变量,报错 System.out.println ( s1.age ); System.out.println ( s1.score ); go (); Student.go (); }}
package com.study.oop9;import javax.swing.Action;/** * @author Yx * @create 2022/1/14-19:20 *///抽象类的所有方法,继承了它的子类,都必须要实现它的方法,除非public class A implements Action {//未实现}
6.11 接口
-
普通类,只有具体实现
-
抽象类:具体实现和规范(抽象方法)都有
-
接口:只有规范,自己无法写方法 专业的约束!约束和实现分离:面向接口编程。
-
接口就是规范,定义的是一组规则
-
接口的本质是契约,就像法律一样,制定好之后大家都遵守
-
OO的精髓,是对对象的抽象,最能体现这一点的就是接口,为什么我们讨论设计模式都只针对具备了抽象能力的语言,比如c++ ,Java,c#),就是因为设计模式所研究的,实际上就是如何合理的去抽象
声明类的关键字是class,声明接口的关键字是interface
package com.study.oop10;
/**
* @author Yx
* @create 2022/1/14-19:33
*/
public interface UseService {
//接口中的所有定义其实都是抽象的public
public abstract void run();// =void run();
void run2();
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
//常量
int AGE=99;//等价于 public static final int AGE2=99;
public static final int AGE2=99;
}
package com.study.oop10;
/**
* @author Yx
* @create 2022/1/14-19:36
*/
public class UseServiceImpl implements UseService,TimeService {
//抽象类:extends;
//类 可以实现接口,implements 接口
//实现了接口的类,就需要重写接口的方法
//多继承 利用接口实现多继承
@Override
public void run() {
}
@Override
public void run2() {
}
@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 time() {
}
}
package com.study.oop10;
/**
* @author Yx
* @create 2022/1/14-19:38
*/
public interface TimeService {
void time();
}
作用:
- 约束
- 定义一些方法,让不同的人实现
- public abstract
- public static final
- 接口不能被实例化, 接口中没有构造方法
- implements可以实现多个接口
- 必须要重申接口的方法;
6.12 内部类
- 内部类就是在一个类的内部再定义一个类,比如A类中定义了一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类
package com.study.oop11;
/**
* @author Yx
* @create 2022/1/14-19:47
*/
public class Outer {
private int id=20;
public void out(){
System.out.println ("这是外部类的方法");
}
public class Inner{
public void in(){
System.out.println ("这是外部类的方法");
}
public void getID(){
//获得外部类的私有属性
System.out.println (id);
}
}
}
package com.study.oop11;
/**
* @author Yx
* @create 2022/1/14-19:49
*/
public class Application {
public static void main(String[] args) {
//new
Outer outer=new Outer ();
//通过这个外部类来实例化内部类
Outer.Inner inner=outer.new Inner();
inner.in();
inner.getID ();
}
}
package com.study.oop11;
/**
* @author Yx
* @create 2022/1/14-19:47
*/
public class Outer {
public void method(){
class inner{
public void in(){};
}
}
}
class A{
//一个Java类中可以有多个class类,但是只能有一个public calss
}
package com.study.oop11;
import com.study.oop2.Person;
import com.sun.org.apache.bcel.internal.generic.NEW;
/**
* @author Yx
* @create 2022/1/14-19:58
*/
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();
}
6.13 异常机制
异常指程序运行中出现的不期而至的各种状况
异常发生在程序运行期间,它影响了正常程序执行流程。
三种异常:
- 检查性异常:最具代表的检查性错误是用户错误或问题引起的异常,这是程序员无法预见的。
- 运行时异常:运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
- 错误Error: 错误不是异常,而是脱离程序员控制的问题。
java把异常当做对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类
在Java ApI中已经定义了许多异常类,这些异常类分为两大类,错误Error和Exception
6.13.1Error
-
Error类对象由Java虚拟机生成抛出,大多数错误与代码编写者所执行的操作无关。
-
Java虚拟机运行错误(Virtual MachineError),当JVM 不再有继续执行的操作所需的内存资源时,将出现OutofMemoryError.这些异常发生时,Java虚拟机(JVM)一般会选择线程终止;
-
还有发生在虚拟机试图执行应用时,如类定义错误(NoClassDefFoundError)、链接错误(LinkageError).这些错误是不可查的,因为它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况
6.13.2 Exception
- 在Exception分支中有一个重要的子类RuntimeException(运行时异常)
- ArrayIndexOutOfBoundsException(数组下标越界)
- NullPointerException(空指针异常)
- ArithmeticException(算术异常)
- MissingResourceException(丢失资源)
- ClassNotFoundException(找不到类)等异常,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。
- 这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能的避免这类异常的发生
- Error 和Exception 的区别:Error 通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这类异常时,Java虚拟机(JVM)一般会选择终止线程;Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常
6.14 异常处理机制
- 抛出异常
- 捕获异常
异常处理的五个关键字:
- try、catch、finally、throw、throws
throws是用来声明一个方法可能抛出的所有异常信息,throws是将异常声明但是不处理,而是将异常往上传,谁调用我就交给谁处理。而throw则是指抛出的一个具体的异常类型
throws:用于声明异常,例如,如果一个方法里面不想有任何的异常处理,则在没有任何代码进行异常处理的时候,必须对这个方法进行声明有可能产生的所有异常(其实就是,不想自己处理,那就交给别人吧,告诉别人我会出现什么异常,报自己的错,让别人处理去吧)。
throw:就是自己进行异常处理,处理的时候有两种方式,要么自己捕获异常(也就是try catch进行捕捉),要么声明抛出一个异常(就是throws 异常~~)。
注意:
throw一旦进入被执行,程序立即会转入异常处理阶段,后面的语句就不再执行,而且所在的方法不再返回有意义的值!
package com.study.oop12;
/**
* @author Yx
* @create 2022/1/14-21:49
*/
public class Demo01 {
public static void main(String[] args) {
int a=1;
int b=0;
try {
if(b==0){// throw throws
throw new ArithmeticException();//主动抛出异常
}
} catch (Exception e) {
System.out.println (1);
e.printStackTrace ();//打印错误的信息
} finally {
}
//ctrl+alt+T
try {//监控区域
System.out.println ( a / b );
}catch (ArithmeticException e){//catch 捕获异常
System.out.println ("程序出现异常,变量b不能为0");
}finally {//处理善后工作
System.out.println ("finally");
}
//finally 可以不要finally
//假设要捕获多个异常: 从小到大!
try{
new Demo01 ().a ();
}catch (Error e){
System.out.println ("捕获error");
}
catch (Exception e){
System.out.println ("捕获Exception");
}
catch(Throwable t ){//catch(想要捕获的异常类型) 捕获异常
System.out.println ("捕获Throwable ");
}
}
public void a(){
b();
}
public void b(){
a ();}
//假设在方法中,处理不了这个异常,方法向上抛出异常
public void test(int a,int b)throws ArithmeticException{
if(b==0){
throw new ArithmeticException();//主动抛出异常,一般在方法中使用
}
System.out.println (a/b);
}
}
6.15 自定义异常
- 使用Java 内置的异常类可以描述在编程时出现的绝大部分异常情况。除此之外, 用户还可以自定义异常。用户自定义异常类,只需要继承Exception类即可。
- 在程序中使用自定义异常类,大体可以分为以下几个步骤:
- 创建自定义异常类
- 在方法中通过throw关键字抛出异常
- 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作
- 在出现异常方法的调用者中捕获并处理异常。
实际中的经验总结:
- 处理运行时异常时,采用逻辑去合理规避同时辅助 try -catch 处理
- 在多重代码块catch 块后面, 可以加一个catch(Exception)来处理可能会被遗漏的异常
- 对于不确定的代码,也可以加上try-catch,处理潜在的异常
- 尽量去处理异常,切忌只是简单的调用printStackTrace()去打印输出
- 具体如何处理异常,要根据不同的业务需求和异常去决定
- 尽量添加finally语句块去释放占用的资源
package com.study.oop13;
/**
* @author Yx
* @create 2022/1/14-23:30
*/
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);
}
}
}
package com.study.oop13;
/**
* @author Yx
* @create 2022/1/14-23:26
*/
//自定义的异常类
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 +
'}';
}
}