Java学习笔记_2021

本文使用typora直接上传,由于没有设置图墙,图片无法显示。
如需笔记,可私信博主

1.基础知识

1.1Java语言概述

知识点内容
特点跨平台性JVM(java virtual machine,java虚拟机)
核心机制Java虚拟机(JVM)
垃圾收集机制Java还是可能出现内存泄漏、内存溢出问题

1.2JDK、JRE、JVM关系

名称内容
JDK- Java开发工具包(Java Development Kit)
- 包括:JRE、开发工具
- 开发工具:编译工具(javac.exe),打包工具(jar.exe)
JRE- Java运行环境(java runtime environment)
- 包括:JVM、Java核心类库
- 不可开发,可以运行
JVM- Java虚拟机(java virtual machine)
image-20211119213544767

1.3基础语法

1.3.1变量

1.3.1.1基本数据类型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L6QOvdmI-1639810532177)(image-20211123205100215.png)]

注:

  • java中方法参数传递方式是按值传递。

    如果参数是基本类型,传递的是基本类型的字面量值的拷贝。

    如果参数是引用类型,传递的是该参量所引用的对象在堆中地址值的拷贝。

    class basicKnowledge{
        public void func(String s){
            s="stupid";
        }
    }
    
    public class basicKnowledgeTest {
        public static void main(String[] args){
            basicKnowledge bk=new basicKnowledge();
            String s="wangjunyi";
            bk.func(s);//这里传递的是s的地址的拷贝值,该地址拷贝值指向了“wangjunyi”,但原地址没有
            System.out.println(s);
        }
    }
    
  • 为什么叫做引用数据类型:

img

执行

str="java";//赋值运算符会改变引用中所保存的地址,原来的地址被覆盖掉。但是原来的对象不会被改变(重要)。
img
1.3.1.1.1整型
整型占用字节表数范围
byte1字节=8bit-128~127
short2字节 [ − 2 15 , 2 15 − 1 ] [-2^{15},2^{15}-1] [215,2151]
int4字节 [ − 2 31 , 2 31 − 1 ] [-2^{31},2^{31}-1] [231,2311]
long8字节 [ − 2 56 , 2 56 − 1 ] [-2^{56},2^{56}-1] [256,2561]long l1=14545424L;
1.3.1.1.2浮点型
浮点型占用字节表数范围
float4字节[-3.403E38,3.403E38]float>long
double8字节[-1.798E308,1.798E308]Java浮点型常量默认为double
1.3.1.1.2字符类型
字符类型占用字节编码表现形式特点
char2字节Unicode编码
(一个字符可以表示一个字母/汉字/其他书面语)
1.单引号:char c1=‘a’;
2.转义字符:char c2=’\t’
3.直接用Unicode值(4位十六进制)
char c3=’\u000a’ (’\n’)
- 可以进行运算
- 不可以为空
char c1=’’;//wrong
- 1.3.1.1.3布尔型

boolean: true or false

1.3.1.2基本数据类型之间的转换
1.3.1.2.1自动类型转换

小范围->大范围:√

大范围->小范围:×

即:byte、char、short–>int–>long–>float–>double


char:

  • byte、char、short三种变量进行运算时,结果为int类型

float f1=12.3F;//correct
float f2=12.3;//wrong,double->float
float f3=12.3+f1;//wrong,double->float

long l1=123456L;//correct
long l2=123456;//correct,int->long
byte b='c';
byte b1=b+1;//wrong,int->byte,整型常量默认int型
int i1=b+1;//correct

float f=12.3F;
double d1=12.2+f;//correct,浮点型常量默认double
1.3.1.2.2强制类型转换

()

1.3.1.3基本数据类型与String之间的转换
1.3.1.3.2String
  • 引用数据类型
  • 支持与其他类型(整数、浮点数)拼接
//支持拼接
String s1="wangjing",s2="NB";
String s=s1+s2;
System.out.println(s);

char c='a';
int num=10;
String str="hello";
System.out.println(c+num+str);//107hello
System.out.println(c+(num+str));//a10hello
System.out.println((c+num)+str);//107hello
System.out.println((str+num)+c);//hello10a
System.out.println(str+num+c);//hello10a

System.out.println('*'+'\t'+'*');//97,都是整型变量进行加和
System.out.println('*'+"\t"+'*');//*  *,从左到右运算,字符串的拼接
System.out.println('*'+'\t'+"*");//53*,先整型加和再拼接
System.out.println('*'+('\t'+"*"));//*  *

//String->int
String s="123";
int i1=parseInt(s);
image-20211128100136455
1.3.1.4进制与进制之间的转换

0b/0B:二,十,0:八,0X/0x:十六

1.3.2关键字和保留字

1.3.2.1关键字
  • 关键字所有都小写
1.3.2.2保留字
  • 以后的Java版本可能使用的预备关键字

1.3.3标识符

合法标识符规则:

image-20211123203214132

标识符命名规范:

image-20211123203652412

注:

  • java使用Unicode字符集,理论上中文也可以当作标识符

1.3.4运算符

1.3.4.1算术运算符
运算符举例说明
/-8/5=-1
8/5=1

8/5.0=1.6
不是四舍五入
而是舍弃小数取整数
被除数和除数中有浮点数结果:double
%-12%5=-2
12%5=2
12%-5=2
-12%-5=-2
结果符号与被模数是一样的
+±-自增(减)1不会改变变量的数据类型
1.3.4.2赋值运算符
运算符举例说明
+= -= /= *=short s=1;
s=s+2;//wrong;
s+=2;//yes
不会改变变量的数据类型
int i=1;
i*=0.1;//0,C++亦此
1.3.4.3比较运算符
1.3.4.4逻辑运算符
运算符说明
&逻辑与如果&前面为false,后面内容还是照样执行
&&短路与如果&&前面为false,则不执行后面的内容
|逻辑非如果|前面是true,后面的内容照样执行
||短路非如果|前面是true,后面的内容不执行了
1.3.4.5位运算符
  • 操作的都是整型变量,是直接对整数的二进制每一位进行的运算
image-20211128111638022 image-20211128132053130

🥚

image-20211128132227874
  • A<<n:A*2^n,直到最高位变成1(突变负数)
  • A>>n:A/2^n,(直到最高位变成1,突变负数)
