JAVA基础

关键字:package、import的使用

一、package关键字的使用

​ 1.为了更好的实现项目中类的管理,提供包的概念
​ 2.使用package声明类或接口所属的包,声明在源文件的首行
​ 3.包,属于标识符,遵循标识符的命名规则、规范(xxxyyyzzz)、“见名知意”
​ 4.每“.”一次,就代表一层文件目录。
​ 补充:同一个包下,不能命名同名的接口、类。
​ 不同的包下,可以命名同名的接口、类。

JDK中主要的包介绍

  1. java.lang----包含一些Java语言的核心类,如String、Math、Integer、System和Thread,提供常用功能
  2. java.net----包含执行与网络相关的操作的类和接口。3. java.io ----包含能提供多种输入/输出功能的类。
  3. java.util----包含一些实用工具类,如定义系统特性、接口的集合框架类、使用与日期日历相关的函数。
  4. java.text----包含了一些java格式化相关的类
  5. java.sql----包含了java进行JDBC数据库编程的相关类/接口
  6. java.awt----包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)。B/S C/S

MVC的设计模式

​ MVC是常用的设计模式之一,将整个程序分为三个层次:视图模型层,控制器层,与数据模型层。这种将程序输入输出、数据处理,以及数据的展示分离开来的设计模式使程序结构变的灵活而且清晰,同时也描述了程序各个对象间的通信方式,降低了程序的耦合性。

模型层 model 主要处理数据

数据对象封装 model.bean/domain

数据库操作类 model.dao

数据库 model.db

控制层controller处理业务逻辑

应用界面相关 controller.activity

存放fragment controller.fragment

显示列表的适配器 controller.adapter

服务相关的 controller.service

抽取的基类 controller.base

视图层 view显示数据

相关工具类 view.utils

自定义view view.ui

二、import关键字的使用

import:导入

1.在源文件中显式的使用import结构导入指定包下的类、接口2.声明在包的声明和类的声明之间
3.如果需要导入多个结构,则并列写出即可
4.可以使用"xxx."的方式,表示可以导入XXx包下的所有结构
5.如果使用的类或接口是java.lang包下定义的,则可以省略import结构
6.如果使用的类或接口是本包下定义的,则可以省略import结构
7.如果在源文件中,使用了不同包下的同名的类,则必须至少有一个类需要以全类名的方式显示。
8.使用"xXx.
"方式表明可以调用xXX包下的所有结构。但是如果使用的是Xxx子包下的结构,则仍需要显式导入
9.import static:导入指定类或接口中的静态结构∶属性或方法。

面向对象的特征一:封装与隐藏

1.为什么要引入封装性?

我们程序设计追求“高内聚,低耦合”。

高内聚:类的内部数据操作细节自己完成,不允许外部千涉;
低耦合:仅对外暴露少量的方法用于使用。

隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。通俗的说,把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想。

2.问题引入:

当我们创建一个类的对象以后,我们可以通过"对象.属性"的方式,对对象的属性进行赋值。这里,赋值操作要受到属性的数据类型和存储范围的制约。除此之外,没其他制约条件。但是,在实际问题中,我们往往需要给属性赋值加入额外的限制条件。这个条件就不能在属性声明时体现,我们只能通过方法进行限制条件的添加。(比如: setLegs()同时,我们需要避免用户再使用"对象.属性"的方式对属性进行赋值。则需要将属性声明为私有的(private).
–>此时,针对于属性就体现了封装性。

3.封装性思想具体的代码体现:

体现一:将类的属性xxx私化(private),同时,提供公共的(public)方法来获取(getXxx)和设置(setXxx)此属性的值

private double radius;
public void setRadius(double radius){
   
this.radius = radius;
}
public double getRadius(){
   
return radius;
}

体现二:不对外暴露的私有的方法

体现三:单例模式(将构造器私有化)

体现四:如果不希望类在包外被调用,可以将类设置为缺省的。

4.Java规定的四种权限修饰符

4.1权限从小到大顺序为: private <缺省<protected < public
4.2具体的修饰范围:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kdvEMUuo-1646661895046)(D:\Program Files\Testedit\Note\Pictures\image-20211125205056940.png)]

4.3 权限修饰符可用来修饰的结构说明:
4种权限都可以用来修饰类的内部结构:属性、方法、构造器、内部类、修饰类的话,只能使用:缺省、public

