JAVA-SE核心基础篇

一,java语言概述

1.常用Dos命令

dir:列出当前目录下的文件以及文件夹
md:创建目录
rd:删除目录(空目录)
cd:进入指定目录
cd..:退回上一级目录
cd/:退回根目录
del:删除文件
echo 1 >java.txt:创建文件
exit:退出

2,java语言运行机制及运行过程

Java语言特点:跨平台性
Java两种核心机制:
Java虚拟机(jvm):Java程序运行环境
垃圾回收机制(gc)

3.jdk,jre,jvm的关系

jdk:Java开发工具包。(Java开发工具包和jre)
jre:Java运行环境。(包括jvm)

4 环境变量的配置

为什么要添加环境变量?
让Java工具包在任何路径下都可以使用。
高级系统设置-环境变量:
系统变量-path(window系统执行命令时需要搜索的路径)
加上 jdk的安装路径\bin
开发时的配置(推荐):
在系统变量里面新建变量JAVA_HOME 值为jdk安装路径。
然后再classpath变量中加入:%JAVA_HOME%\bin

5.HelloWorld

如何显示记事本后缀:
我的电脑-查看-文件拓展名
Java代码写在.java结尾的文件中。(源文件)
通过javac命令对该Java文件进行编译。(字节码文件)
通过Java命令对。class文件进行运行。

6 注释

1.单行注释//
2.多行注释/**/
3.文档注释/**  */
注释内容可以被jdk提供的工具javadoc解析,生成一套以网页文件形式体现的该程序的说明文档。

二,java基本语法

1.关键字和保留字

关键字:在Java语言里有特殊含义的字符串。
保留字:目前没用到,以后的版本可能会用到。

2.标识符

标识符:自己起的名字。包括:包名,类名。。。
0-9 _ $
数字不可以开头
不能使用关键字和保留字,可以包含
严格区分大小写
不能包含空格

3.变量

变量
变量:内存中的一个存储区域。
	可以在同一类型范围内变化。
包含:类型,名,存储的值。
作用:内存中保存数据。
	先声明,后使用。
	同一个作用域内,不能定义重复的变量名。
变量分类:按照数据类型分类
	基本数据类型:数值(整数,浮点数),字符,布尔
	引用数据类型:类(包括字符串),接口,数组
变量分类:按照声明位置不同分类
	成员变量:(类内,方法体外)
		包括:实例变量(不以static修饰),类变量(以static修饰)
	局部变量:(方法体内)
		包括:形参,方法局部变量,代码块局部变量
1.整型:byte,short,int,long 字节(1.2.4.8)1字节=8bit
	*long型变量的声明必须以l或L结尾
2.浮点型:float4),double8float:单精度浮点数,精确7*Java的浮点型常量默认为double类型,声明float常量,后加f或F。
3.字符类型 char2)
	表示方式:1.声明一个字符,2.定义一个转义符。
	char c='\n';
4.布尔类型	
	boolean:true,false
	双引号里面如果想要使用双引号,前面需要加\
	char+int=int
基本数据类型之间的运算
1.自动类型提升
    byte+int=int
	Java支持自动向上转型。
	当bytecharshort三种变量做运算时,结果为int2.强制类型转换
	向下转型
	强制类型转换符(int),可能会损失精度。
	*long赋值的数后面不加l可能会导致编译失败,过大的整数。
整型常量默认类型为int,浮点型默认常量为double。
String类型变量的使用
String属于引用类型。
String可以和所有类型做运算。

4.运算符

算术运算符
	a=2;b=++a;=>a=3,b=3;
	a=2;b=a++;=>a=3,b=2;
赋值运算符
比较运算符
逻辑运算符
	&和&&的异同:
	1)都表示且
	2)&&短路且
位运算符
三元运算符
三元运算符的嵌套:
	int sum=(a>b):a?((a==b)?"a==b":b)
	另一个三目运算符作为表达式出现

5.流程控制

顺序结构
分支结构
	if-else
	switch-case
	switch(表达式){
   
   
		case 常量1:
			执行语句;
			breakdefault:
			执行语句;
	}
	switch结构中的表达式,只能是如下6种数据类型:
	byteshortcharint,String,枚举。
例题:年份累加
循环结构:
	for
	while
	do{
   
   

	}while();
键盘输入:
import java.util.Scanner;
Scanner sc=new Scanner(System.in);
int a=sc.nextInt();
String b=sc.next();

三,数组