1.3.4.6三元运算符
1.3.4.7运算符优先级
image-20211128132756644

1.3.5程序流程控制

1.3.5.1switch-case
  • 注意break;
  • switch(整型表达式)
1.3.4.2带标签的break和continue
label1:for(int i=0;i<4;i++){
            for(int j=i;j<4;j++){
                System.out.print(j);
                if(i==3)
                    break label1;
            }
            System.out.println();
        }
/*
0123
123
23
3
*/

1.4数组

数据类型:引用数据类型

数组元素:既能是基本数据类型,也可以是引用数据类型

长度一旦确定,不能改变

1.4.1一维数组

1.4.1.1声明和初始化
int[] ids;//声明,可以把int[]当作类
ids=new int[]{1001,1002,1003,1004};//静态初始化:数组初始化和数组元素的赋值同时进行
String[] names=new String[5];//动态初始化:分开进行
1.4.1.2获取长度
//获取长度
//.length属性
System.out.println(names.length);
1.4.1.3数组的默认初始化值
类型默认初始化值
整型0
浮点型0.0
char型0//不是‘0’,输出的话是空白
boolean型false
引用数值类型(String,类,接口,数组)null
1.4.1.4数组的内存解析
  • 内存的简化结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-reyZJNij-1639810532179)(image-20211202161808810.png)]

  • 程序执行过程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lZpm8bRO-1639810532179)(image-20211202162358777.png)]

栈空间没有变量指向0x12ab,垃圾回收机制在合适的时机进行回收

引用数据类型new时,改变的是地址,而不是改变指向的变量

1.4.2二维数组

1.4.2.1声明和初始化
//二维数组
//声明与初始化
int[][] arr1=new int[][]{{1,2,3},{4,5},{6,7,8}};//静态初始化,长度可以不一样
String[][] arr2=new String[3][2];//动态初始化
String[][] arr3=new String[3][];//动态初始化
int[] arr4[]=new int[][]{{1},{1,2},{1,3}};//静态初始化,也是正确的
1.4.2.2获取数组的长度
//获取数组的长度
System.out.println(arr1.length);//3
System.out.println(arr1[1].length);//4
1.4.2.3二维数组的默认初始化值
二维数组外层元素a[]内层元素a[] []
int[] []地址值🚩0(与一维数组相同)
1.4.2.4二维数组的内存解析
image-20211202211635056

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HIImjA8A-1639810532180)(image-20211202211656713.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jn0MFmtJ-1639810532180)(image-20211202211714156.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-syASysw2-1639810532180)(image-20211202211747849.png)]

1.4.3数组算法

1.4.3.1赋值
  • random
double d=Math.random();//[0,1)之间的一个随机数

Random rand = new Random(512);//512:seed
int i=rand.nextInt();
double db=rand.nextDouble();
  • arr2=arr1
int[] arr1=new int[]{3,5,6,1,7,8};
int[] arr2;
arr2=arr1;//arr2和arr1的关系:arr2与arr1地址相同,都指向堆空间中唯一的数组实体
1.4.3.2特征值(max,min,avg,sum)
1.4.3.3复制
//元素为基本数据类型
int[] arr2=new int[arr1.length];
for(int i=0;i<arr1.length;i++){
	arr2[i]=arr1[i];
}
1.4.3.4反转
1.4.3.5查找
1.4.3.6排序

1.4.4Arrays工具类

  • 操作数组的工具类
1.4.4.1方法
image-20211202221332605
int[] arr1 =new int[]{1,2,4,3};
int[] arr2 = new int[]{1,4,2,3};
boolean b=Arrays.equals(arr1,arr2);
System.out.println(b);
System.out.println(Arrays.toString(arr1));
Arrays.sort(arr2);
for(int i=0;i<arr2.length;i++){
System.out.print(arr2[i]+" ");
}
System.out.println("\n"+Arrays.binarySearch(arr2,4));
//false
//[1, 2, 4, 3]
//1 2 3 4 
//3

1.4.5数组的常见异常

  • 索引越界ArrayIndexOutOfBoundsException
  • 空指针NullPointerException

2.面向对象(类和对象设计 | 继承与多态)

2.1面向过程和面向对象

2.1.1面向对象三大主线

1.Java类及类的成员:属性、方法、构造器、代码块、内部类

2.面向对象的三大特征:封装性、继承性、多态性、(抽象性)

3.其他关键字:this,super,static,final,abstact,interface,package,import

2.2Java语言基本元素:类(Class)和对象(Object\instance)

2.3类的结构:属性和方法

  • field=属性=成员变量(=域=字段)
  • method=(成员)方法=函数
  • 创建类的对象=类的实例化=实例化类

2.3.1属性与局部变量的对比

**属性:**加载到堆空间中

**static属性:**方法区

**局部变量:**栈

2.4类和对象的创建

Person p1=new Person();

2.4.1类里多个对象的关系

Person p1=new Person();
p1.name="Tom";
p1.age=1;

Person p3=new Person();
p3=p1;
p3.name;//Tom
p3.age=10;
p1.age;//10->类为引用数据类型,p3=p1的含义是将p1的地址赋给了p3,p3新new出来的Person对象会通过垃圾回收机制回收

2.5对象

2.5.1对象的内存解析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1t1lqBqq-1639810532181)(image-20211207194948240.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SL3aBBNk-1639810532181)(image-20211207195621879.png)]

2.5.1.1对象数组的内存解析

**注意:**引用类型的变量,只能存储两类值:null 或 地址值(含变量的类型)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j7sVGC4i-1639810532181)(image-20211207211751108.png)]

2.5.2万事万物皆对象

  • 在Java语言范畴中,我们都将功能、结构等封装到类中,通过类的实例化,来调用具体的功能结构
  • 在涉及到Java语言与前端Html、后端的数据库交互时,前后端的结构在Java层面交互时,都体现为类、对象

2.5.3匿名对象

new Phone().sendEmail();//不给对象一个名字,用完即弃,只能调用一次

2.6方法

2.7.1方法的声明:权限修饰符

private\public\缺省\protected