构造器(或构造方法) : constructor

1.构造器的作用:

1.创建对象
2.初始化对象的信息

2.使用说明:

1.如果没显式的定义类的构造器的话,则系统默认提供一个空参的构造器
2.定义构造器的格式:权限修饰符  类名(形参列表){}
3.一个类中定义的多个构造器,彼此构成重载
4.一旦我们显式的定义了类的构造器之后,系统就不再提供默认的空参构造器
5.—个类中,至少会有一个构造器。
所谓avaBean,是指符合如下标准的java类:
>类是公共的
>一个无参的公共的构造器
>属性,且对应的get. set方法

面向对象特征之二:继承性

一、继承性的好处:

1.减少了代码的冗余,提高了代码的复用性
2.便于功能的扩展
3.为之后多态性的使用,提供了前提

二、继承性的格式:class A extends B{}

A:子类、派生类、subclass
B:父类、超类、基类、superclass
2.1体现:一旦子类A继承父类B以后,子类A中就获取了父类B中声明的所有的属性和方法。
   特别的,父类中声明为private的属性或方法,子类继承父类以后,仍然认为获取了父类
   中私有的结构。只有因为封装性的影响,使得子类不能直接调用父类的结构而已。
2.2子类继承父类以后,还可以声明自己特有的属性或方法:实现功能的拓展。子类和父类的关系,
   不同于子集和集合的关系。
extends:延展、扩展

三、Java中关于继承性的规定:

1.一个类可以被多个子类继承。
2.Java中类的单继承性:一个类只能有一个父类3.子父类是相对的概念。
4.子类直接继承的父类,称为:直接父类。间接继承的父类称为:间接父类
5.子类继承父类以后,就获取了直接父类以及所有间接父类中声明的属性和方法

四、1.如果我们没有显式的声明一个类的父类的话,则此类继承于java.lang.object类

2.所有的java类 (除java.lang.object类之外)都直接或间接的继承于java.lang.object类
3.意味着,所有的java类具有java.lang.object类声明的功能

super关键字的使用

  • 1.super理解为:父类的

  • 2.super可以用来调用:属性、方法、构造器

  • 3.super的使用

    • 3.1 我们可以在子类的方法或构造器中。通过使用"super .属性"或"super.方法"的方式,显式的调用父类中声明的属性或方法。但是,通常情况下,我们习惯省略"super. "
    • 3.2 特殊情况:当子类和父类中定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须显式的使用"super.属性"的方式,表明调用的是父类中声明的属性。
    • 3.3 特殊情况:当子类重写了父类中的方法以后,我们想在子类的方法中调用父类中被重写的方法时,则必须显式的使用"super.方法"的方式,表明调用的是父类中被重写的方法。
  • 4.super调用构造器

    • 4.1 我们可以在子类的构造器中显式的使用"super(形参列表)"的方式,调用父类中声明的指定的构造器
    • 4.2 "super(形参列表)“的使用,必须声明在子类构造器的首行!
    • 4.3 我们在类的构造器中,针对于"this(形参列表)"或"super(形参列表)"只能二选一,不能同时出现.
    • 4.4 在构造器的首行,没有显式的声明"this(形参列表)"或"super(形参列表)"默认调用的是父类中空参的构造器:super();
    • 4.5 在类的多个构造器中,至少有一个类的构造器中使用了"super(形参列表)",调用父类中的构造器

面向对象特征之三:多态性

1.理解多态性:

可以理解为一个事物的多种形态。

2.何为多态性:

对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)

3.多态的使用:虚拟方法调用

有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。
总结:编译,看左边;运行,看右边。

4.多态性的使用前提:

① 类的继承关系 ② 方法的重写

5.对象的多态性:

只适用于方法,不适用于属性(编译和运行都看左边)。

6.关于向上转型与向下转型:

  • 向上转型:多态
  • 向下转型:
    • 为什么使用向下转型:有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的,但是由于变量声明为父类类 型,导致编译时,只能调用父类中声明的属性和方法。子类特有的属性和方法不能调用。如何才能调用子 类特的属性和方法?使用向下转型

    • 如何实现向下转型:使用强制类型转换符:()

    • 使用时的注意点:

      • 使用强转时,可能出现classCastException的异常。
      • 为了避免在向下转型时出现ClassCastException的异常,我们在向下转型之前,先进行instanceof的判断,一旦返回true,就进行向下转型。如果返回false,不进行向下转型。
    • instanceof的使用:

      • a instanceof A:判断对象a是否是类A的实例。如果是,返回true;如果不是,返回false.
      • 如果a instanceof A返回true,则 a instanceof B也返回true。其中,类B是类A的父类。
      • 要求x所属的类与类A必须是子类和父类的关系,否则编译错误。
    • 图示