1.一维数组

1)数组默认值

数组元素的默认初始化值:
整型数组元素默认值为0
浮点型数组元素默认值0.0
布尔型数组元素默认值false
字符型数组元素默认值Ascii值位0的元素
引用数据类型数组元素默认值null

2)一位数组内存解析

在这里插入图片描述

在这里插入图片描述


2.二维数组

1)二维数组的使用

// 静态初始化
int[][] arr = new int[][] {
   
    {
   
    1, 2, 3 }, {
   
    4, 5 }, {
   
    6, 8, 7 } };
// 动态初始化1
int[][] arr1 = new int[3][2];
// 动态初始化2
int[][] arr2 = new int[3][];
// 调用arr2
arr2[1] = new int[3];// 先指定列的个数
for (int i = 0; i < arr2[1].length; i++) {
   
   
	System.out.println(arr2[1][i]);
}
// 如何获取数组的长度
System.out.println(arr.length);// 3
System.out.println(arr[0].length);// 3
// 二维数组元素的调用
for (int i = 0; i < arr.length; i++) {
   
   
	for (int j = 0; j < arr[i].length; j++) {
   
   
		System.out.println(arr[i][j]);
	}
}

2)二维数组默认初始值

int a[][]=new int[3][3];
System.out.println(a[0]);//输出地址[I@15db9742
System.out.println(a[0][0]);//0
System.out.println(a[2][3]);//java.lang.ArrayIndexOutOfBoundsException

3)二维数组的内存解析

在这里插入图片描述

3.数组中设计的常见算法:

1)反转

2)线性查找

3)二分查找

4)冒泡排序

4.Arrays工具类的使用

Arrays工具类的使用
int a[] = new int[] {
   
    43, 26, 25, 65, 89, 75, 45, 13, 23, 15, 65 };
int b[] = new int[] {
   
    43, 26, 25, 65, 89, 75, 45, 13, 23, 15, 65 };
System.out.println(Arrays.equals(a, b));//判断两个数组是否相等
Arrays.sort(a);//对数组进行从小到大排序
int key=89;
System.out.println(Arrays.binarySearch(a, key));//对排序后的数组进行二分查找
System.out.println(Arrays.toString(a));//输出数组信息

5.数组中的常见异常

1.下标越界异常
2.空指针异常
/*
* int a[] = new int[] { 43, 26, 25, 65, 89, 75, 45, 13, 23, 15, 65 }; a=null;
* System.out.println(a[0]);
*/
/*
* int[][]arr=new int [4][];
*  System.out.println(arr[0][0]);
*/
String arr[]=new String [] {
   
   "aa","bb","cc"};
arr[0]=null;
System.out.println(arr[0].toString());

四,面向对象

1.成员变量(属性)与局部变量的区别

不同点:
1.类中的声明位置不同
	1)类内,方法体外   
	2)方法的形参列表,方法体内,构造器形参,构造器内部变量
2.权限修饰符的不同
	1)可以在声明属性时指明其权限,使用权限修饰符
	2)不能使用权限修饰符
3.默认初始化值
	1)根据其类型都有默认的初始化值
	2)没有默认初始化值(调用之前显示赋值),形参在调用时赋值。
4.内存中加载的位置
	1)堆中(非static2)栈中

2.return关键字

1适用范围:使用在方法体中
2.作用:
1)结束方法
2)针对有返回值类型的方法,返回值。
3.return 后面不可以声明执行语句

方法中使用的注意点:
可以调用当前类的属性和方法
方法中不可以定义方法

3.对象数组

内存解析

在这里插入图片描述

4.匿名对象与方法重载

匿名对象

new Phone().price=1999;
new Phone().showPrice;//0.0
每次new的都是堆空间的一个新对象。

方法重载

1.定义:在同一个类中,允许存在一个以上同名方法,
只要他们的参数个数/顺序,参数类型不同即可。
2.特点:与返回值无关,与权限修饰符无关。
常见的:构造器重载

5.可变个数形参与变量赋值

可变个数形参

Object...args
如果有多个参数,必须放到最后。

变量赋值

如果变量是基本数据类型:此时赋值的是变量所保存的数据值。
如果变量时引用数据类型:此时赋值的是变量所保存数据的地址值。
此时改变变量的值,相当于改变地址对应的值。

6.值传递机制与递归方法

值传递机制