2.7.2方法的重载(overload)

  • “两同一不同”:同一个类,同一个方法名,列表参数不同(参数个数不同、参数类型不同)
  • 跟方法的权限修饰符、返回值类型、形参变量名、方法体都没有关系

2.7.3可变个数的形参

  • …可传一个、两个、多个
  • (数据类型…变量名)
  • 与同数据数组类型冲突,无法构成重载,就当作数组即可
public void show(String ... strs){
}

public static void main(String[] args){
	Test test=new Test();
    test.show("hello");//right
    test.show("hello","world");//right
    test.show();//notice!:right
}

2.7.4⭐方法参数的值传递机制

2.7.4.1关于变量的赋值
  1. 如果变量是基本数据类型,此时赋值的是变量所保存的数据值
  2. 如果变量是引用数据类型(类、数组、接口),此时赋值的是变量所保存的数据的地址值
2.7.4.2Java的实参如何传入方法

方法的形参的传递机制:值传递

  1. 形参是基本数据类型,将实参基本数据类型变量的“数据值”传递给形参
  2. 形参是引用数据类型:将实参引用数据类型变量的“地址值”传递给形参
2.7.4.3一个好例子

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yo3JUToG-1639810532182)(image-20211208205449591.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PvbpsSPm-1639810532182)(image-20211208205427393.png)]

2.7.5递归方法

2.7封装性

程序设计追求“高内聚、低耦合”

高内聚:类的内部数据操作曦姐自己完成,不允许外部干涉

低耦合:仅对外暴露少量的方法用于使用。

**封装性的设计思想:**把该隐藏的隐藏起来,该暴露的暴露出来

  1. getXxx(),setXxx()

2.7.1权限修饰符

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x5CGlLoE-1639810532182)(image-20211208223147182.png)]

  • 在类的成员定义前,与C++不同

权限由小到大:

  1. private

  2. 缺省

  3. protected

  4. public

注意:

  • 4中权限可以用来修饰类及类的内部结构:属性、方法、构造器、内部类
  • 修饰外部类:缺省、public

2.7.2构造器

//权限修饰符+类名+(形参)
public Person();//注意和C++不同,有权限修饰符

2.8继承性

2.8.1基本概念

class A extents B{}
//A:subclass
//B:superclass
  1. subclass extends superclass‘s 所有的属性、结构、方法,(构造器见后文)

  2. **私有属性:**实际上获取到了,但是因为封装性的影响,不能直接调用,可以用过setAge(),getAge()获取和修改

  3. 子类可以额外定义自己的属性和方法

  4. 子类的范围要父类,不同于集合和子集

2.8.2java中关于继承性的规定

  1. Java中类的单继承性和多层继承性:一个类可以被多个子类继承,一个类只能有一个父类。允许多层继承
  2. 直接父类、间接父类

2.8.3Object类

  1. 如果没有显式地声明一个类地父类,此类继承与java.lang.Object类
  2. 所有类(除java.lang.Object类)都直接或间接继承java.lang.Object类,可以使用Object中的所有功能
2.8.3.1功能
2.8.3.1.1 equals()
  1. ==和.equals()

  2. 适用范围:

    • 基本数据变量:值相等,没必要完全是同类型
    • 引用数据类型:比较地址
    ==.euqals()
    基本数据类型值相等,没必要完全是同类型
    int a=10;double b=10.0;a==b?//true
    - 不和boolean比较
    - 这是一个方法
    - 只针对类
    - 不能适用于基本数据类型
    - 可以用包装类
    引用数据类型地址值
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5TvBub2f-1639810532183)(image-20211212162445743.png)]
    - 在Object类中等价于==
    - 在String,File,Data,包装类都重写了.equals的方法,重写以后,比较的不是两个引用的地址是否相同,而是比较两个对象的实体内容是否相同
    Customer c1=new Customer("c1");
    Customer c2=new Customer("c2");
    
    String s1=new String("fsdfhs");
    String s2=new String("fsdfhs");
    
    System.out.println(c1.equals(c2));//false->地址值不同
    System.out.println(s1.equals(s2));//true->重写了
    
  • 注意比较String需要用equals而不是==
  1. 自定义类重写equals()

    比较实体内容,而不是比较地址

    class Person{
    	@override
    	public boolean equals(Object obj){
    		if(this==obj){
    			return true;	
    		}
    		if(obj instanceof Person){
    			//比较
    		}
    		return false;
    	}
    }
    
2.8.3.1.2 getClass()
2.8.3.1.3 toString()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k84eHu43-1639810532183)(image-20211212173750823.png)]

  1. 当我们输出一个对象得引用时,实际上就是在调用当前对象的toString()
  2. 像String,Data,File,包装类都重写了Object类中的toString方法
  3. 自定义类可以重写toString
public String toString(){

}
2.8.3.1.4 hashCode()

2.8.4包装类

2.8.4.1单元测试

Junit单元测试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dyru259L-1639810532183)(image-20211212193614841.png)]

2.8.4.2使用
  • 万物皆对象
  • 使得基本数据类型就具有类的特征

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YaDy6R08-1639810532184)(image-20211212193650923.png)]

  • 虚线框内:父类Number
2.8.4.3基本数据类型、包装类和String类之间的转换

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gfJcxwoB-1639810532184)(image-20211212194336623.png)]