方法的重载和重写

1.二者的概念

重载:在同一个类中,可以声明多个方法名相同,形参列表不同的方法,彼此之间构成重载,构造器也可以重载。

重写:大前提:要有子父类,子类继承父类之后,可以对父类中同名同参数的方法进行覆盖操作

重载不表现为多态性,重写变现为多态性

2.从编译和运行的角度看:

重载:

是指允许存在多个同名方法,而这些方法的参数不同。编译器根据方法不同的参数表,对同名方法的名称做修饰。对于编译器而言,这些同名方法就成了不同的方法。它们的调用地址在编译期就绑定了。Java的重载是可以包括父类和子类的,即子类可以重载父类的同名不同参数的方法。
所以:对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法,这称为“早绑定”或“静态绑定”
而对于多态,只有等到方法调用的那一刻,解释运行器才会确定所要调用的具体方法,这称为“晚绑定”或“动态绑定”。

重写

约定俗称:子类中的叫重写的方法,父类中的叫被重写的方法
① 子类重写的方法的方法名和形参列表与父类被重写的方法的方法名和形参列表相同
② 子类重写的方法的权限修饰符不小于父类被重写的方法的权限修饰符
>特殊情况:子类不能重写父类中声明为private权限的方法
③ 返回值类型:
>父类被重写的方法的返回值类型是void,则子类重写的方法的返回值类型只能是void
>父类被重写的方法的返回值类型是A类型,则子类重写的方法的返回值类型可以是A类或A类的子类。
>父类被重写的方法的返回值类型是基本教据类型(比如:double、int),则子类重写的方法的返回
值类型必须是相同的基本数据类型
④ 子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型(具体放在异常处理时候讲)
子类和父类中的同名同参数的方法要么都声明为非static的(只有非static的考虑重写),
要么都声明为static的(static的就不可以重写了)。

子类对象实例化全过程

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

== 和 equals 的区别

一、回顾==的使用

==:运算符
1.可以使用在基本数据类型变量和引用数据类型变量中
2.如果比较的是基本数据类型变量:比较两个变量保存的数据是否相等。(不一定类型要相同)
如果比较的是引用数据类型变量:比较两个对象的地址值是否相同,即两个引用是否指向同一个对象实体

二、equals()方法的使用:

1.是一个方法,而非运算符

2.只能适用于引用数据类型

3.object类中equals()的定义:
public boolean equals (object obi) {
return (this ==obj);
}

说明:0bject类中定义的equals()和==的作用是相同的:比较两个对象的地址值是否相同,即两个引用是否指向同一个对象实体

4.像String、Date、File、包装类等都重写了0bject类中的equals()方法,重写以后,比较的不是两个引用的地址是否相同,而是比较两个对象的“实体内容”是否相同。

5.通常情况下,我们自定义的类如果使用equals()的话,也通常是比较两个对象的"实体内容"是否相同。那么我们就需要对Object类中的equals()进行重写.

  • 重写的原则:比较两个对象的实体内容是否相同

6.如果不重写,比的是地址,重写之后比的是“实体内容”,String,Date,File,不用重写。

//重写equals()方法
public boolean equals(Object obj){
   
    if (this == obj){
   
        return true;
    }
    if (obj instanceof Order){
   
          ((Order) obj).orderId,
        Order order = (Order) obj;//如果不强制转换,obj.不出来orderId
        return this.orderId == order.orderId && this.orderName.equals(order.orderName);
    }
    return false;
}

object类中toString()的使用:

1.当我们输出一个对象的引用时,实际上就是调用当前对象的toString()

2.object类中toString()的定义:
public String toString() {
return getClass().getName() +"@" + Integer.toHexString(hashCode());}

3.像String、 Date、File、包装类等都重写了0bject类中的toString()方法
使得在调用对象的toString()时,返回"实体内容"信息.
4.自定义类也可以重写toString()方法,当调用此方法时,返回对象的"实体内容"