形参:方法定义时,小括号内的参数。
实参:方法调用时,实际传递给形参的值。
如果参数是基本数据类型,此时赋值的是变量所保存的数据值。
如果参数是引用数据类型,此时赋给形参的值,是变量所指向地址的值。

递归方法

一个方法体内,自己调用自己。

/**
 * 递归方法求1-100的和
 */
public static void main(String[] args) {
   
   
    int n = 100;
    int sum = getSum(n);
    System.out.println(sum);
}

public static int getSum(int sum) {
   
   
    if (sum == 1) {
   
   
        return 1;
    } else {
   
   
        return sum + getSum(sum - 1);
    }
}
/**
 * 已知一个数列,f(0)=1,f(1)=4,f(n+2)=2*f(n+1)+f(n);
 * 其中n是大于0的整数,求f(10。
 *
 * @param sum
 * @return
 */
public static int getSum(int sum) {
   
   
    if (sum == 0) {
   
   
        return 1;
    } else if (sum == 1) {
   
   
        return 4;
    } else {
   
   
        return 2 * getSum(sum - 1) + getSum(sum - 2);
    }
}
/**
 * 递归方法求斐波那契数列的前n项,并输出。
 * @return
 */
public static void main(String[] args) {
   
   
    int arg=10;
    int avg=getArgs(arg);
    System.out.println(avg);
}
public static int getArgs(int args){
   
   
    if(args<=2){
   
   
        return 1;
    }
    else{
   
   
        return getArgs(args-1)+getArgs(args-2);
    }
}

7.封装和隐藏

封装和隐藏:

特点:
高内聚:类的内部数据操作细节自己完成,不允许外部干涉
低耦合:仅仅对外暴漏少量方法用于使用。
体现:私有化属性,设置公有的方法来获取和设置属性。需要权限修饰符来配合。

权限修饰符:

1.private:类内部
2.default:同一包下的类
3.protected:不同包的子类
4.public:同一项目下
用来修饰类:public和default,和类的内部结构:属性,方法,构造器,内部类。

构造器:construct

作用:
1)创建对象
2)初始化对象
构造器重载

属性赋值的先后顺序:

1)默认初始化
2)显示初始化
3)构造器初始化
4)set方法

javabean

类是公有的
有一个无参的公共构造器
有属性,且有对应的get,set方法

关键字this的使用

1this可以用来修饰属性和方法
this代表当前对象
2this可以用来修饰和调用构造器
调用构造器:
public Student(Integer number, Integer state) {
   
   
this.number = number;
this.state = state;
}

public Student(Integer number, Integer state, Double score) {
   
   
this(number,state);//调用其他构造器,不能调用自己。
this.score = score;
}

MVC设计模式:

视图模型层view
控制器层controller:service,base,activity
模型层model:bean,dao,db

继承性:extends

减少了代码的量,提高了代码复用性
便于功能的拓展
为多态的实现提供了前提
一旦子类A继承父类B以后,A就获取了B中声明的所有属性和方法。
规定:
一个类可以被多个子类继承
一个类只能由一个父类
允许多层继承

8.Eclipse中的Debug

Debug:
1.设置断点:
2.按键:
F5进入方法,F6一行一行执行,F7从方法中出来
resume:终止此处断点,进入下一处。
   Terminate:强行终止
   debug中step into功能失灵问题:更换eclipsejre为jdk的。

9.方法重写与权限修饰符

方法重写

1.重写:子类继承父类以后,可以对父类中同名同参数的方法,进行覆盖操作。
2.应用:重写以后,当子类执行该方法,实际上执行的是子类重写父类的方法。
3.规定:
方法名形参列表必须相同,

子类重写方法的权限修饰符不小于父类被重写的方法,
*子类不能重写父类的私有方法,
返回值类型:void--》void,其他的小于等于父类的返回值类型。
子类抛出的异常类型不能大于父类。
非static(因为静态方法不能被覆盖,随着类的加载而加载)

权限修饰符

四种权限修饰符
在不同包的子类中,能调用order类中声明为protected和public的属性,方法。
不同包下的不同类(非子类)只能调用order类中的public的属性和方法。

10.super关键字

super调用属性和方法
1.我们可以在子类的方法或构造器中,通过使用"super."属性/方法的方式,显示的调用
父类中声明的属性或方法,通常省略。
2.特殊情况下,当子类和父类定义了同名的属性时,用super来调用父类的方法。
3.当子类重写了父类的方法,在子类的方法中调用父类中被重写的方法,必须使用super4.super调用构造器:
public Student(int id,String name,String school){
   
   
super(id,name);//调用父类的构造器
this.school=school;
}
在子类构造器中用super(形参列表)调用父类中声明的指定的构造器。
super声明在子类构造器首行。