public void Test1(){
        //基本数据类型---->包装类
        int num1=10;
        Integer in1=Integer.valueOf(num1);
        Integer in2=num1;
        System.out.println(in1==num1);//true
        System.out.println(in1.toString());//10

        //包装类--->基本数据类型
        System.out.println(in1.intValue());//10
        Boolean b1=Boolean.valueOf("true123");//false
        Boolean b2=Boolean.parseBoolean("true");//true
        System.out.println(b1.booleanValue()?1:0);

        //自动装箱
        Integer in3=num1;
        Boolean b3=true;

        //自动拆箱
        int num3=in3;

        //基本数据类型--->String
        int num4=1230;
        String s2=num+"";
        String s4=Integer.valueOf(num4).toString();
        String s5=String.valueOf(num4);

        //String--->基本数据类型
        //包装器类.parseXXX(String s)
        int num5=Integer.parseInt(s4);
        boolean b4=Boolean.parseBoolean("true");

2.8.5方法重写

2.8.5.1定义

override/overwrite

  1. 重写:子类继承父类以后,可以对父类中同名同参数地方法进行覆盖操作

  2. 应用:重写之后,当创建子类对象的以后,通过子类对象调用子父类地同名同参数地方法是,实际执行的是子类重写父类的方法

2.8.5.2要求
  1. 重写:子类中重写的方法和父类中被重写的方法方法名和形参列表相同
  2. **权限修饰符:**子类重写的方法的权限修饰符 父类中被重写的方法的权限修饰符
  3. 子类中不能重写父类中声明为private的方法
public class Person{
	private void show(){
		System.out.println("人")}
}
package another
public class Student extends Person{
	public void show(){//没有用,始终不会调用这个
		System.out.println("学生")}
}
public class StudentTest{
	public static void main(String[] args){
		Student s= new Student();
		s.show();
	}
}
//人
  1. 返回值类型
父类中被重写的方法子类中重写的方法
voidvoid
A类A类或A的子类
基本数据类型相同的基本数据类
  1. 抛出的异常类型

子类重写的方法抛出的异常类型 父类重写的方法抛出的异常类型

2.8.5.3注意

2.8.6子类对象实例化过程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xU867xGY-1639810532184)(image-20211212123322414.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yzkaqTxc-1639810532185)(image-20211212123523278.png)]

  1. **从结果上看:**子类继承父类以后,就获取了父类中声明的属性或方法,创建子类的对象,在对空间中,就会加载所有父类中声明的属性。
  2. **从过程上看:**当我们通过子类的构造器创建子类对象时,我们一定会直接或间接地调用其父类地构造器,进而调用父类的父类的构造器,直到调用了java.lang.Object类地空参构造器位置。正因为加载过所有父类的结构,所以才可以看到内存中有父类的结构,子类对象才可以考虑进行调用。
  3. **注意:**虽然创建子类对象时,调用了父类的构造器,但是自始至终就只创建过一个对象

2.9多态性

2.9.1定义

Person p2=new Man();//父类的引用指向子类的对象,子类的对象赋给父类的引用

2.9.2使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BRkGQNxW-1639810532185)(image-20211212143541202.png)]

  1. 当调用子父类同名同参数的方法时,实际执行的时子类重写父类的方法 — 虚拟方法重用
  2. 有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,;但在运行期,我们实际执行的是子类重写父类的方法。总结:编译看左边,执行看右边
  3. 使用前提:
    • 类的继承关系
    • 类的方法重写

2.9.3注意

public class Person{
	int a=1;
}
package another
public class Student extends Person{
	int a=2;
}
public class StudentTest{
	public static void main(String[] args){
		Person p1 = new Student;
		System.out.println(p1.a);
	}
}
//1->父类的

1.多态性不适合属性属性编译和运行都看左边(superclass)

2.9.4重载和重写的区别

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5GDqibNw-1639810532185)(image-20211212143959691.png)]

2.9.5向下转型

用得少

2.9.5.1使用

有了对象的多态性以后,内存中实际上时加载了子类特有的属性和方法的,但是由于变量声明为父类型的,导致编译时只能调用父类中的属性和方法,子类特有的属性和方法不能调用

如何调用子类特有的属性和方法?(向下转型)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dM7uo2ls-1639810532185)(image-20211212150314281.png)]

Person p1=new Man();
Man m1=(Man)p1;//强转有风险
m1.earnMoney();//right
p1.earnMoney();//wrong
int a=m1.money;//right
int b=p1.money;//wrong
2.9.5.2问题
Person p1=new Person();
Man m1=(Man)p1;//wrong,小范围->大范围

2.9.6 关键字:instanceof

a instanceof A//:对象a是否是类A的实例,是->true
    //为了避免再向下转型是出现异常,先进行instanceof
   //的判断,一旦返回true,可以进行向下转型
    

2.9.7经典举例

在继承多态中:

1、对于方法的覆盖,new的谁就调谁,这就是多态。

2、对于成员变量的覆盖,this在哪个类就指向哪个类的成员变量,没有多态。

Man m1=new Man();
Person p1=m1;
System.out.println(p1==m1);//true,引用数据类型比较地址值
public class Person{
	int count=1;
	private void show(){
		System.out.println(this.count)}
}
package another
public class Student extends Person{
	int count=2;
	public void show(){//没有用,始终不会调用这个
		System.out.println(this.count)}
}
public class StudentTest{
	public static void main(String[] args){
		Student s= new Student();
		System.out.println(s.count);//2
         s.show();//2
         Person p1=s;
         System.out.println(p1.count);//1->属性无法被重写
         p1.show();//2->方法被重写,位于子类中,对于成员变量的覆盖,this在哪个类就指向哪个类的成员变量,没有多态。
	}
}
package basic;

public class Demo {
    public static void main(String[] args) {
        Fu f = new Zi();
        System.out.println(f.num);//->这里定义的是父类,而成员变量没有多态,所以即使你new的子类,依然指向父类的成员变量。
        System.out.println(f.fun1());//->不解释了,就是多态。
        f.show();
    }
}

class Fu {
    public String num = "父类成员变量";

    public void show() {
        System.out.println(this.num);//因为成员变量没有多态,所以this指向当前类对象的成员变量。
        System.out.println(this.fun1());//因为方法有多态,所以this指向new对象的方法。
    }

    public String fun1() {
        System.out.println(this.num);//因为成员变量没有多态,所以this指向当前类对象的成员变量。
        return "父类调用";
    }
}

class Zi extends Fu {
    public String num = "子类成员变量";

    public String fun1() {
        System.out.println(this.num);//因为成员变量没有多态,所以this指向当前类对象的成员变量。
        return "子类调用";
    }
}
//父类成员变量
//子类成员变量
//子类调用
//父类成员变量
//子类成员变量
//子类调用

2.10关键字

2.10.1 this

2.10.1.1概念
  • this表示当前对象,可以调用类的属性、方法和构造器
  • this在方法内部使用,及这个方法所属对象的引用
  • 在构造器内部使用,表示该构造器正在初始化的对象