基本数据类型、包装类与String三者之间如何转换

基本数据类型<----->包装类:自动装箱、自动拆箱
Integer i = 10;

基本数据类型、包装类—>String::valueOf(Xxx xx)

String—>基本数据类型、包装类:parseXxx(String s)

static关键字的使用

1.static:静态的

2.static可以用来修饰:

属性、方法、代码块、内部类

3.使用static修饰属性:静态变量(类变量)

 3.1 属性,按是否使用static修饰,又分为:静态属性vs非静态属性(实例变量)
 实例变量:我们创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性。当修改其中一个对象中的
         非静态属性时,不会导致其他对象中同样的属性值的修改。
 静态变量:我们创建了类的多个对象,多个对象共享同一个静态变量。当通过某一个对象修改静态变量时,会导致
         其他对象调用此静态变量时,是修改过了的。
 3.2 static修饰属性的其他说明:
     静态变量随着类的加载而加载。可以通过"类.静态变量"的方式进行调用
     静态变量的加载要早于对象的创建。
     由于类只会加载一次,则静态变量在内存中也只会存在一份
             类变量     实例变量
      类      yes         no
     对象     yes        yes
 3.3 静态属性举例:System.out; Math.PI;

4.使用static修饰方法:静态方法

 随着类的加载而加载,可以通过"类.静态方法"的方式进行调用
                 静态方法     非静态方法
           类      yes           no
          对象     yes           yes
 静态方法中,只能调用静态的方法或属性
 非静态方法中,既可以调用非静态的方法或属性,也可以调用静态的方法或属性

5. static注意点:

 5.1 在静态的方法内,不能使用this关键字、super关键字
 5.2 关于静态属性和静态方法的使用,大家都从生命周期的角度去理解。
  • 开发中,如何确定一个属性是否要声明为static的?

    属性是可以被多个对象所共享的,不会随着对象的不同而不同的。

  • 开发中,如何确定一个方法是否要声明为static的?

    操作静态属性的方法,通常设置为static的
    工具类中的方法,习惯上声明为static的。比如:Math、Arrays、collections;

单例设计模式:

  • 1.所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例。

  • 2.如何实现?
    饿汉式 VS 懒汉式

  • 3.区分饿汉式和懒汉式

    • 饿汉式:
      坏处:对象加载时间过长。
      好处:饿汉式是线程安全的
    class Bank{
         
    //1.私化类的构造器
        private Bank(){
         
        }
    //2.内部创建类的对象
    //4.要求此对象也必须声明为静态的
    	private static Bank instance = new Bank();
    //3.提供公共的静态的方法,返回类的对象
    	public static Bank getInstance(){
         
    		return instance;
    	}
    }
    
    • 懒汉式:
      好处:延迟对象的创建。
      目前写法的坏处:线程不安全------->到多线程内容时,再修改
class Order{
   
//1.私化类的构造器private Order(){}
//2.声明当前类对象,没初始化//4.此对象也必须声明为static的
private static Order instance = null;
//3.声明public. static的返回当前类对象的方法
    public static Order getInstance(){
   
		if(instance -= null){
   
			instance = new Order();
		}
	return instance;
	}
}

类的成员之四:代码块(或初始化块)

1.代码块的作用:用来初始化类、对象

2. 代码块如果有修饰的话,只能使用static.

3.分类:静态代码块vs非静态代码块

4. 静态代码块

 >内部可以有输出语句
 >随着类的加载而执行,且只执行一次
 >作用:初始化类的信息
 >如果一个类中定义了多个静态代码块,则按照声明的先后顺序执行
 >静态代码块的执行,要优先于非静态代码块的执行
 >静态代码块内只能调用静态的属性、静态的方法,不能调用非静态的结构

5. 非静态代码块

 >内部可以有输出语句
 >随着对象的创建而执行,且
 >每创建一个对象,就执行一次非静态代码块
 >作用:可以在创建对象时,对对象的属性等进行初始化
 >如果一个类中定义了多个非静态代码块,则按照声明的先后顺序执行
 >非静态代码块内可以调用静态的属性、静态的方法,或非静态的属性、非静态的方法

对属性可以赋值的位置:

 1.默认初始化
 2.显式初始化
 3.构造器中初始化
 4.有了对象以后,可以通过"对象.属性"或“对象.方法”的方式,进行赋值
 5.在代码块中赋值