11.子类对象实例化全过程:

1.从结果上看,
子类继承父类以后,就获取了父类中声明的属性和方法;
创建子类对象,在堆空间中,就会加载所有父类中声明的属性。
2.从过程上看,
当我们通过子类的构造器创建子类对象时,我们一定会直接或间接地调用其父类构造器,
进而调用父类的父类的构造器,知道调用了Object的无参构造器为止。正因为加载过所
有的父类结构,所以才可以看到内存中有父类的结构,子类对象才可以进行调用。

12.向下转型

向下转型:使用强制类型转换符
Person p=new Student();//此时p并不能调用Student中重写的方法。
Student stu=(Student)p;//此时就可以了

13.instanceof关键字:

stu instanceof p:
判断对象stu是否是类p的实例,如果是,返回true,如果不是,返回false。
使用情景:为了避免向下转型时出现类型转换异常,我们在向下转型之前,先用
instanceof进行判断,如果返回true在进行转型。

14.java.lang.Object

1.Object类时左右Java类的父类
2.如果在声明类时没有指明类的直接父类,默认类的父类为Object。
3.Object类中的功能(属性,方法)具有通用性。
属性:无。
方法:equals()/toString()/getClass()/hashCode()/clone()克隆/finalize()垃圾回收
4.Object类只声明了一个空参构造器

15.==和equals()的区别

1.==可以使用在基本数据类型和引用数据类型变量中
2.==如果比较基本数据类型变量,比较的是数据是否相等(不一定类型要相同)。
  如果比较引用类型变量,比较的是地址值是否相等,即两个对象是否指向同一个对象实体。
1.equals()是一个方法,不是运算符。
2.只适用引用数据类型。
3.Object类中equals的定义:
   public boolean equals(Object obj) {
        return (this == obj);
    }
  String类中定义的equals方法:
  STring对equals方法进行了重写,如果地址相同,返回true,
  否则比较字符串的值是否相同。

16.equals()方法的重写:

public boolean equals(Object o) {
   
   
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Customer customer = (Customer) o;
        return age == customer.age &&
            Objects.equals(name, customer.name);
    }

17.Object类中toString()的使用:

1.当我们输出一个对象的引用,实际上就是调用当前对象的toString()
2.Object类中对toString()的定义:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
3.向String,Date,File。包装类实际上都重写了Object的toString方法。
使得在调用对象的toString方法时,返回实体对象信息。
4.自定义类重写toString方法

18.包装类

八种数据类型都有对应的包装类
char–>Character

public static void main(String[] args) {
   
   
    /**
     * 基本数据类型和包装类,String的转换
     * jdk5.0新特性:自动拆箱与自动装箱
     */
    //包装类转换为基本数据类型
    Integer a=10;
    int b=a;//自动拆箱
    int c=a.intValue();//int->integer
    //基本数据类型转换为包装类
    int num1=10;
    Integer num2=num1;//自动装箱
    Integer num3=new Integer(num1); //integer->int
    //基本数据类型和包装类与String的转换
    int num=1;
    String s1=num+"";//int->String
    String s2=String.valueOf(num);//int->String
    Integer number=10;
    String s3=String.valueOf(number);//integer->String
    int aa=Integer.parseInt(s3);//String->int
    Integer bb= Integer.parseInt(s3);//String->integer
}

/**
 * 面试题:
 * 三目运算符后面两个条件语句对应的类型会在比较前进行统一。
 */
Object o1=true?new Integer(1):new Double(2.0);
System.out.println(o1);//1.0

Integer内部存在一个Integer[]数组,范围-128–+127,如果我们是用自动装箱的方式,
给integer赋值的范围在此范围内直接从数组中取。

19.static关键字

1.可以用来修饰属性,方法,代码块,内部类
2.修饰属性:
静态属性(类变量)和非静态属性(实例变量)
实例变量:每个对象都有自己的实例变量。
静态变量:所有对象共享静态变量。通过一个对象修改,别的对象调用的也是修改过的。
public static void setCountry(String country) {
Chinese.country = country;
}
静态变量随着类的加载而加载。
静态变量的加载早于对象的创建。
由于类只会加载一次,则静态变量在内存中也只存在一份,在方法区的静态域中。
3.修饰方法:
静态方法_随着类的加载而加载。
静态方法中只能调用静态的方法或属性。
非静态方法中,既可以调用非静态的方法或属性,也可以调用静态的方法或属性。
4.开发中如何确定一个属性要声明为static?
所有对象都相同的属性。
开发中如何确定一个方法要声明为static?
操作静态属性的方法
工具类中的方法
static实现id自增
private static int idadd=1001;

