typora-root-url: C:\Users\13799\Pictures\Java
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ehwVPukB-1647855537848)(C:\Users\13799\AppData\Roaming\Typora\typora-user-images\image-20220103123746769.png)]
Java基础
一、Java面向对象基础
1、常识
Windows快捷命令:
- Ctrl+C:复制
- Ctrl+V:粘贴
- Ctrl+A:全选
- Ctrl+X:剪切
- Ctrl+Z:撤销
- windows+r+cmd:命令行窗口
- Ctrl+shift+esc:资源管理器
Dos命令:
- 打开CMD:
- 开始+系统+命令提示符
- windows+r+cmd:命令行窗口
-
常用Dos命令:(所有字符都得是英文半角)
- 磁盘块名 + : #切换盘块
- dir #查看当前盘所有文件目录
- cd + … #返回上一级
- cd + /d +路径 #跳转到目标路径
- cls #清除屏幕
- exit #推出
- ipconfig #查看电脑ip
- ping + 域名 #获得网站的ip
- md +目录名 #创建目录
- rd +目录名 #删除目录
- cd> +文件名 #创建文件
- del +文件名 #删除文件
2、java基础
JDK----Java开发环境
JRE---- Java运行环境
JVM----Java虚拟机,跨平台的基础
(向下包含)
1、常用快捷命令:
-
psvm:主函数(main函数)入口
public static void main(String[] args) { }
-
soutv:快速打印方法的参数
public String toLogin(String uname,String pwd){ System.out.println("uname = " + uname); System.out.println("pwd = " + pwd); return "main.jsp"; } }
-
sout:输出语句
System.out.println()//输出一个就换一行 System.out.print()//输出之后不换行 例1: public class Demo1 { public static void main(String[] args) { for (int i = 0; i < 9; i++) { System.out.print(i); } } }输出:012345678 例2: public class Demo2 { public static void main(String[] args) { for (int i = 0; i < 9; i++) { System.out.println(i); } } }输出:0 1 2 3 4 5 6 7 8
2、Java基础语法
1、注释:
说明代码的功能,规范性编码。
常用有三种:
-
单行注释:代码后面加上 //注释
-
多行注释:/* 注释 */
-
文档注释(JavaDoc):注释里面可以自己很多需要标注的东西,例如:作者、版本等等 /** 注释 */
/**
* @Author shkjahfjk
* @version 1.8
*/
2、标识符和关键字:
-
关键字:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xYiR4iYJ-1647855537849)(C:\Users\13799\AppData\Roaming\Typora\typora-user-images\image-20220109165209313.png)]
-
public:
-
private:
-
final:定义常量
-
static:定义类变量和静态方法,静态方法可以直接在同一个类中直接调用;
使用了static的方法会和类一起加载,而未使用的方法只有在类被实例化成对象后才会加载
-
break:强制退出循环,跳出所在的循环体,会继续执行循环体之后的代码
int i=0; while(i<100){ i++; if (i%10==0){ System.out.println("省略"); break;//强制退出循环,跳出所在的循环体,会继续执行循环体之后的代码 } System.out.print(i); } 输出:123456789省略
-
continue:退出此次循环,跳到循环体的开始条件处,再次执行循环
int i=0; while(i<50){ i++; if (i%10==0){ System.out.println("省略"); continue;//退出此次循环,跳到循环体的开始条件处,再次执行循环 } System.out.print(i); } 输出:123456789省略 111213141516171819省略 212223242526272829省略 313233343536373839省略 414243444546474849省略
-
return:方法的返回值,是一个方法中最后一句被执行的语句
-
-
标识符:
类名、变量名以及方法名都叫标识符
其书写规则有:
- 只能以字母、$、 _ 这三种开头
- 除开头外,可以用字母、$、_ 、数字任意组合
- 不能用关键字来作为类名、变量名或方法名
- 标识符是大小写敏感的(区分大小写)
- 一般不用中文或拼音做标识符
-
数据类型:Java是强类型语言,要求变量的使用要严格符合规定,所有变量都必须先定义(初始化),然后才能使用
- 基本类型:
- byte:1个字节
- short:短整型,2个字节
- int:整型,4个字节
- long:长整型,8个字节(须在定义的时候在数字后面加一个L用作区分,如:long num=30L;)
- float:单精度浮点数,4个字节(须在定义的时候在数字后面加一个F用作区分,如:float num=30.2F;)
- double:双精度浮点数,8个字节
- char:字符型,2个字节(char A=‘a’;)
- string:字符串,不是关键字,是一个类(string A=“abcdefg”;)
- boolean:布尔型,占一个比特位,只有true和false两种情况(0和1两种情况)
- 引用类型:
- 类
- 接口
- 数组
- 基本类型:
3、数据类型扩展:
-
不同进制:
- 八进制(O):如:O45
- 十六进制(OX):如:OX45
-
银行业务不能用浮点数类型比较,会有误差,要用数学工具类:BigDecimal
-
所有的字符本质上是数字,可以通过强制转换成数字。(即按照相应规则的编码方式,如:UTF-8)
-
转义字符:
- \t : 制表符
- \n : 换行
等等
4、类型转换:
Java中的不同类型数据运算时,要先转换成相同类型再来运算,转换顺序(由低到高):
byte、short、char -> int -> long -> float -> double
-
强制类型转换:
int a=8; float b=(float) a;//将int类型强转为float类型 short c=(short) a;//将int类型强转为short类型
注:强制转换,由高到低强转时可能溢出。
-
自动类型转换:
由编译器自动将低优先级类型转换为高优先级类型
int a=8; double c=a;//将int自动转换为double型
5、变量、常量、作用域:
-
变量:可以变化的量,每个变量都需要定义
-
每个变量必须声明其所属的数据类型
-
变量声明是一个完整的语句
-
变量名必须是合法的标识符
type 变量名 = 变量初始值 ; //变量定义的方法
-
-
常量:
通过final关键字来定义
public class Hello { final static int a=0;//final与static都是修饰符 static final int b=1;//修饰符不区分前后 public static void main(String[] args) { System.out.println(b); System.out.println(a); } }
-
作用域:
-
类变量:static 关键字声明的变量,跟实例变量的作用范围一样,但是不用通过对象来调用
public class Hello { static int a; public static void main(String[] args) { System.out.println(a);//跟局部变量类似,可直接调用 } }
-
实例变量:在类中,方法外声明的变量,从属于对象,必须通过类来调用
public class Hello { String name="yhx"; int age=0; public static void main(String[] args) { Hello hello=new Hello();//new一个Hello的对象hello System.out.println(hello.name);//通过hello对象来调用实例变量name } }
-
局部变量:在某一个方法内声明并起作用的变量
public class Hello { public static void main(String[] args) { int a=0;//局部变量 System.out.println(a);//直接调用 } }
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oHON8rZ8-1647855537849)(C:\Users\13799\AppData\Roaming\Typora\typora-user-images\image-20220114091531255.png)]
6、基本运算符:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LqkiqNHD-1647855537850)(C:\Users\13799\AppData\Roaming\Typora\typora-user-images\image-20220114092040417.png)]
-
%:取余运算,输出余数
public class Hello { public static void main(String[] args) { int a=9; int b=3; System.out.println(a%b); } } 输出余数: 输出结果为:0
-
关系运算符:返回值为true或false(布尔值)
-
自增、自减运算符:++、–
package Study; public class Hello { public static void main(String[] args) { int a=1; int d=1; int b=a++;//先给b赋值,再a自增 System.out.println("b="+b); System.out.println("a="+a); //输出:b=1,a=2 int c=++d;//先d自增,再给c赋值 System.out.println("d="+d); System.out.println("c="+c); //输出:d=2,c=2 } }
-
位运算:(二进制位的运算)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cZ5EvArE-1647855537850)(C:\Users\13799\AppData\Roaming\Typora\typora-user-images\image-20220114094555200.png)]
- &:与运算
- / :或运算
- ^:异或运算
- ~:取反(非运算)
- <<:算数左移(移一位等价于*2)
- 》:算数右移(移一位等价于/2)
-
连接符:
public static void main(String[] args) { int a=1; int d=1; int c=1; int b=1; System.out.println(a+b+" string类型 "+c+d); //在输出语句中:String类型前的+为加号,String后的+为连接符 //a+b中的+即为加号,c+d中的+即为连接符 //输出结果:2 string类型 11 }
-
三元运算符:(? :)
例:x?y:z
x为真,则执行y
x为假,则执行z
public static void main(String[] args) { int a=80; int b=50; String grade1=a<60?"不及格":"及格"; String grade2=b<60?"不及格":"及格"; System.out.println(grade1);//及格 System.out.println(grade2);//不及格 }
7、包机制:
- 包的本质是文件夹:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A3wgCij4-1647855537851)(C:\Users\13799\AppData\Roaming\Typora\typora-user-images\image-20220114100742997.png)]
-
一般利用公司域名的倒置为包名:
如:www.baidu.com
包名:com.baidu.www
-
为了使用某一个包内的成员,必须用import将其导入
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3qsITtnx-1647855537852)(C:\Users\13799\AppData\Roaming\Typora\typora-user-images\image-20220114102327185.png)]
8、JavaDoc生成文档:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YYsk2TOu-1647855537852)(C:\Users\13799\AppData\Roaming\Typora\typora-user-images\image-20220114102629220.png)]
3、Java流程控制
1、用户交互:Scanner对象(获取用户输入)
import java.util.Scanner;//引用scanner类
- 基础语法:
Scanner scanner=new Scanner(System.in);//基础语法
-
用hasNext()和hasNextLine()方法判断是否还有输入的数据,两个方法用法一致
-
用Scanner类的next()和nextLine()方法获取输入的字符串;
-
next()的例子:
import java.util.Scanner;//引用Scanner类
public class Hello {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);//创建一个扫描器对象,用于接受键盘输入
if(scanner.hasNext()){//利用hasNext()方法来判断是否还有输入
String str=scanner.next();//利用next()方法来接受输入
System.out.println(str);
}
scanner.close();//IO类最好在用完后手动关闭,以减少资源损耗
}
}
输入:hellow world
输出:hellow
- nextLine()的例子:
import java.util.Scanner;//引用Scanner类
public class Hello {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);//创建一个扫描器对象,用于接受键盘输入
if(scanner.hasNext()){//利用hasNext()方法来判断是否还有输入
String str=scanner.nextLine();//利用nextline()方法来接受输入
System.out.println(str);
}
scanner.close();//IO类最好在用完后手动关闭,以减少资源损耗
}
}
输入:hellow world
输出:hellow world
-
next()和nextLine()的异同:
next()方法一定要接收到有效的输入才能利用回车输出,有效输入前的空格会被自动省略,有效输入后的空格会导致输入在此退出,不能得到带空格的字符串
nextLine()方法可以得到回车键之前的所有输入
-
精简后的代码:(不用判断是否有输入)
import java.util.Scanner;//引用Scanner类 public class Hello { public static void main(String[] args) { Scanner scanner=new Scanner(System.in);//创建一个扫描器对象,用于接受键盘输入 String str=scanner.nextLine();//利用nextline()方法来接受输入 System.out.println(str); scanner.close();//IO类最好在用完后手动关闭,以减少资源损耗 } }
-
进阶用法:scanner.next()方法有许多种
比如:scanner.nextInt()等
2、顺序结构:
Java的基本结构,从上而下依次执行Java语句
3、if选择结构:
-
if单选择结构:
if(判断条件)
{
判断条件为真时,执行此处代码
}
-
if双选择结构:
if(判断条件)
{
判断条件为真时,执行此处代码
}
else{
判断条件为假时,执行此处代码
}
-
if多选择结构:
if(判断条件1)
{
判断条件1为真时,执行此处代码
}
else if(判断条件2)
{
判断条件2为真时,执行此处代码
}
else if(判断条件3)
{
判断条件3为真时,执行此处代码
}
…
else{
所有判断条件都为假时,执行此处代码
}
-
if嵌套结构
if(判断条件1)
{
判断条件1为真时,执行此处代码
if(判断条件2)
{
判断条件2为真时,执行此处代码
}
}
4、Switch多选择结构:
switch()中的判断条件只能是byte、short、int或char类型;从1.7版本开始也支持String类型
在Java程序的执行中,将String类型的数据转换成对应的hasCode来进行的判断,不同的字符串对应不同的数字
char grade='c';
switch (grade){
case 'a':
System.out.println("优秀");
break;//每一个case后面都需要一个break。以避免将后面的case都执行了
case 'b':
System.out.println("良好");
break;
case 'c':
System.out.println("及格");
break;
default://以上所有的case都匹配不了的时候执行
System.out.println("未知成绩");
}
输入:c
输出:及格
5、循环结构:
-
while循环结构:最基本的循环结构
先判断后执行
while(判断条件)
{
只要判断条件为真,则执行此处语句
}
//输出0~100
int i=0;
while(i<=100){
System.out.println(i);
i++;
}
-
do-while循环结构:至少会执行一次
先执行后判断
先执行一次,在进行while条件的判断
do{
代码执行区域
}
while(判断条件);
int i=0; do { System.out.println(i); i++; }while (i>1); //本来是要输出大于1的数,但是用do-while也会输出0 输出:0
-
for循环结构:最有效最直接
for(初始化;判断条件;更新初始值){
符合判断条件时,执行此处代码语句
}
判断条件为假时,终止循环
//输出0~99的数
for (int i=0;i<100;i++){
System.out.println(i);
}
4、Java方法
1、方法的定义:
-
方法的定义:(命名规则:首字母小写及驼峰原则)
一个由一些语句组成的,能实现一些功能的模块,等价于C++中的函数
定义:
修饰符 返回值类型 方法名(参数类型 形参名){
方法体
…
返回值(必须与返回类型一致)//如果返回值类型为void,返回值为 return;
}
例:
public static void main(String[] args) { int x=5; int y=6; int sum=add(x,y);//调用add()方法 System.out.println(sum); } //定义了一个加法方法,static关键字的使用是为了方便调用 public static int add(int a,int b){ return a+b; }
2、方法的调用:
-
当方法不用static修饰时,可以用new一个对象,然后用:
“new 对象();
对象名.方法名(参数) ”
来调用方法
public class Demo1 { public static void main(String[] args) { int[] a = {2, 5, 154, 45, 1245, 187, 6, 75, 4};//初始无序数组 Demo1 demo1=new Demo1();//要调用类Demo1中的方法sort,就得先new一个Demo1的对象,此处将该对象命名为demo1 int[] array = demo1.sort(a);//利用对象名.方法名来调用执行冒泡排序算法的方法 System.out.print(Arrays.toString(array));//利用Arrays.toString()方法在输出排序之后的数组 } //冒泡排序(将大数排在首位) public int[] sort(int[] array) { int temp = 0;//交换元素时用到的中间变量 //外层循环,数组共有array.length个元素,则最多只需要array.length-1次遍历,所以i < array.length //每一次都会将最大的数放在array[i]处,i从0依次增大到最大值,即array.length-1 for (int i = 0; i < array.length; i++) { //内层循环,将已确定次序的大数排出后,所以每一次内循环需要比较的数有j < array.length - 1 - i个,再对剩余的不确定数组比对排序 for (int j = 0; j < array.length - 1 - i; j++) { if (array[j] < array[j + 1]) { temp = array[j]; array[j] = array[j + 1]; array[j + 1] = temp; } } } return array; } }
-
当方法用static修饰时,可以直接调用
public static void main(String[] args) { int[] array = sort(a);//sort为static来修饰的方法,可以直接调用 } public static int[] sort(int[] array) { //方法体 }
-
当方法的返回值不为空时,方法调用通常被当作一个值
例如:
int sum=add(x,y);//方法调用被当做一个值 public static int add(int a,int b){ return a+b; }
-
当方法的返回值为空时,方法调用通常是一个语句
例如:
System.out.println(sum);//方法调用为一个语句,调用的是println()方法
-
3、方法的重载:
- 重载就是在同一个类中,拥有方法名相同、但形参不同的方法
//int型的加法add
public static int add(int a,int b){
return a+b;
}
//double型的加法add
public static double add(double a,double b){
return a+b;
}
-
方法重载必须要遵守的原则:
- 方法名必须相同
- 参数列表必须不同(可以是:参数个数、参数类型、参数排列顺序不同)
- 方法的返回类型可以相同也可以不相同
- 仅仅返回类型不同,不能称之为方法的重载
-
可变参数:
对一个类型的参数不指定特定的个数
对double类型的参数不指定个数,注意这种参数只能放在形参列表的最后一个 public static void add(double...numbers){ }
4、递归:
一个方法自己调用自己
递归结构包括两个部分:
- 递归头:不再调用自身方法的条件
- 递归体:调用自身方法的条件
public static void main(String[] args) {
int a=f(5);
System.out.println(a);
}
public static int f(int n){
if (n==0){
return 1;
}
else if (n==1){
return 1;
}
else{
return n*f(n-1);//递归调用本身
}
}
5、Java数组
1、数组的声明和创建:
相同数据类型的数据的有序集合;通过数组下标来访问数组内的某一个数据
注意:数组下标由0开始
-
声明一个数组:
数据类型【】+数组名;
-
创建一个数组:
数据类型【】+数组名=new 数据类型【数组长度】;
例子:
int[] array;//声明一个int型数组,array
array=new int[5];//利用new方法,来创建array数组
int[] array1=new int[5];//可将上述两句话统一成一句话,将数组的声明和创建一起完成
System.out.println(array.length);//数组名.length;可以获取数组长度
输出:5
2、三种数组的初始化以及内存分析:
- Java的内存分为:
- 堆区:存放new的对象和数组;可以被所有的线程共享,不会存放别的对象引用
- 栈区:存放基本变量类型(包含此基本类型的具体数值);引用对象的变量(会存放这个引用在堆里的具体地址)
- 方法区:可以被所有线程共享,包含了所有的class和static变量
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pkUgMk8W-1647855537853)(…/JavaSE/java1.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jfP3gvNM-1647855537853)(…/JavaSE/屏幕截图 2022-01-21 100700.png)]
-
数组的三种初始化方法:
-
静态初始化:直接给数组赋值
int[] a={1,2,3};//静态初始化,将数组的大小与每一个下标对应的值都给出
-
动态初始化:数组的具体值灵活定义
//动态初始化 int[] b=new int[3];//先将数组给声明并创建大小 //再给每个数组元素分别定义数值 b[0]=1; b[1]=2; b[2]=3;
-
数组的默认初始化:
数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化
-
3、数组下标越界及数组小结:
- 数组小结
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IqCyeeEZ-1647855537854)(…/JavaSE/QQ截图20220313145151.png)]
-
数组下标越界:
数组下标的合法区间:【0,length-1】,超出这个范围则会越界报错。
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4//数组下标越界报错 at Study.Demo1.main(Demo1.java:13)//出错的代码行数
4、多维数组:
-
二维数组:
一个特殊的数组,每一个元素都是一个数组
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TLb05O89-1647855537854)(…/JavaSE/QQ截图20220313145243.png)]
-
定义二维数组:
- 静态定义二维数组:
public static void main(String[] args) { int[][] a={{1,2},{3,4}};//静态初始化,a[i]为一个数组,a[i][j]为第i+1个数组的第j+1个元素 for (int i=0;i<a.length;i++){ for(int j=0;j<a[i].length;j++) { System.out.print(a[i][j]); } System.out.println(); } } 输出:12//数组a[0]中的元素 34//数组a[1]中的元素
- 动态定义二维数组:
int[][] a=new int[2][2];//动态初始化,只给出一维数组的个数,以及每一个一维数组的元素个数 //a[i]为一个数组,a[i][j]为第i+1个数组的第j+1个元素 //以循环遍历的方式给二维数组的每一个元素赋值,从0开始 int n=0; for (int i=0;i<a.length;i++){ for (int j=0;j<a[i].length;j++){ a[i][j]=n; n++; } } //循环输出二维数组中的每一个元素 for (int i=0;i<a.length;i++){ for(int j=0;j<a[i].length;j++) { System.out.print(a[i][j]); } System.out.println(); }
5、Arrays类:
Java提供的一个关于数组的工具类
例如:
//Arrays.toString()方法,可以将a数组打印出来
System.out.println ( Arrays.toString(a));
6、冒泡排序:
public static void main(String[] args) {
int[] a = {2, 5, 154, 45, 1245, 187, 6, 75, 4};//初始无序数组
int[] array = sort(a);//调用冒泡排序算法
System.out.print(Arrays.toString(array));//利用Arrays.toString()方法在输出排序之后的数组
}
//冒泡排序(将大数排在首位)
public static int[] sort(int[] array) {
int temp = 0;//交换元素时用到的中间变量
//外层循环,数组共有array.length个元素,则最多只需要array.length-1次遍历,所以i < array.length
//每一次都会将最大的数放在array[i]处,i从0依次增大到最大值,即array.length-1
for (int i = 0; i < array.length; i++) {
//内层循环,第i大的数已排好序,所以每一次内循环需要比较的数只有有j < array.length - 1 - i个
for (int j = 0; j < array.length - 1 - i; j++) {
if (array[j] < array[j + 1]) {//如果要求将小数排在首位,则array[j] > array[j + 1]即可
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
//将最终生成的数组返回,即为冒泡排序后的数组
return array;
}
7、稀疏数组:
用来存贮稀疏矩阵
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M7r7Krly-1647855537855)(…/JavaSE/QQ截图20220313145313.png)]
6、Java类与对象
1、什么是面向对象(oop):
- 以类的方式组织代码,以对象来封装数据
- 三大特性:
- 封装:将数据包装起来,对外只提供接口进行访问
- 继承:父类和子类之间存在继承关系,子类具有父类的所有相关功能
- 多态:
2、引用传递和值传递:
public class Demo2 {
public static void main(String[] args) {
Person person=new Person();
System.out.println(person.name);//输出null
change(person);
System.out.println(person.name);//输出yhx
}
public static void change(Person person){
//person是一个对象:指向的是--->Person person=new Person();是一个具体的人,所以可以改变属性name
person.name="yhx";
}
}
//新建一个class,(注意,一个.java中只能有一个public class);没有public修饰符的类只能在该.java文件中调用
class Person{
String name;//Person的属性
}
3、类与对象的关系:
-
类:是一个抽象的数据类型,是对某一类事物的整体描述、定义,但是并不能代表某一个具体的事务
//Person 就是一个类 class Person{ String name;//Person的属性 }
-
对象:是抽象概念的集体实例
//fact_person就是一个对象
public class Demo2 {
public static void main(String[] args) {
Person fact_person=new Person();//利用new关键字来创建一个Person类的实例对象fact_person
System.out.println(fact_person.name);//输出null
change(fact_person);
System.out.println(fact_person.name);//输出yhx
}
public static void change(Person person){
//person是一个对象:指向的是--->Person person=new Person();是一个具体的人,所以可以改变属性name
person.name="yhx";
}
}
4、构造器详解:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nKqxwdQw-1647855537856)(…/JavaSE/QQ截图20220313145339.png)]
//Person类,被Demo2类调用
package Study;
public class Person {
String name;//属性
//一个类什么也不写也会有一个方法,这个方法就是构造器(编译器会隐式构造)
//显示定义该构造器 (构造器的名字与类名相同,且不能有返回值)
public Person(){
}
//一旦显示定义一个有参构造器,则必须将无参构造器显示构造出来
public Person(String name){
this.name=name;
}
}
//Demo2类,里面有主函数
package Study;
public class Demo2 {
public static void main(String[] args) {
//使用new关键字时,就是去Person类中去使用构造器构造一个实例出来
Person yhx=new Person();//new一个无参构造器的Person对象:yhx
Person xry=new Person("我是许润云");//new一个有参构造器的Person对象:xry
System.out.println(yhx.name);//无参构造器只生成了一个对象,对象的属性为初始值
System.out.println(xry.name);//有参构造器不仅生成了一个对象,还在方法内部对name属性赋了值
}
}
输出:null
我是许润云
/*总结:
构造器:
1、名字和类名相同
2、没有返回值
作用:
1、new方法生成对象时就是在调用构造器
2、可以利用有参构造器给对象初始化值
注意:
当定义了一个有参构造器时,如果还想调用无参构造器,必须把无参构造器显式的构造出来
*/
private Course course;
//当类中有类属性或集合属性的时候,在构造方法中需要声明该类的对象或者集合的对象,
//例如此处的course为Course类的类属性,因此在构造方法中需要new一个Course的对象
public Stu_Course() {
this.course=new Course();
}
public Stu_Course(Date time) {
this.time = time;
this.course=new Course();
}
-
可以通过alt+insert来快捷创建构造器:
先alt+insert,再点击Constructor,进去选择自己需要的参数组合即可
最下面的Select None则表示生成无参构造器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kzoiY9xK-1647855537856)(…/JavaSE/QQ截图20220313145416.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JKT4u8s7-1647855537857)(…/JavaSE/QQ截图20220313145422.png)]
5、创建对象的内存分析:(栈区、堆区、方法区)
- 堆区:存放new的对象和数组;可以被所有的线程共享,不会存放别的对象引用
- 栈区:存放基本变量类型(包含此基本类型的具体数值);引用对象的变量(会存放这个引用在堆里的具体地址)
- 方法区:可以被所有线程共享,包含了所有的class和static变量(也在堆里面)
//Pet类,被调用生成对象
package Study;
public class Pet {
public String name;
public int age;
public void shout(){
System.out.println("叫了一声:哎哟~");
}
}
//含有主函数
package Study;
public class Demo2 {
public static void main(String[] args) {
Pet dog=new Pet();
dog.name="旺旺";
dog.age=1;
dog.shout();
Pet cat=new Pet();
}
}
该程序的内存分配示意图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NI3jiKSX-1647855537857)(…/JavaSE/QQ截图20220313145453.png)]
6、类与对象的小结:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zXx5bL9z-1647855537858)(…/JavaSE/QQ截图20220313145503.png)]
7、Java三大特性(封装、继承、多态)
1、封装:(高内聚、低耦合)
-
高内聚:类的内部数据操作细节由自己完成,不允许外部干涉
-
低耦合:仅仅暴露少量的方法给外部使用
-
封装即为数据的隐藏,禁止直接访问一个对象中数据的实际表示,应该通过操作接口来访问,即信息隐藏
-
封装的好处:
- 提高程序的安全性,保护数据
- 隐藏代码的实现细节
- 统一接口
- 系统的可维护性增加
-
注意:属性要私有化, 利用get/set 方法来调用
get/set方法生成快捷方式:先Alt+insert,再选择Getter或Setter
get/set方法:内部还可以设计一些条件判断的语句
//调用的类
package Study;
//类
public class Demo3 {
//属性(封装一般是对于属性来说):私有属性,其他的类不再能够直接调用这些私有属性,只能通过方法来调用
private String name="老杨";
private int age;
private char sex;
//get 方法:获得这个属性数据,为外部提供一个调用该属性的接口
public String getName(){
return this.name;
}
//set 方法:给私有属性设置值,为外部提供一个修改本类中私有属性的接口
public void setName(String name){
this.name=name;
}
}
//主函数所在的类
package Study;
public class Demo2 {
public static void main(String[] args) {
Demo3 student=new Demo3();
String name1=student.getName();//通过get方法获得私有属性
System.out.println(name1);
student.setName("杨辉祥");//通过set方法为私有属性设置值
String name2=student.getName();//通过get方法获得新的属性值
System.out.println(name2);
}
}
输出:老杨
杨辉祥
2、继承
2.1、继承:
- 继承的本质是对某一批类的抽象,将它们共同的特点提取出来,其他的类可以继承这些抽象类的所有功能
- 关键字是:extends
- 子类是父类的扩展,子类继承父类,子类可以继承拥有父类的所有公共方法和公共属性(public修饰的)
- new一个子类的对象时,除了启动自身的构造器,还会自动的启动父类的构造器
//父类
package Study;
public class Person {
//父类的公共方法可以被子类继承
public void say(){
System.out.println("我是你爹");
}
}
//子类
package Study;
//学生也是人,是人的子类
public class Student extends Person {
//没有方法,但是继承了父类的公共方法
}
//主函数
package Study;
public class Demo2 {
public static void main(String[] args) {
Student student=new Student();//生成一个学生对象
student.say();//学生类Student可以调用父类Person中的公共方法
}
}
输出:我是你爹
- 在Java中,所有类都默认继承Object类
- Java中只有单继承,没有多继承(也就是只能由一个直接父类)
2.2、super/this:
-
super:调用父类中的公共属性或公共方法
-
this:调用当前类中的属性或方法
-
例1:super/this调用属性
//父类 package Study; public class Person { protected String name="yhx";//父类的属性 } //子类 package Study; //学生也是人,是人的子类 public class Student extends Person { private String name="rxy";//子类的属性 public void test(String name){ System.out.println(name);//name表示当前方法被调用时传过来的实参 System.out.println(this.name);//this.name表示调用当前类的属性name System.out.println(super.name);//super.name表示调用父类中的属性name } } //主函数 package Study; public class Demo2 { public static void main(String[] args) { Student student=new Student(); student.test("马牛逼");//调用Student类中的test()方法,并且将实参传送过去 } } 输出:马牛逼 rxy yhx
-
例2:super/this调用方法
//父类 package Study; public class Person { //父类的print()方法 public void print(){ System.out.println("我是你爹"); } } //子类 package Study; //学生也是人,是人的子类 public class Student extends Person { //子类的print()方法 public void print(){ System.out.println("我是儿子"); } public void test(){ print();//调用本类中的print()方法 this.print();//调用本类中的print()方法 super.print();//调用父类中的print()方法 } } //主函数 package Study; public class Demo2 { public static void main(String[] args) { Student student=new Student(); student.test();//调用Student类中的test()方法 } } 输出:我是儿子 我是儿子 我是你爹
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GhxGH7v4-1647855537858)(…/JavaSE/QQ截图20220313145546.png)]
2.3、方法重写(与方法重载不同):
- 重写都是指方法,与属性无关
- 重写了的方法,一旦执行,执行的就是被重写后的方法体
- 只能子类重写父类的public方法
- 不能被重写的方法:
- static修饰的静态方法
- final修饰的常量
- private修饰的私有方法
- 为什么需要重写:
- 父类的功能,子类不一定需要,或者不一定能够满足
- 快捷键:先Alt+Insert,再选择override
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QNrO7FJA-1647855537865)(…/JavaSE/QQ截图20220313145615.png)]
3、多态(只是方法才能说多态)
-
一个对象的实际类型是确定的;例如:new Student();//实际类型即为Student类
-
但是实际类型可以指向的引用类型就不确定了,可以指向父类或者祖宗类
例如:
Student s1 = new Student();//s1的实际类型为Student,指向的引用类型为Student Person s2 = new Student();//s2的实际类型为Student,指向的引用类型为其父类Person Object s3 = new Student();//s3的实际类型为Student,指向的引用类型为其祖宗类Object
//父类
package com.yhx.demo_duotai;
public class Person {
public void run(){
System.out.println("父类run");
}
}
//子类
package com.yhx.demo_duotai;
public class Student extends Person {
@Override
public void run() {
System.out.println("子类run");
}
public void eat(){
System.out.println("子类eat");
}
}
//主函数
package com.yhx;
import com.yhx.demo_duotai.Person;
import com.yhx.demo_duotai.Student;
public class Main_class {
public static void main(String[] args) {
Student s1 = new Student();//s1的实际类型为Student,指向的引用类型为Student
Person s2 = new Student();//s2的实际类型为Student,指向的引用类型为其父类Person
Object s3 = new Student();//s3的实际类型为Student,指向的引用类型为其祖宗类Object
//对象能调用什么方法,主要看对象定义等式的左边部分所表示的类有哪些可执行的方法(包括继承过来的方法)
s1.run();
s2.run();//子类重写了父类的方法,所以执行子类的方法体
s1.eat();
s2.eat();//出错了,Person类中没有eat()方法,父类的对象只可以指向子类被重写了的方法,不可以调用子类独有的方法
}
}
8、Java扩充
1、instanceof关键字和类型转换:
-
类型转换:
/* 1、父类的引用指向子类的对象 2、把子类转换成父类,向上转型,可以自动转换,会丢失自己的一些方法 3、把父类转换成子类,向下转型,需要强制转换 */ //类型之间的转换:父--》子 (高级--》低级) Person s1 = new Student();//对象s1为Person类型(父类的引用指向了子类的对象) //方法一:将s1转变成Student类型,那么转换后的对象就可以使用Student类中的方法了 Student student=(com.yhx.demo_duotai.Student)s1;//括号内写出强转的类即可 student.go(); //方法二:或者可以这样强行转换类型 ((Student)s1).go(); //子类转换成父类,会丢失自己的一些方法 Student student1=new Student(); student1.go(); Person person=student1;//将student1转换成父类Person,子类转换成父类可以自动转换
-
Instanceof
判断两个类之间是否有父子关系,判断一个对象是什么类型的
//Object》Person》Student //Object》Person》Teacher //Object》String Object object=new Student();//object对象为Object类型 System.out.println(object instanceof Student);//true,Object类是Student类的父类 System.out.println(object instanceof Person);//true,Object类是Person类的父类 System.out.println(object instanceof Object);//true,Object类是Object类的父类 System.out.println(object instanceof Teacher);//false,Object类不是Tercher类的父类 System.out.println(object instanceof String);//false,Object类不是String类的父类
2、static详解:
-
静态属性:
private static int age;//静态变量 private double score;//非静态变量 public static void main(String[] args) { Student s1=new Student(); System.out.println(Student.age);//静态变量可以直接使用类名调用,也可以利用对象调用 System.out.println(s1.score);//非静态变量要先新建一个对象,通过对象调用
-
静态方法:
package com.yhx.demo_static; public class Student { public static void main(String[] args) { Student.go();//静态方法可以直接调用 Student s1 = new Student(); s1.run();//非静态方法只能通过对象调用 } //非静态方法 public void run(){ System.out.println("run"); } //静态方法 public static void go(){ System.out.println("go"); } }
-
静态代码块
package com.yhx.demo_static; public class Person { //每一次对象生成的时候,在构造器之前执行 //可以用来给对象的生成赋一些初值 { System.out.println("匿名代码块"); } //静态代码块 //在类的加载的时候就执行,在匿名代码块和构造器之前执行,只会执行一次 static { System.out.println("静态代码块"); } public Person() { System.out.println("构造器"); } public static void main(String[] args) { Person person1 = new Person(); System.out.println("================================="); Person person2 = new Person(); } } 输出: 静态代码块 匿名代码块 构造器 ================================= 匿名代码块 构造器
3、抽象类:
/*
抽象类的特点:
1、不能new这个抽象类,只能靠子类去实现它
2、抽象方法必须在抽象类中
3、抽象类也可以写普通方法
*/
package com.yhx.demo_abstractClass;
//抽象类
//用abstract关键字来修饰class的类即为抽象类
public abstract class Action {
//用abstract来修饰方法名,即为抽象方法
//抽象方法,只有方法名字,没有方法体
public abstract void doSomething();
}
4、接口:
声明接口的关键字是interface,声明类的关键字是class
-
接口的本质是契约,如同我们的法律,制定好了就要去遵守
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uRWXOKbK-1647855537866)(…/JavaSE/QQ截图20220313145652.png)]
//接口1
package com.yhx.demo_interface;
//定义接口的关键字:interface
public interface UserService {
//接口定义的所有属性都是一个常量,默认为常量(public static final);而且一般不在接口中定义属性
int age=99;
//接口中的所有方法的定义都是抽象的,默认为 public abstract
//接口的方法都只有定义,没有具体实现;因此需要一个类来实现接口的方法
public abstract void add(String name);
void delete(String name);
void insert(String name);
void select(String name);
}
//接口2
package com.yhx.demo_interface;
public interface TimeService {
void timer();
}
//实现接口的类
package com.yhx.demo_interface;
//一个类通过关键字:implements加上一个接口,来实现一个接口
//一个类可以实现多个接口,只要将所有接口的方法都重写即可
public class UerServiceImpl implements UserService,TimeService{
//要实现一个接口,就必须在类中重写接口的所有方法
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void insert(String name) {
}
@Override
public void select(String name) {
}
@Override
public void timer() {
}
}
5、多种内部类:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mz35a9Q3-1647855537866)(…/JavaSE/QQ截图20220313145715.png)]
1、成员内部类
- 内部类可以调用外部类的私有属性和私有方法
//成员内部类的定义
package com.yhx.demo_insideClass;
public class Outer {
//外部类的私有属性
private int id=10;
//外部类的公共方法
public void out(){
System.out.println("这是外部类的方法");
}
//内部类:定义在一个类内部的类;定义方法和外部类一样
public class Inner{
//内部类的方法
public void in(){
System.out.println("这是内部类的方法");
}
//内部类可以操作外部类的私有属性和私有方法
public void getId(){
System.out.println(id);
}
}
}
//主函数
package com.yhx;
import com.yhx.demo_insideClass.Outer;
public class Main_class {
public static void main(String[] args) {
Outer outer = new Outer();//实例化一个外部类的对象
//通过外部类的对象来实例化内部类的对象
Outer.Inner inner = outer.new Inner();
inner.in();
inner.getId();
}
}
输出:
这是内部类的方法
10
2、静态内部类
package com.yhx.demo_insideClass;
public class Outer {
//外部类的私有属性
private int id=10;
//外部类的公共方法
public void out(){
System.out.println("这是外部类的方法");
}
//静态内部类:定义在一个类内部的类,加了一个static关键字
//静态内部类不可以操作外部类的非静态私有属性和非静态私有方法
public static class Inner{
//内部类的方法
public void in(){
System.out.println("这是内部类的方法");
}
}
}
3、局部内部类
写在外部类的方法中的类
package com.yhx.demo_insideClass;
//外部类
public class Outer {
//外部方法
public void A(){
//外部方法中写的内部类:局部内部类
class Inner{
//内部方法
public void in(){
}
}
}
}
4、匿名内部类
package com.yhx.demo_insideClass;
public class Test {
public static void main(String[] args) {
//没有名字初始化类,不用将实例保存到变量中
new A().eat();
//没有名字初始化实现接口的类
new UserService(){
//重写接口的方法
@Override
public void hello() {
}
};
}
}
class A{
public void eat(){
System.out.println("这是A中的eat方法");
}
}
interface UserService{
void hello();
}
9、异常
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gETiHsHR-1647855537867)(…/JavaSE/QQ截图20220313145736.png)]
1、Java异常体系结构:
- Java把异常当作对象来处理,并且定义了一个基类java.lang.Throwable作为所有异常的超类。
- 在Java API中已经定义了许多异常类,这些异常类分为错误Error和异常Exception这两大类。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yCR94cZZ-1647855537867)(…/JavaSE/QQ截图20220313145754.png)]
- 错误Error:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P3LhGUqO-1647855537868)(…/JavaSE/QQ截图20220313145800.png)]
- 异常Exception:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rpM7i3gH-1647855537869)(…/JavaSE/QQ截图20220313145805.png)]
2、异常处理机制:
异常处理的五个关键字:try、catch、finally、throw、throws
-
捕获异常:(try、catch、finally)
try—catch—finally快捷生成方式:先选中要捕捉异常的代码,再Ctrl+Alt+T,然后在下拉框中选择要生成的结构
package com.yhx.demo_exception;
public class Demo1 {
public static void main(String[] args) {
//关键字try用来监控某一代码块是否有异常
try{
Demo1 demo1 = new Demo1();
demo1.A();
}
//一旦出现了catch后面括号中的错误类型,就执行下面区域的代码
//如果try中的代码出现的错误不是catch后面括号中的错误类型,就捕捉不到该异常
//Exception类型的异常是所有异常的父类,如果括号中是Exception则可以捕获所有类型的异常
//catch可以跟if—else一样有多层判断,而且判断范围是Error<Exception<Throwable;小的判断范围要写在大的范围的前面
catch (Error e){
System.out.println("这是一个错误");
}
catch (Exception e){
System.out.println("这是一个异常");
}
catch (Throwable e){
System.out.println("这是一个Throwable");
}
//不管异常监控区域是否出现错误,都会执行此处代码;用来进行善后的工作
finally {
System.out.println("程序异常检测完毕");
}
/*
1、try和catch必须成对出现
2、finally可有可无,可以用来处理一些善后工作
*/
}
public void A(){
B();
}
public void B(){
A();
}
}
- 抛出异常:(throw、throws)
package com.yhx.demo_exception;
public class Demo2_throwException {
public static void main(String[] args) {
new Demo2_throwException().test(1,0);
}
//假设该方法中有出现异常的条件,就可以主动抛出这个异常
public void test(int a,int b){
if (b==0){
//主动抛出异常:throw
//一般在方法中使用,即使并未实际运行a/b,也可以使它主动抛出相应的错误
throw new ArithmeticException();
}
}
}
-
异常处理的好处:
可以在catch代码块里面解决掉可以预见的一些异常,使得程序发生一些可预见错误的时候不用终止程序,而是按照catch中的处理方法继续运行程序
3、自定义异常:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QhQfGesV-1647855537869)(…/JavaSE/QQ截图20220313145848.png)]
package com.yhx.demo_exception;
//自定义异常类,只需要将自己创建的类继承Exception类即可
public class Demo4_myException extends Exception {
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rXBCBn83-1647855537870)(…/JavaSE/QQ截图20220313145913.png)]
10、泛型:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lCXRHMAg-1647855537870)(…/JavaSE/QQ截图20220313145931.png)]
即加了泛型之后,实际传入的数据类型一定要和规定好的泛型一致;也可以使用来表示匹配所有类型
10.1泛型类:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DRbdMJcE-1647855537871)(…/JavaSE/QQ截图20220313145952.png)]
/*
声明泛型类的对象的时候:一定要指明该对象的类型
例如:
Test2<String> test=new Test2<String>();
*/
package com.yang.Demo1;
public class Test2<T>{
private T a;
public T getA() {
return a;
}
public void setA(T a) {
this.a = a;
}
}
10.2泛型方法:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tcJ0PYJT-1647855537871)(…/JavaSE/QQ截图20220313150009.png)]
package com.yang.Demo1;
public class Test3 {
public static void main(String[] args) {
Generics g = new Generics();
g.run("阿巴阿巴");
g.run(1234);
g.run(true);
}
}
class Generics{
//定义一个泛型方法
public <T> void run(T t){
System.out.println(t);
}
}
10.3泛型接口:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PIFgQ3yT-1647855537872)(…/JavaSE/QQ截图20220313150028.png)]
//泛型接口的定义
package com.yang.Demo2;
public interface testInterface <T> {
void run(T t);
}
//泛型接口的实现类
package com.yang.Demo2;
public class testInterfaceImpl<T> implements testInterface<T>{
@Override
public void run(T t) {
System.out.println(t);
}
}
//主函数
package com.yang.Demo2;
public class Test {
public static void main(String[] args) {
testInterfaceImpl<String> A = new testInterfaceImpl<>();
A.run("阿巴阿巴");
testInterfaceImpl<Integer> B = new testInterfaceImpl<>();
B.run(10);
}
}
//假设该方法中有出现异常的条件,就可以主动抛出这个异常
public void test(int a,int b){
if (b==0){
//主动抛出异常:throw
//一般在方法中使用,即使并未实际运行a/b,也可以使它主动抛出相应的错误
throw new ArithmeticException();
}
}
}
- 异常处理的好处:
可以在catch代码块里面解决掉可以预见的一些异常,使得程序发生一些可预见错误的时候不用终止程序,而是按照catch中的处理方法继续运行程序
###### 3、自定义异常:
[外链图片转存中...(img-QhQfGesV-1647855537869)]
```Java
package com.yhx.demo_exception;
//自定义异常类,只需要将自己创建的类继承Exception类即可
public class Demo4_myException extends Exception {
}
[外链图片转存中…(img-rXBCBn83-1647855537870)]
10、泛型:
[外链图片转存中…(img-lCXRHMAg-1647855537870)]
即加了泛型之后,实际传入的数据类型一定要和规定好的泛型一致;也可以使用来表示匹配所有类型
10.1泛型类:
[外链图片转存中…(img-DRbdMJcE-1647855537871)]
/*
声明泛型类的对象的时候:一定要指明该对象的类型
例如:
Test2<String> test=new Test2<String>();
*/
package com.yang.Demo1;
public class Test2<T>{
private T a;
public T getA() {
return a;
}
public void setA(T a) {
this.a = a;
}
}
10.2泛型方法:
[外链图片转存中…(img-tcJ0PYJT-1647855537871)]
package com.yang.Demo1;
public class Test3 {
public static void main(String[] args) {
Generics g = new Generics();
g.run("阿巴阿巴");
g.run(1234);
g.run(true);
}
}
class Generics{
//定义一个泛型方法
public <T> void run(T t){
System.out.println(t);
}
}
10.3泛型接口:
[外链图片转存中…(img-PIFgQ3yT-1647855537872)]
//泛型接口的定义
package com.yang.Demo2;
public interface testInterface <T> {
void run(T t);
}
//泛型接口的实现类
package com.yang.Demo2;
public class testInterfaceImpl<T> implements testInterface<T>{
@Override
public void run(T t) {
System.out.println(t);
}
}
//主函数
package com.yang.Demo2;
public class Test {
public static void main(String[] args) {
testInterfaceImpl<String> A = new testInterfaceImpl<>();
A.run("阿巴阿巴");
testInterfaceImpl<Integer> B = new testInterfaceImpl<>();
B.run(10);
}
}