关键字:final 最终的

1. final可以用来修饰的结构:类、方法、变量
2. final用来修饰一个类:此类不能被其他类所继承。

​ 比如:String类、System类、StringBuffer类

3.final用来修饰方法:表明此方法不可以被重写

​ 比如:Object类中getclass();

4. final用来修饰变量:此时的"变量"就称为是一个常量
  • 4.1 final修饰属性:可以考虑赋值的位置有:显式初始化、代码块中初始化,构造器中初始化

  • 4.2 final修饰局部变量:尤其是使用final修饰形参时,表明此形参是一个常量。当我们调用此方法时,
    给常量形参赋一个实参。一旦赋值以后,就只能在方法体内使用此形参,但不能进行重新赋值。

    static final 用来修饰属性:全局常量

关键字:abstract

  1. abstract 抽象的

  2. abstract 可以用来修饰的结构:类、方法

  3. abstract修饰类:抽象类

此类不能实例化
抽象类中一定有构造器,便于子类实例化时调用(涉及,子类对象实例化的全过程)
开发中,都会提供抽象类的子类,让子类对象实例化,完成相关的操作

  1. abstract修饰方法:抽象方法

抽象方法只有方法的声明,没有方法体
包含抽象方法的类,一定是抽象类,反之,抽象类中可以没有抽象方法
若子类重写了父类中的所有的抽象方法后,此子类方可实例化
若子类没有重写父类中的所有的抽象方法,则此子类也是一个抽象类,需要使用abstract修饰

static、final、abstract都能用来修饰什么

总结:

异常

一、常见异常

java.lang.Throwable
     |-----java.lang.Error:一般不编写针对性的代码进行处理。
     |-----java.lang.Exception:可以进行异常的处理.
         |------编译时异常(checked)
             |------IOException
                 |------FileNotFoundException
             |------ClassNotFoundException
         |------运行时异常(unchecked,RuntimeException)
             |-----NullPointerException
             |-----ArrayIndexOutOfBoundsException
             |-----ClassCastException
             |-----NumberFormatException
             |-----InputMismatchException
             |-----ArithmeticException

二、异常处理机制

一、异常的处理:抓抛模型

过程一:"抛":程序在正常执行的过程中,一旦出现异常,就会在异常代码处生成一个对应异常类的对象。
      并将此对象抛出。
      一旦抛出对象以后,其后的代码就不再执行。
      关于异常对象的产生:① 系统自动生成的异常对象
                      ② 手动的生成一个异常对象,并抛出(throw)
过程二:“抓":可以理解为异常的处理方式: ① try-catch-finally ② throws

二、try-catch-finally的使用

try{
   
     //可能出现异常的代码
}catch(异常类型1变量名1){
   
     //处理异常的方式1
}catch(异常类型2变量名2){
   
     //处理异常的方式2
}catch(异常类型3 变量名3){
   
     //处理异常的方式3
}
.....
finally{
   
    //一定会执行的代码
}
说明:
    1. finally是可选的。
    1. 使用try将可能出现异常代码包装起来,在执行过程中,一旦出现异常,就会生成一个对应异常类的对象,
      根据此对象的类型,去catch中进行匹配
    1. 一旦try中的异常对象匹配到某一个catch时,就进入catch中进行异常的处理。一旦处理完成,
      就跳出当前的try-catch结构(在没有写finally的情况下),继续执行其后的代码
    1. catch中的异常类型,如果没有子父类关系,则谁声明在上,谁声明在下无所谓。
      catch中的异常类型如果满足子父类关系,则要求子类一定声明在父类的上面。否则,报错。
    1. 常用的异常对象处理的方式:1 String getMessage() , 2 printStackTraceT()
    1. 在try结构中声明的变量,再出了try结构以后,就不能再被调用
    1. try-catch-finally结构可以嵌套
      • 体会1: 使用try-catch-finally处理编译时异常,是得程序在编译时就不再报错,但是运行时仍可能报错。
        相当于我们使用try-catch-finally将一个编译时可能出现的异常,延迟到运行时出现。
      • 体会2: 开发中,由于运行时异常比较常见,所以我们通常就不针对运行时异常编写try-catch-finally了。
        针对于编译时异常,我们说一定要考虑异常的处理。
    1. finally是可选的
    1. finally中声明的是一定会被执行的代码。即使catch中又出现异常了,或try中有return语句, 或catch中有return语句等情况。
    1. 像数据库连接、输入输出流、网络编程Socket等资源,JVM是不能自动的回收的,我们需要 自己手动的进行资源的释放。此时的资源释放,就需要声明在finally中。