类变量与实例变量的内存解析

在这里插入图片描述

20.单例设计模式:

1.采取一定的方法,保证在整个软件系统中,对某个类只能存在一个对象实例。
2.饿汉式vs懒汉式实现:
//饿汉式
public class Test1 {
   
   
    //私有的构造器
    private Test1(){
   
   
    }
    //私有的创建对象
    private static Test1 test=new Test1();
    //公有的方法供外部调用
    public static Test1 getTest1(){
   
   
        return test;
    }
}
//懒汉式
public class Test1 {
   
   
    //私有的构造器
    private Test1(){
   
   
    }
    //私有的创建对象
    private static Test1 test=null;
    //公有的方法供外部调用
    public static Test1 getTest1(){
   
   
        if(test==null){
   
   
            test=new Test1();
        }
        return test;
    }
}
3.懒汉式和饿汉式的对比:
饿汉式占用内存,线程安全的。
懒汉式好处:延迟对象的创建,线程不安全。
4.应用场景:
网站计数器,应用程序的日志应用,数据库连接池,Application。

main()方法的使用说明
也是一个普通的静态方法
可以做输入

21.代码块:和属性赋值顺序完结篇

作用:用来初始化对象。
只能用static来修饰
分类:静态代码块,非静态代码块
非静态能调用静态的属性方法,静态的不能掉用非静态的属性方法。
1.静态代码块
随着类的加载而执行
一共只执行一次,因此可以初始化类的信息。
2.非静态代码块
随着对象的创建而执行
每次创建对象都会执行一次,因此可以创建对象时初始化对象。
属性赋值顺序完结篇
1)默认初始化
2)显示初始化/在代码块中赋值
3)构造器初始化
4)set方法

22.final关键字

1.final修饰类和方法
用final修饰的类不能被继承,称为最终类。
eg:String,System,StringBuffer
用final修饰的方法不能被重写。
2.final修饰变量
此时的变量就称为常量。
1)修饰属性
显式初始化,代码块中初始化。
2)修饰局部变量
该局部变量的值不能被再次修改

23.抽象类与抽象方法

abstract关键字的使用
1.abstract抽象的
2.可以用来修饰的结构:类和方法
3.abstract修饰类:抽象类
1)此类不能实例化
2)抽象类中一定有构造器,便于子类实例化时调用。
3)开发中,都会提供抽象类的子类,让子类对象实例化,完成相关操作。
4.abstract修饰方法:抽象方法
public abstract void test();
包含抽象方法的类一定是抽象类,抽象类不一定包含抽象方法。
如果继承了抽象类,必须继承抽象类的抽象方法。
5.注意
1abstract不能用来修饰:属性,构造器。
2abstract不能用来修饰私有方法,静态方法,final方法,final的类。

创建抽象类的匿名子类对象
Person p=new Person(){
   
   //Person是一个抽象类
public void eat(){
   
   
}
public void walk(){
   
   
}
};

24.接口:interface

1.接口的使用用interface来定义
2.Java中,接口和类是并列的两个结构。
3.如何定义接口,定义接口的成员
	1)jdk7以前,只能定义全局常量和抽象方法
	全局常量:public static final的,但是书写时,可以省略不写
	抽象方法:public abstract的,但是书写时,可以省略不写。
	2)jdk8:除了定义全局常量和抽象方法外,还可以定义静态方法,默认方法。
4.接口中不能定义构造器,接口不能实例化。
5.Java中,通过类去实现接口。implements
6.Java中允许实现多个接口。
7.接口与接口之间可以多继承
8.接口的实现体现了多态性。
面试题:接口与抽象类的比较:
	1.抽象类:通过extends来继承,只能继承一个抽象类,
		抽象类中一定有构造方法,创建子类对象时被调用。
		抽象类中不光有抽象方法,还可以有其他方法。
	2.接口:接口通过implements来实现,允许实现多个接口,
		接口中不存在构造方法,接口中只能声明全局常量和抽象方法,
		jdk'8.0以后,还可以定义静态方法和默认方法。
	3.不能实例化,都可以被继承。