2.10.1.1this在构造器中
public Person(){
	this.name="abc";
}
public Person(int age){
	this();//notice
	this.age=age;
}
public Person(String description){
    this(12);//notice
	this.feat=description;
}
  • this(形参列表)必须声明在当前构造器的首行,且最多调用一个其他的构造器

2.10.2 package

  • 包也属于标识符

  • 规范:小写

  • 每.(点)一次,就代表一层文件目录

  • 同一个包下,不能命名同名的接口、类;不同的包下,可以命名同名的接口、类

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TOFrS0BI-1639810532186)(image-20211208235938030.png)]

2.10.3 import

  1. 在源文件中显式地使用import结构导入指定包下的类、接口
  2. 声明在包的声明和类的声明之间
  3. 如果需要导入多个结构,并列举出
  4. 可以使用"XXX.*"的方式,表示可以导入XXX包下的所有结构
  5. 如果使用的类或接口是java.lang包下定义的,则可以省略import结构
  6. 如果使用的类或接口时本包下定义的,则可以省略import结构
  7. 如果导入不同包里面的类同名,使用时需要全类名(包.类)
  8. 使用”XXX.*“不可以调用XXX的子包,需要重新导入子包

2.10.4 super

2.10.4.1使用
  1. super:父类的…
  2. super可以修饰来调用:属性、方法和构造器
2.10.4.2 super调用构造器
super(形参列表)//必须声明在子类构造器的首行,一旦使用就不能再使用this(形参列表)
  1. 在构造器首行没有显式声明this(形参),super(形参),默认调用super()
public class Person{
	Person(){
		System.out.println("我无处不在")
	}
}
package another
public class Student extends Person{
	Student(){};
}
public class StudentTest{
	public static void main(String[] args){
		Student s= new Student();//子类构造器默认调用super(),所以需要父类具有空参构造器
	}
}
//我无处不在

2.10.5 static

  • 同一个类的所有对象共享同一个static数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l7Z1xFkx-1639810532186)(image-20211212211227417.png)]

  • static可以修饰:属性,方法,代码块,内部类
2.10.5.1使用static修饰属性
  1. 静态变量随着类的加载而加载,早于对象创建(实例化时),存在于方法区的静态域

  2. 只会加载一次,在内存中只有一份

Person.description;//直接调用类的静态变量
  1. 是否应该使用static:
  • 属性时可以被多个对象所共享的,不会随着对象的不同而不同
2.10.5.2类变量和实例变量的内存解析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VUZR1vdS-1639810532187)(image-20211213114921832.png)]

2.10.5.3使用static修饰方法
  1. 随着类的加载而加载,可以通过类.方法调用
  2. 静态方法中,只能调用静态的方法或属性(生命周期相同);非静态方法中,都可
  3. 不能使用this和super(this:当前对象而言,super也要基于当前对象的父类)
  4. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L5yGI81l-1639810532187)(image-20211213115433069.png)]
  5. 是否应该使用static:
    • 操作静态变量的方法,通常设置为static
    • 工具类中的方法,习惯上声明为static的,笔记Math,Array,Collections
2.10.5.4单例设计模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RA9S6bdn-1639810532187)(image-20211213120013230.png)]

2.10.5.5使用static修饰代码块
2.10.5.6使用static修饰内部类

2.10.6 final

≈const

1.final可以修饰的结构:类、方法、变量

2.10.6.1final+类
  • 此类不能被其他类继承
2.10.6.2final+方法
  • 此方法不能被重写(不是重载)
2.10.6.3final+变量
  • 变量不只是属性
  • ->常量

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZyR8mlV6-1639810532187)(image-20211213184736407.png)]

o没有变,o的属性可以变

2.11 main方法的语法

  1. main程序入口
  2. main()也是一个普通的静态方法,可以调用
  3. main()形参也可以作为我们与控制台交互的方式(Scanner)
Public class Test{
	int num1=1;
	public static void main(String[] args){//不能调用除静态属性和静态方法之外的
		System.out.println(num1);//wrong,非静态变量
	}
}
class mianTest{
	public static void main(String[] args){//可以被入口调用
}
}
//与控制台交互
Public class Test{
	int num1=1;
	public static void main(String[] args){
		for(int i=0;i<args.length;i++){
			System.out.print("..."+args[i]);
		}
	}
}

2.12抽象类和抽象方法

超级抽象的爸爸类

  1. abstract可以修饰的结构:类、方法
  2. 一旦abstract了,就不能实例化

2.12.1abstract+类

  • 抽象类不能实例化
  • 抽象类中一定有构造器,便于子类实例化时调用
  • 开发中,都会提供抽象类的子类,让子类实例化,完成相关的操作
  • 包含抽象方法的类,一定是抽象类;抽象类不一定有抽象方法。
abstract class Person{

}

2.12.2abstract+方法

  • 没有方法体
  • 非抽象的子类中需要实现父类中的所有抽象方法。
  • 若子类重写了父类中的所有抽象方法,然后此子类才可以实例化
  • 若子类没有重写了父类中的所有抽象方法,则此子类要么是抽象类要么报错
public abstract void eat();//没有括号

2.12.3 abstract的使用注意

  • 不能用来修饰构造器、属性、私有方法、静态方法、final的方法、final的类

2.12.4 (匿名类)抽象类中构建匿名子类对象

public class Test(){
	public static void main(String[] args){
		Test t=new Test();
        t.method(man);//非匿名类 非匿名对象
        t.method(new Man());//非匿名类 匿名对象

        Person p=new Person(){//匿名类 非匿名对象
            public void eat(){
                System.out.print("aa");
            }
        }
        t.method(p);
        t.method(new Person(){//匿名类 匿名对象
            @Override
            public void eat(){
                
            }
        })}
	public void method(Person p){

	}
}

abstract class Person{
	public abstract void eat();
}

class Man extends Person{
	@override
	public void eat();
}

2.12.5模板方法的设计模式

2.12.6练习

2.13接口interface

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lEVQt267-1639810532188)(image-20211213194602867.png)]

2.13.1定义

  • 接口使用interface定义
  • 接口和类是并列的
  • 接口中只能定义全局常量和公有抽象方法,不能有构造器,不能实例化
  • 常量定义:可以省略public static,默认都是全局常量
  • 方法定义:可以
  • 类实现接口(implements)
  • 如果实现类覆盖了接口中所有的抽象方法,则此类可以实例化
  • 如果实现类没有覆盖接口中所有的抽象方法,此类仍为抽象类
  • Java可以实现多个接口
  • 接口与接口之间是多继承
  • 接口体现多态性