三、异常处理的方式二:throws +异常类型

    1. "throws +异常类型"写在方法的声明处。指明此方法执行时,可能会抛出的异常类型。
      一旦当方法体执行时,出现异常,仍会在异常代码处生成一个异常类的对象,此对象满足throws后异常类型时,
      就会被抛出。异常代码后续的代码,就不再执行!
    1. 体会:try-catch-finally:真正的将异常给处理掉了。
      throws的方式只是将异常抛给了方法的调用者,并没有将异常真正的处理掉
    1. 开发中如何选择使用try-catch-finally 还是使用throws ?
    • 3.1 如果父类中被重写的方法没有throws方式处理异常,则子类重写的方法也不能使用throws,意味着如果
      子类重写的方法中有异常,必须使用try-catch-finally方式处理。
    • 3.2 执行的方法a中,先后又调用了另外的几个方法,这几个方法是递进关系执行的。我们建议这几个方法使用throws
      的方式进行处理。而执行的方法a可以考虑使用try-catch-finally方式进行处理。

多线程

一、测试Thread中的常用方法:

1. start():启动当前线程;调用当前线程的run()
2. run():通常需要重写Thread类中的此方法,将创建的线程要执行的操作声明在此方法中
3. currentThread():静态方法,返回执行当前代码的线程
4. getName()∶获取当前线程的名字
5. setName():设置当前线程的名字
6. yield():释放当前cpu的执行权,让步操作
7. join():在线程a中调用线程b的join(),此时线程a就进入阻塞状态,直到线程b完全执行完以后,线程a才结束阻塞状态。
8. stop():己过时。当执行此方法时,强制结束当前线程。
9.sleep(long millitime):让当前线程"睡眠”指定的millitime毫秒。在指定的millitime毫秒时间内,当前线程是阻塞状态。
10. isAlive():判断当前线程是否存活

线程的优先级:

1.MAX_PRIORITY: 10
  MIN_PRIORITY: 1
  NORM_PRIORITY:5---默认的的优先级
2.如何获取和设置当前线程的优先级:
     getPriority():获取线程的优先级
     setPriority(int p):设置线程的优先级

说明:高优先级的线程要抢占低优先级线程cpu的执行权。但是只是从概率上讲,高优先级的线程高概率的情况下被执行。并不意味着只有当高优先级 的线程执行完以后,低优先级的线程才执行。

线程通信: wait() / notify() / notifyAll ( ):此三个方法定义在0bject类中的。

二、多线程的创建,

  • 方式一:继承于Thread类
1.创建一个继承于Thread类的子类
2.重写Thread类的run()
3.创建Thread类的子类的对象
4.通过此对象调用start()

例子:遍历100以内的所有的偶数

  • 方式二:实现Runnable接口
1.创建一个实现了Runnable接口的类
2.实现类去实现Runnable中的抽象方法: run()
3.创建实现类的对象
4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
5.通过Thread类的对象调用start()
  • 创建线程的方法三:实现callable接口。----JDK5.0新增
如何理解实现Callable接口的方式创建多线程比实现Runnable接口创建多线程方式强大?
1. call()可以有返回值的。
2. call()可以抛出异常,被外面的操作捕获,获取异常的信息
3. Callable是支持泛型的
  • 创建线程的方式四:使用线程池
好处:
1.提高响应速度(减少了创建新线程的时间)
2.降低资源消耗(重复利用线程池中线程,不需要每次都创建)
3.便于线程管理
     corePoolSize:核心池的大小
     maximumPoolSize:最大线程数
     keepALiveTime:线程没有任务时最多保持多长时间后会终止
  面试题:创建多线程有几种方式?四种!
  • 比较创建线程的两种方式。
    • 开发中:优先选择:实现Runnable接口的方式
    • 原因:
      1.实现的方式没有类的单继承性的局限性
      2.实现的方式更适合来处理多个线程有共享数据的情况。