接口的应用:

代理模式
/**
 * 代理模式:将两者都要实现的行为封装在接口中,被代理对象和代理对象都继承该接口
 * 代理对象中声明被代理对象属性,并创建拥该属性的构造器,通过创建代理对象完成
 * 被代理对象的方法。
 */
class TEST{
   
   
    public static void main(String[] args) {
   
   
        Zhuli zhuli=new Zhuli(new Star());
        zhuli.sing();
        zhuli.buyThing();
        zhuli.getMoney();
    }
}
public class Star implements Proxy {
   
   //被代理对象
    @Override
    public void sing() {
   
   
        System.out.println("明星唱歌");
    }

    @Override
    public void getMoney() {
   
   

    }

    @Override
    public void buyThing() {
   
   

    }
}

interface Proxy {
   
   
    public void sing();

    public void getMoney();

    public void buyThing();
}
class Zhuli implements Proxy{
   
   //代理对象
private Star star;//声明被代理对象
    public Zhuli(Star star){
   
   //存在被代理对象的带参构造器
        this.star=star;
    }
    @Override
    public void sing() {
   
   
star.sing();//被代理对象完成
    }

    @Override
    public void getMoney() {
   
   
        System.out.println("助理替歌手收钱");
    }

    @Override
    public void buyThing() {
   
   
        System.out.println("助理替歌手买东西");
    }
}
工厂模式

实现创建者与调用者的分离,将创建对象的具体过程隔离起来。

public interface Java8 {
   
   
    /**
     * 接口中定义的静态方法只能通过接口来调用
     */
    public static void test1(){
   
   
        System.out.println("***");
    };

    /**
     * 通过实现类的对象可以调用/重写接口中的默认方法
     */
    public default void test2(){
   
   
        System.out.println("***");
    }
    /**
     * 如果一个类继承的父类和实现的接口存在同名同参数的方法,
     * 子类在没有重写这个方法的前提下,默认调用父类的方法
     */
    /**
     * 如果一个类实现的多个接口中存在同名同参数的方法,
     * 子类在没有重写这个方法的前提下,会报错,接口冲突。
     * 如果重写的方法想要调用其中的一个:接口.super.method
     */
}

25.内部类的使用:

1.Java中允许将一个类声明在另一个类的内部
2.内部类的分类:成员内部类(静态,非静态)vs局部内部类(方法,代码块,构造器内)
3.成员内部类:


class Demo{
   
   
    public static void main(String[] args) {
   
   
        /**
         * 创建内部类实例
         */
        Person.Dog dog=new Person.Dog();//静态内部类
       Person p=new Person();//非静态内部类
       Person.Bird bird=p.new Bird();
    }
}
class Person {
   
   
    private String name;
    public void eat(){
   
   
        System.out.println("吃饭");
    }

    /**
     * 内部类可以被final修饰,表示此类不能被继承
     * 内部可以定义属性方法构造器
     * 可以被abstract修饰
     */
     static class Dog{
   
   
        //eat();不能调用外部的eat方法
    }
    class Bird{
   
   
      public Bird(){
   
   
         
     }

        /**
         * 调用外部成员的方法
         */
        
     public void sing(){
   
   
         eat();
         name="bird";
     }
    }

}
面试题:创建静态内部类对象和非静态内部类对象:
//静态内部类对象
Person.Dog dog=new Person.Dog();
//非静态内部类对象
Person p=new Person();
Person.Bird bird=new p.bird();

五,异常处理

1.异常的体系结构

异常:在Java中,程序执行发生的不正常情况称为异常。
java.long.Throwable
1.java.long.Error,:一般不编写针对性代码进行处理
2.java.long,Exception:可以进行异常的处理
1)编译时异常:IOException,FileNotFindException,ClassNotFindException
2)运行时异常:NullPointException,ArrayIndexOutOfBoundsException,ClassCastException
,NumberFormatException,InputMismatchException,ArithmeticException

2.异常处理机制一:

try-catch-finally
一旦抛出异常,其后的代码就不再执行。
try {
      //可能会出现异常的代码
} catch (异常处理类型1 变量名1) {
e.printStackTrace
} catch (异常处理类型2 变量名2) {
e.printStackTrace
} finally {
    //最终一定要执行的代码
}

编译时异常和运行时异常的不同处理
开发时运行时异常不需要try-catch
编译时异常用try-catch来解决

3.异常处理机制二:Throws +异常类型