public class InterfaceTest{
	 
}

class Plane implements Flyable{
    @Override
    public void fly(){
        
    }
    @Override
    public void eat(){
        
    }
}

interface Flyable{
	//全局常量
	public static final int MAX_SPEED=7900;
    int MAX_SPEED=7900;
    //公有抽象方法
    public abstract void fly();
    void stop();
}

interface extents Flyable,aa,bb,cc{//接口的多继承
    
}
class beautifulBoy extends Person implements makeUp,dressUp{

}

2.13.2接口和抽象类

1接口抽象类

2.14类的成员四:代码块

public class Person{
	int age;
	String name;
    {

    }//用来初始化类或对象
	Person(){
		System.out.println("我无处不在")
	}
}
  1. 用来初始化类或对象
  2. 只能用static修饰或者不修饰

2.14.1静态代码块

  • 内部可以有输出语句
  • 随着类的加载而加载,只执行一次
  • 可以用于对静态变量进行初始化
  • 如果一个类中定义了多个静态代码块,按照声明的先后顺序执行
  • 静态代码块执行优于非静态代码块
  • 只能调用静态属性、方法
static{

}

2.14.2非静态代码块

  • 内部可以有输出语句
  • 随着对象的创建而加载,每创建一个对象,就执行一次
  • 如果一个类中定义了多个非静态代码块,按照声明的先后顺序执行
  • 都可以调用(静态、非静态、属性、方法)
{

}

2.14.3对属性可以赋值的位置

  1. 默认初始化
  2. 显式初始化
  3. 构造器中初始化
  4. 有了对象以后,通过对象.属性或对象.方法的方式,进行赋值
  5. 在代码块中赋值
2.14.3.1属性赋值的顺序
public class OrderTest {
   public static void main(String[] args) {
      Order order = new Order();
      System.out.println(order.orderId);
   }
}

class Order{
   int orderId = 3;
   {
      orderId = 4;
   }
}
//4

2.14.4⭐练习

  • 由父及子,静态先行
  • **有继承关系,类的加载顺序:**先加载父类,再加载子类
package com.atguigu.java3;
//总结:由父及子,静态先行
class Root{
	static{
		System.out.println("Root的静态初始化块");
	}
	{
		System.out.println("Root的普通初始化块");
	}
	public Root(){
		super();
		System.out.println("Root的无参数的构造器");
	}
}
class Mid extends Root{
	static{
		System.out.println("Mid的静态初始化块");
	}
	{
		System.out.println("Mid的普通初始化块");
	}
	public Mid(){
		super();
		System.out.println("Mid的无参数的构造器");
	}
	public Mid(String msg){
		//通过this调用同一类中重载的构造器
		this();
		System.out.println("Mid的带参数构造器,其参数值:"
			+ msg);
	}
}
class Leaf extends Mid{
	static{
		System.out.println("Leaf的静态初始化块");
	}
	{
		System.out.println("Leaf的普通初始化块");
	}	
	public Leaf(){
		//通过super调用父类中有一个字符串参数的构造器
		super("尚硅谷");
		System.out.println("Leaf的构造器");
	}
}
public class LeafTest{
	public static void main(String[] args){
		new Leaf(); //Root的静态初始化块-Mid的静态初始化块-Leaf的静态初始化块-Root的普通初始化块-Root的无参数的构造器-Mid的普通初始化块-Mid的无参数的构造器-Mid的带参数构造器,其参数值:尚硅谷-Leaf的普通初始化块-Leaf的构造器
		System.out.println();
		new Leaf();//Root的普通初始化块-Root的无参数的构造器-Mid的普通初始化块-Mid的无参数的构造器-Mid的带参数构造器,其参数值:尚硅谷-Leaf的普通初始化块-Leaf的构造器
	}
}
/*
Root的静态初始化块
Mid的静态初始化块
Leaf的静态初始化块
Root的普通初始化块
Root的无参数的构造器
Mid的普通初始化块
Mid的无参数的构造器
Mid的带参数构造器,其参数值:尚硅谷
Leaf的普通初始化块
Leaf的构造器

Root的普通初始化块
Root的无参数的构造器
Mid的普通初始化块
Mid的无参数的构造器
Mid的带参数构造器,其参数值:尚硅谷
Leaf的普通初始化块
Leaf的构造器
*/
package com.atguigu.java3;

class Father {
	static {
		System.out.println("11111111111");
	}
	{
		System.out.println("22222222222");
	}
	public Father() {
		System.out.println("33333333333");
	}
}

public class Son extends Father {
	static {
		System.out.println("44444444444");
	}
	{
		System.out.println("55555555555");
	}
	public Son() {
		System.out.println("66666666666");
	}

	public static void main(String[] args) { // 由父及子 静态先行
		System.out.println("77777777777");
		System.out.println("************************");
		new Son();
		System.out.println("************************");
		new Son();
		System.out.println("************************");
		new Father();
	}
}
/*
11111111111
44444444444
77777777777
************************
22222222222
33333333333
55555555555
66666666666
************************
22222222222
33333333333
55555555555
66666666666
************************
22222222222
33333333333
*/

2.15类的成员五:内部类

不大用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BxZfnr0c-1639810532188)(image-20211213204845918.png)]

package basic;

public class InnerClass {
    public static void main(String[] args){
        //创建静态成员内部类
        Person.Dog dog=new Person.Dog();

        //创建非静态成员内部类--》先有对象
        Person p= new Person();
        Person.Bird bird=p.new Bird();
    }
}
class Person{
    int age;
    String name;

    //静态成员内部类
    static class Dog{
        public void show(){
        }
    }
    //非静态成员内部类
    class Bird{
        String name;
        public void sing(){
            System.out.println(Person.this.age);//调用外部类的结构
        }
        public void displasy(String name){
            System.out.println(name);//方法形参
            System.out.println(this.name);//内部类属性
            System.out.println(Person.this.name);//外部类属性
        }
    }
}

2.15.1 分类

  1. 成员内部类