联系: public class Thread implements Runnable
相同点:两种方式都需要重写run(),将线程要执行的逻辑声明在run()中。目前两种方式,要想启动线程,都是调用的Thread类中的start().

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NauxRDEB-1646661895049)(D:\Program Files\Testedit\Note\Pictures\image-20211205170202918.png)]

在Java中,我们通过同步机制,来解决线程的安全问题。
  • 方式一:同步代码块

    synchronized(同步监视器){
    //需要被同步的代码
    }
    说明: 1.操作共享数据的代码,即为需要被同步的代码 -->不能包含代码多了,也不能包含代码少了
    2.共享数据:多个线程共同操作的变量。比如: ticket就是共享数据。
    3.同步监视器,俗称:锁。任何一个类的对象,都可以充当锁。
    要求:多个线程必须要共用同一把锁。
    补充:在实现Runnable接口创建多线程的方式中,我们可以考虑使用this充当同步监视器。

  • 方式二:同步方法

    同步的方式,解决了线程的安全问题。—好处
    操作同步代码时,只能有一个线程参与,其他线程等待。相当于是一个单线程的过程,效率低。—局限性

  • 方式三:Lock锁— JDK5.0新增
1.面试题: synchronized 与Lock的异同?
     相同:二者都可以解决线程安全问题
     不同: synchronized机制在执行完相应的同步代码以后,自动的释放同步监视器
          Lock需要手动的启动同步(Lock()),同时结束同步也需要手动的实现(unLock())
2.优先使用顺序:
     Lock→同步代码块(已经进入了方法体,分配了相应资源)→同步方法(在方法体之外)
使用同步方法解决实现Runnable接口的线程安全问题

关于同步方法的总结:

  1. 同步方法仍然涉及到同步监视器,只是不需要我们显式的声明。
  2. 非静态的同步方法,同步监视器是: this
    静态的同步方法,同步监视器是:当前类本身
演示线程的死锁问题
  1. 死锁的理解:不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步 资源,就形成了线程的死锁
  2. 说明:
    1)出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于阻塞状态,无法继续
    2)我们使用同步时,要避免出现死锁。
线程通信的例子:
使用两个线程打印1-10日。线程1,线程2交替打印涉及到的三个方法:
wait():一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器。
notify():一旦执行此方法,就会唤醒被wait的一个线程。如果有多个线程被wait,就唤醒优先级高的
notifyALL():一旦执行此方法,就会唤醒所有被wait的线程。
说明:
1.wait( ),notify(),notifyALL()三个方法必须使用在同步代码块或同步方法中。
2.wait(), notify( ), notifyALL()三个方法的调用者必须是同步代码块或同步方法中的同步监视器
     否则,会出现IllegalMonitorStateException异常
3.wait(), notify(),notifyAlL()三个方法是定义在java.Lang.object类中。而不是在Thread类中

面试题: sleep()和wait()的异同?
1.相同点:一旦执行方法,都可以使得当前的线程进入阻塞状态。
2.不同点:
1)两个方法声明的位置不同:Thread类中声明sleep() , object类中声明wait()
2)调用的要求不同: sleep()可以在任何需要的场景下调用。wait()必须使用在同步代码块或同步方法中
3)关于是否释放同步监视器:如果两个方法都使用在同步代码块或同步方法中,sleep()不会释放锁,wait()会释放锁。

JAVA常用类Day17

String

String replace(char oldChar, char newChar):返回一个新的字符串,
      它是通过用newChar替换此字符串中出现的所有oldChar得到的。
String replace(CharSequence target, CharSequence replacement):使用指定的字面值替换序列替换
      此字符串所有匹配字面值目标序列的子字符串。
String replaceAll(String regex,String replacement):使用给定的replacement替换此字符串所有匹
      配给定的正则表达式的子字符串。
String replaceFirst(String regex,String replacement):使用给定的replacement替换此字符串匹配
      给定的正则表达式的第一个子字符串
boolean matches(String regex):告知此字符串是否匹配给定的正则表达式。
String[] split(String regex):根据给定正则表达式的匹配拆分此字符串。
String[] split(String regex,int limit):根据匹配给定的正则表达式来拆分此字符串,最多不超过limit个,
      如果超过了,剩下的全部都放到最后一个元素中。
String 的常用方法有哪些?(至少7个)。
    length()/ charAt()/ equals(</
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值