“throws+异常类型”写在方法声明处,指明方法执行时,可能会抛出的异常。
一旦当方法体执行时,出现异常,仍会在异常代码处生成一个异常类的对象,
此对象满足throws的异常类型时就会抛出,异常代码后续的代码,就不要执行。

try-catch真正的将异常处理掉了,而throws只是将异常抛给了方法的调用者,并没有真正的处理掉。

重写方法异常抛出的规则
子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型

开发中如何选择try-catch还是throws
1.如果父类被重写的方法没有抛出异常,则子类重写的方法中的异常只能用try-catch
2.执行的方法a中,先后又调用了另外的几个方法,这几个方法是递进关系执行的,
我们建议这几个方法使用throws的方法进行处理,而方法a可以用try-catch进行处理。

4.手动生成一个异常对象并抛出:throw

public class MyException {
   
   
    public static void main(String[] args) {
   
   
        person p=new person();
        try {
   
   
            p.setAge(-1001);
        } catch (Exception e) {
   
   
            System.out.println(e.getMessage());
        }
    }
}
class person {
   
   
    private int age;
    public person(){
   
   

    }
    public void setAge(int age) throws Exception{
   
   
        if (age>0){
   
   
            this.age=age;
        }else{
   
   
            throw  new Exception("年龄不能小于0!");
        }
    }
    public int getAge(){
   
   
        return age;
    }
}

5.用户自定义异常:

/**
 * 自定义异常
 * 1.继承于现的异常结构,RuntimeException,Exception
 * 2.提供全局常量, static  final long serialVersionUID
 * 3.提供重载的构造器
 */
public class TestException extends IOException {
   
   
    static  final long serialVersionUID=-7034897190745766939L;
    public TestException(){
   
   

    }
    public TestException(String msg){
   
   
        super(msg);
    }

}

六,多线程

1.概述

1)概念

程序:为完成特定任务,用某种语言编写的一组指令的集合。
一段静态的代码,静态对象。
进程:程序的一次执行过程,或是正在运行的一个程序。
是一个动态的过程,有他本身的生命周期。
独立的方法区和堆空间
线程:一个程序内部的执行路径。
独立的计数器和栈
单核cpu和多核cpu
假的多线程,多个线程交替进行。
并行和并发
并行:多个cpu同时执行多个任务。
并发:一个cpu执行多个任务。
并行:传输的数据8位一送出去
串行:传输的数据1位1送出去

2)优点

1.提高应用程序的响应,增强图形化界面用户的体验。
2.提高cpu利用率
3.改善程序结构,将复杂的程序分为多个线程。

3)何时需要

1.程序需要同时执行多个任务。
2.程序需要实现一些需要等待的任务时,用户输入,文件读写,网络操作,搜索。
3.需要一些后台运行的程序。

2.创建线程的方式一:继承Thread类

/**
 * 多线程的创建:继承Thread类
 * 重写run方法-->将线程执行的操作声明在run方法
 * 创建子类的对象,通过此对象调用start方法
 */
public class MyThread extends Thread {
   
   
    public void run(){
   
   
        for (int i = 0; i <100 ; i++) {
   
   
            System.out.println(this.currentThread().getName()+" "+i);
        }
    }
}
class Test1{
   
   
    public static void main(String[] args) {
   
   
        MyThread m1=new MyThread();
        m1.start();
    }
}

1)线程的常用方法:

*start():启动当前线程:调用当前线程的run方法
* run();通常需要重写Thread类的run方法,将创建线程要执行的操作声明在此方法
* currentThread():静态方法,返回执行当前代码的线程。
* getName():获取当前线程名
* setName():设置当前线程的名字
* yield():释放当前cpu执行权
* join():在线程a中调用线程b的join方法,a进入阻塞状态,直到b执行完以后,a才结束阻塞状态。优先权
* sleep():挂起一会儿,单位ms
* stop():强制终止,死亡

2)线程优先级:

1.
MAX_PRIORITY:10
MIN_PRIORITY:1
NORM_PRIORITY:5
2.如何获取和设置当前线程优先级:
m1.setPriority();
m1.getPriority();
优先级高并不一定代表一定先执行,只是概率大一点。

3)案例:多窗口卖票

/**
 * 继承Thread方法实现多窗口卖票,存在线程安全问题
 */