一方面,作为外部类的成员:

  • 调用外部类的结构
  • 可以被static修饰,非内部类不可以被static修饰

另一方面

  • 可以定义属性、方法、构造器

  • 可以被final(不能继承),abstract(不能调用)修饰

  1. 局部内部类(方法内,代码块内,构造器内)

2.15.2实例化成员内部类对象

public class InnerClass {
    public static void main(String[] args){
        //创建静态成员内部类
        Person.Dog dog=new Person.Dog();

        //创建非静态成员内部类--》先有对象
        Person p= new Person();
        Person.Bird bird=p.new Bird();//notice!
    }
}

2.15.3区分调用外部类的结构

class Person{
    String name;

    //非静态成员内部类
    class Bird{
        String name;
        
        public void sing(){
            System.out.println(Person.this.age);//调用外部类的结构
        }
        public void displasy(String name){
            System.out.println(name);//方法形参
            System.out.println(this.name);//内部类属性
            System.out.println(Person.this.name);//外部类属性
        }
    }
}

2.15.4局部内部类

public class cmp {
    //返回一个实现了Comparable接口的类
    public Comparable getComparable(){
        class myComparable implements Comparable{
            @Override
            public int compareTo(Object o) {
                return 0;
            }
        }
        return new myComparable();
    }
}

2.16Java类的高级特性

2.16.1泛型

2.16.2Java的类加载机制

2.16.3反射机制

2.16.4注解

3.📕Java标准类库

3.1 String类

3.2StringBuffer类

3.3包装器类

3.4System类和Runtime类

3.5Math和Random类

3.6Date和Calendar类

3.8Set类

4.异常处理

4.1异常概述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h19M9PPQ-1639810532188)(image-20211213214726168.png)]

4.2分类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-thOIiKzs-1639810532189)(image-20211213215402794.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vlcZtBzY-1639810532189)(image-20211213215912426.png)]

体系结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uGNuO4SE-1639810532189)(image-20211213220548509.png)]

4.2.1编译时异常

提前准备

4.2.2运行时异常

遇到再说

4.3异常处理方式

4.3.1概述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vXW50c6v-1639810532189)(image-20211213222412351.png)]

  • 抛:一旦抛出异常对象,其后的代码不再执行
  • 抓:可以理解为异常处理的两种方式:①try-catch-finally ②throws

4.3.2机制一:try-catch-finally块

4.3.2.1try-catch
  • try出现异常位置之后的代码不再执行
  • 如果catch成功处理,try_catch后面的代码正常执行
  • 常用的异常对象处理方式:①String getMessage() ②printStackTrace()
  • 在try结构中声明的变量,除了try块就不能用了
try{//可能出现的异常
}
catch(异常类型一 变量名1){//处理异常的方式1
 	System.out.println(e.getMessage());
}
catch(异常类型二 变量名2){
    System.out.println(e.getStackTrace());
}
finally{//一定会执行的代码
}
4.3.2.2finally的使用
  1. finally是可选的
  2. finally一定会被执行:即使catch中又出现异常,try中有return语句,catch中有return语句
  3. 什么东西需要写进finally:
public void testMethod(){
		int num = method();
		System.out.println(num);
	}
	
	public int method(){
		
		try{
			int[] arr = new int[10];
			System.out.println(arr[10]);
			return 1;
		}catch(ArrayIndexOutOfBoundsException e){
			e.printStackTrace();
			return 2;
		}finally{
			System.out.println("我一定会被执行");
			return 3;
		}
	}
	public void test2(){
		FileInputStream fis = null;//写在外面,防止finally中fis看不到
		try {
			File file = new File("hello1.txt");
			fis = new FileInputStream(file);
			
			int data = fis.read();
			while(data != -1){
				System.out.print((char)data);
				data = fis.read();
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			try {//嵌套
				if(fis != null)
					fis.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

4.3.3机制二:throws + 异常类型

往上抛

  1. throws + 异常类型卸载方法的声明处
  2. 一旦方法体执行出现异常,在异常代码处生成异常类的对象,此对象满足throws后异常类型时,就会被抛出。
  3. 异常代码后续代码不执行

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kOmmZFmW-1639810532190)(image-20211213231246920.png)]

4.4编译时异常和运行时异常

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Eqt1Q40w-1639810532191)(image-20211213230240169.png)]

4.5重写方法异常抛出的规则

方法重写的规则之一:

  1. 子类重写的方法抛出的异常 父类被重写的方法抛出的异常

    public class OverrideTest {
    	public static void main(String[] args) {
    		OverrideTest test = new OverrideTest();
    		test.display(new SubClass());
    	}
    	
    	public void display(SuperClass s){//注意这里的形参是父类
    		try {
    			s.method();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    }
    
    class SuperClass{
    	
    	public void method() throws IOException{
    		
    	}
    }
    
    class SubClass extends SuperClass{
    	public void method()throws FileNotFoundException{
    	}
    }
    

4.6如何选择哪种方式处理异常

  1. 如果父类被重写的方法没有throws方式处理异常,子类重写的方法也不可(-》try-catch-finally)

  2. 执行的方法a中,先后调用了另外的几个方法,这几个方法是递进关系执行的。

    我们建议这几个方法:throws

    a:try-catch-finally

4.7手动抛出异常对象:throw

4.8自定义异常

//自定义异常
/*
 * 如何自定义异常类?
 * 1. 继承于现有的异常结构:RuntimeException 、Exception
 * 2. 提供全局常量:serialVersionUID
 * 3. 提供重载的构造器
 * 
 */
public class MyException extends Exception{//继承
	
	static final long serialVersionUID = -7034897193246939L;//全局常量
	
	public MyException(){
		
	}	
	public MyException(String msg){//重载的构造器
		super(msg);
	}
}

package com.atguigu.java2;

public class StudentTest {
	
	public static void main(String[] args) {
		try {
			Student s = new Student();
			s.regist(-1001);
			System.out.println(s);
		} catch (Exception e) {
//			e.printStackTrace();
			System.out.println(e.getMessage());
		}
	}	
}


class Student{
	
	private int id;
	
	public void regist(int id) throws Exception {
		if(id > 0){
			this.id = id;
		}else{
//			System.out.println("您输入的数据非法!");
			//手动抛出异常对象
//			throw new RuntimeException("您输入的数据非法!");
//			throw new Exception("您输入的数据非法!");
			throw new MyException("不能输入负数");//抛出自定义异常对象
			//错误的
//			throw new String("不能输入负数");
		}
		
	}
	@Override
	public String toString() {
		return "Student [id=" + id + "]";
	}
}

4.9练习

//写出程序结果
public class ReturnExceptionDemo {
	static void methodA() {
		try {
			System.out.println("进入方法A");
			throw new RuntimeException("制造异常");
		} finally {
			System.out.println("用A方法的finally");
		}
	}

	static void methodB() {
		try {
			System.out.println("进入方法B");
			return;
		} finally {
			System.out.println("调用B方法的finally");
		}
	}

	public static void main(String[] args) {
		try {
			methodA();
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}

		methodB();
	}
}

5.多线程

5.1概述

5.1.1程序 进程 线程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KBexxaA9-1639810532192)(image-20211214010138654.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mXtClnps-1639810532193)(image-20211214010449367.png)]

5.1.2单核CPU与多核CPU

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mB49X2vR-1639810532193)(image-20211214010808619.png)]

5.1.3并行和并发

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N6ut5ZAk-1639810532194)(image-20211214010833342.png)]

5.1.4多线程的优点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-31dFaLhR-1639810532196)(image-20211214011141766.png)]

5.1.5多线程的使用情景

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q2yuUE5f-1639810532196)(image-20211214011546623.png)]

5.2⭐创建多线程的方式

5.4.1f方式一:继承Thread类

5.4.1.1java.lang.Thread类的特性
  • 每个线程通过Thread对象的run()方法完成操作

    run()方法的主体:线程体

  • 通过该Thread对象的start()方法来启动线程,而非直接调用run()

5.4.1.创建 过程
* 多线程的创建,方式一:继承于Thread* 1. 创建一个继承于Thread类的子类
* 2. 重写Thread类的run() --> 将此线程执行的操作声明在run()* 3. 创建Thread类的子类的对象
* 4. 通过此对象调用start()
//1. 创建一个继承于Thread类的子类
class MyThread extends Thread {
    //2. 重写Thread类的run()
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if(i % 2 == 0){
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}

public class ThreadTest {
    public static void main(String[] args) {
        //3. 创建Thread类的子类的对象
        MyThread t1 = new MyThread();

        //4.通过此对象调用start():①启动当前线程 ② 调用当前线程的run()
        t1.start();
        //问题一:我们不能通过直接调用run()的方式启动线程。
//        t1.run();

        //问题二:再启动一个线程,遍历100以内的偶数。不可以还让已经start()的线程去执行。会报IllegalThreadStateException
//        t1.start();
        //我们需要重新创建一个线程的对象
        MyThread t2 = new MyThread();
        t2.start();


        //如下操作仍然是在main线程中执行的。
        for (int i = 0; i < 100; i++) {
            if(i % 2 == 0){
                System.out.println(Thread.currentThread().getName() + ":" + i + "***********main()************");
            }
        }
    }

}
  • start():①启动当前线程 ② 调用当前线程的run()
  • 不可以还让已经start()的线程去再次执行

5.4.2方式二:实现Runnable接口

5.4.3两种创建方式的对比

5.3线程生命周期

5.4线程的安全问题(线程的互斥)

5.5⭐线程的同步

5.6死锁

6.📕GUI图形界面程序设计

7.I/O流

8.📕网络通信

9.📕JSP与Servlet | JDBC

5.多线程

5.1概述

5.1.1程序 进程 线程

[外链图片转存中…(img-KBexxaA9-1639810532192)]

[外链图片转存中…(img-mXtClnps-1639810532193)]

5.1.2单核CPU与多核CPU

[外链图片转存中…(img-mB49X2vR-1639810532193)]

5.1.3并行和并发

[外链图片转存中…(img-N6ut5ZAk-1639810532194)]

5.1.4多线程的优点

[外链图片转存中…(img-31dFaLhR-1639810532196)]

5.1.5多线程的使用情景

[外链图片转存中…(img-Q2yuUE5f-1639810532196)]

5.2⭐创建多线程的方式

5.4.1f方式一:继承Thread类

5.4.1.1java.lang.Thread类的特性
  • 每个线程通过Thread对象的run()方法完成操作

    run()方法的主体:线程体

  • 通过该Thread对象的start()方法来启动线程,而非直接调用run()

5.4.1.创建 过程
* 多线程的创建,方式一:继承于Thread* 1. 创建一个继承于Thread类的子类
* 2. 重写Thread类的run() --> 将此线程执行的操作声明在run()* 3. 创建Thread类的子类的对象
* 4. 通过此对象调用start()
//1. 创建一个继承于Thread类的子类
class MyThread extends Thread {
    //2. 重写Thread类的run()
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if(i % 2 == 0){
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}

public class ThreadTest {
    public static void main(String[] args) {
        //3. 创建Thread类的子类的对象
        MyThread t1 = new MyThread();

        //4.通过此对象调用start():①启动当前线程 ② 调用当前线程的run()
        t1.start();
        //问题一:我们不能通过直接调用run()的方式启动线程。
//        t1.run();

        //问题二:再启动一个线程,遍历100以内的偶数。不可以还让已经start()的线程去执行。会报IllegalThreadStateException
//        t1.start();
        //我们需要重新创建一个线程的对象
        MyThread t2 = new MyThread();
        t2.start();


        //如下操作仍然是在main线程中执行的。
        for (int i = 0; i < 100; i++) {
            if(i % 2 == 0){
                System.out.println(Thread.currentThread().getName() + ":" + i + "***********main()************");
            }
        }
    }

}
  • start():①启动当前线程 ② 调用当前线程的run()
  • 不可以还让已经start()的线程去再次执行

5.4.2方式二:实现Runnable接口

5.4.3两种创建方式的对比

5.3线程生命周期

5.4线程的安全问题(线程的互斥)

5.5⭐线程的同步

5.6死锁

6.📕GUI图形界面程序设计

7.I/O流

8.📕网络通信

9.📕JSP与Servlet | JDBC

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值