public class ThreadTest1 {
   
   
    public static void main(String[] args) {
   
   
        Window w1=new Window();
        Window w2=new Window();
        w1.start();
        w2.start();
    }
}
class Window extends Thread{
   
   
    private static int piao=100;
    public void run(){
   
   
        while (true){
   
   
            if (piao>0){
   
   
                System.out.println(currentThread().getName()+" "+piao);
                piao--;
            }else{
   
   
                break;
            }
        }
    }
}

3.创建多线程的方式二:实现runnerable接口的方式

/**
 * 通过实现runnable接口创建多线程
 * 1.创建类a实现runnable接口
 * 2.类a重写runnable的run(方法
 * 3.在调用方法里创建a的对象;
 * 4创建Thread对象b并传入a的对象
 * 5.b.start(;
 */
public class RunnableTest2 {
   
   
    public static void main(String[] args) {
   
   
        myRunnable m1=new myRunnable();
        Thread t1=new Thread(m1);
        t1.start();
    }

}
class myRunnable implements Runnable{
   
   
    public void run(){
   
   
        for (int i = 0; i <10 ; i++) {
   
   
            System.out.println(Thread.currentThread().getName()+" "+i);
        }
    }
}

1)案例:多窗口卖票

**
 * runnable方式实现多窗口卖票,存在线程安全问题
 */
public class RunnableTest {
   
   
    public static void main(String[] args) {
   
   
        MyRunnable m1=new MyRunnable();
        Thread t1=new Thread(m1);
        Thread t2=new Thread(m1);
        Thread t3=new Thread(m1);
        t1.start();
        t2.start();
        t3.start();
    }
}
class MyRunnable implements Runnable{
   
   
    private int piao;

    /**
     * 此处不用static修饰的原因,因为上面类中的方法仅仅new了一个此类的对象,
     * 所以个Thread对象实际上只是使用了同一个对象的票。
     */
    public void run(){
   
   
        while(true){
   
   
            if (piao>0){
   
   
                System.out.println(Thread.currentThread().getName()+" :"+piao);
                piao--;
            }else{
   
   
                break;
            }
        }
    }
}

2)线程的生命周期

线程的生命周期
Thread.state();
1.新建    new
2.就绪    start
3.运行    run
4.阻塞    join,sleep,等待同步锁,wait,(过时的挂起)
5.死亡    stop

在这里插入图片描述

4.线程的同步

/**
 * runnable方式实现多窗口卖票,存在线程安全问题
 * 1.买票过程中出现重票错票
 * 2.问题描述:当某个线程操作车票的过程中,尚未操作完成,其他线程参与进来,也操作车票。
 * 3.如何解决:当一个线程在操作共享数据的时候,其他线程不能参与进来,直到线程a操作完,其他线程才能参与进来,
 * 即使线程a出现了阻塞,也不能被改变。
 * 4.在Java中我们通过同步机制,来解决线程安全问题。
 * 方式一:同步代码块
 * synchronized (同步监视器){
 * 需要被同步的代码
 *不能包多了,也不能包少了
 * }
 * 说明:1.操作共享数据的代码,就是需要被同步的代码。
 * 2.共享数据:多个线程共同操作的数据。
 * 3.同步监视器:俗称锁。任何一个类的对象都可以来充当锁。
 * 要求:多个线程必须公用同一把锁。
 * 补充:在实现runnable接口创建的多线程方式中,我么可以考虑使用this关键字充当锁,
 * 在继承Thread类创建的多线程方式中,我们可以考虑使用当前类.class的方式充当锁。
 * 方式二:同步方法
 *如果操作共享数据的代码,完整的声明在一个方法中,我们不妨将此方法声明为同步的。
 * 1.同步方法仍然涉及到同步监视器,只是不需要我i们显示的声明
 * 2.非静态的同步方法,同步监视器是this,静态方法的同步监视器是类的本身。
 * 5.同步的方式:解决了安全问题--好处
 * 操作同步代码时,只能有一个线程参与,其他线程等待,相当于是一个单线程的过程,效率低。--缺点
 */

通过继承Thread类实现多窗口卖票

/**
 * 使用同步代码块方式解决线程安全问题
 * 通过继承Thread类实现多窗口卖票
 */
public class TreadTest1 {
   
   
    public static void main(String[] args) {
   
   
        window1 w1=new window1();
        window1 w2=new window1();
        w1.setName("窗口一");
        w2.setName("窗口二");
        w1.start();
        w2.start();
    }
}
class window1 extends Thread {
   
   
    private static int ticket=100;

    @Override
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值