JavaSE

JavaSE学习笔记

IDEA快捷键

查找类型 ctrl+n

查找资源 双击shift

方法重写 ctrl+O

快速导包 alt+enter

放大编码区 ctrl+shift+F12

错误改正: alt+Enter

关键字

this

this是一个引用、变量,指向了对象本身,this存储在JVM堆内存java对象内部

this可以出现在“实例方法”中,指向当前正在执行这个动作的对象

带有static的方法没有当前对象,因为带有static的方法是通过类名访问的,包括main方法 所以不能直接访问实例变量和实例方法

不能省略的this

用来区分局部变量和实例变量时不能省(变量和原有属性同名)

独特的this方法 构造方法中使用

this(构造参数)在构造函数调用现有的构造函数,且不会生成新的对象 且必须是在该构造方法中第一行

关于this的所有相关函数

public class TestThis {

    int i=10;

    public static void doSome(){
        System.out.println("do some");
    }

    public void doOther(){
        System.out.println("do Other");
    }
//静态方法 没有上下文对象 没有this
    public static void method1() {
        TestThis.doSome();
        doSome();

        TestThis t=new TestThis();
        t.doOther();
        System.out.println(t.i);
    }

    public void method2() {
        
        TestThis.doSome();
        //        ??  不需要对象,自动使用类名调用
        doSome();

        this.doOther();
        doOther();

        System.out.println(this.i);
        System.out.println(i);
    }
//静态方法 没有上下文对象 没有this
    public static void main(String[] args) {

        TestThis.method1();
        method1();

        TestThis t=new TestThis();
        t.method2();

    }
}

super

this与super作为构造方法不能共存

super()只能出现在构造方法第一行,通过当前构造方法掉用父类的构造方法 目的:创建子类对象时,先初始化父类特征

父类和子类中有同名但不同内容的属性内容时不能省略

使用情况

子类通过调用父类构造方法来对父类私有属性进行修改

static

类中统一的属性可以通过static固定,不需要在每个对象中重复生成。

此类静态对象在类加载时就初始化,存储在方法区中

static修饰的元素都可以通过"类名."进行访问

工具类方法一般写作静态 方便调用

Final

final所修饰的不同效果

static final 修饰的变量称为常量, 与静态变量一样,存储在方法区中,在类加载时初始化,但常量不能改变,要求大写 单词间用下划线隔开 且常量一般公开

类:无法被继承

方法:无法被覆盖

变量:无法重新赋值

实例变量:必须在声明时手动赋值且无法修改

引用:一旦赋值不能赋新值 但是所指向对象的属性可以修改 无法被垃圾回收器回收 当整个方法结束才会被回收

package

包机制 包名要全小写

第一章(java的加载与执行)

java的加载与执行

程序阶段:编译+运行

运行阶段:java.exe启动java虚拟机(JVM),JVM启动类加载器ClassLoader,ClassLoader找到对应的class文件并装载到JVM中

public class和class

public class的名字要和源文件名相同,只能有一个

class可以有多个 每个class都能有一个main方法

加载器

JDK带有三个类加载器:启动类加载器 扩展类加载器 应用类加载器

第二章(基础知识)

数据类型

基本数据类型(字节):byte 1,short 2,int 4,long 8 float 4,double 8 boolean 1 char 2

引用数据类型:类,接口,数组。。。。

[-128,127]放在常量池中

基础数据类型包装类

包装类都属于引用类型,函数参数需要是父类为Object的对象,所以基本数据类型需要包装类

char Character

int Integer

自动拆箱和自动装箱 包装类和基本数据类型之间会自动转换

但是使用==进行判断的时候不会自动拆箱,比较的是两个对象的地址

方法

带有static修饰的方法可以不创建对象直接调用 类名.方法()

否则需要创建对象 引用对象.方法()

修饰符列表(public/static等) 返回值类型 方法名 (形式参数列表){

​ 方法体;

}

重载(Overload)

调用的参数不同,对应调用的方法不同

使用重载的情况:

功能相似的时候可以采用重载

满足什么条件构成重载

同一个类当中 / 方法名相同 / 参数不同(数量不同/顺序不同/类型不同)

String

底层是private final byte[ ] 所以每个用 ""括起来的内容都是字符串,放在方法区的常量池中。常量池中的字符串自声明起就不会改变,如果重新赋值会重新声明新的字符串到常量池中,是一个新的字符串对象。

采用new String()方法声明字符串会在堆内存中开辟一个指向常量池中的内存地址。

String s=new String(“xy”);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iSl4DkAC-1649642398204)(C:/Users/CLY/AppData/Roaming/Typora/typora-user-images/image-20220321101259847.png)]

String的方法

compareTo

endsWith

equalsIgnoreCase 判断是否相同且忽略大小写

getBytes 返回byte数组 字符对应的ASCII码

isEmpty 是否为空

substring

toCharArray 转换为char数组

toUpperCase toLowerCase

trim 去除字符串前后空白

第三章(面向对象)

三大特性:封装 继承 多态

new的类在堆内存中

java中 只能通过引用去访问堆内存中变量内部的实例变量

内存分析

1、JVM(Java虚拟机)主要包括三块内存空间,分别是:栈内存、堆内存、方法区内存。

2、堆内存和方法区内存各有1个。一个线程一个栈内存。

3、方法调用的时候,该方法所需要的内存空间在栈内存中分配,称为压栈。方法执行结束之后,该方法所属的内存空间释放,称为弹栈。

4、栈中主要存储的是方法体当中的局部变量。

5、方法的代码片段以及整个类的代码片段都被存储到方法区内存当中,在类加戮的时候这些代码片段会载入。

6、在程序执行过程中使用new运算符创建的java对象,存储在堆内存当中。对象内部有实例变量,所以实例变量存储在堆内存当中。

7、变量分类:
局部变量【方法体中声明】-成员变量【方法体外声明】

​ 实例变量【前边修饰符没有static]*静态变量【前边修饰符中有static]

8.静态变量存储在方法区内存当中。

9、三块内存当中变化最频繁的是栈内存,最先有数据的是方法区内存,垃圾回收器主要针对的是堆内存。

10、垃圾回收器【自动垃圾回收机制、GC机制】什么时候会考虑将某个java对象的内存回收呢?
*当堆内存当中的java对象成为垃圾数据的时候,会被垃圾回收器回收。
*什么时候堆内存中的 java对象会变成垃圾呢?
没有更多的引用指向它的时候。
这个对象无法被访问,因为访问对象只能通过引用的方式访问。

封装
好处

1.将复杂的事物封装,提供简单的外部接口

2.封装之后才是真正的“对象”,真正的“独立体”

3.该段程序可独立使用,适应性强,其他场合可以使用

4.提高了安全性

步骤

1.属性私有化,只能在本类中使用

2、对外提供访问的接口

构造方法
作用

通过构造方法的调用可以创建对象,创建对象的同时初始化实例变量的内存空间

实例对象本身存放在java堆内存的内部 实例对象的引用地址:栈内存 实例对象的元数据class信息:方法区或元空间

如何调用

普通方法 有static时的调用格式: 类名.方法名(实参列表) 无static时: 引用.方法名(实参列表)

构造方法: new 构造方法名(实参列表)

返回值

返回构造生成对象在堆内存中的地址

代码块
public class StaticTest {
    public static StaticTest t1=new StaticTest();
    public static StaticTest t2=new StaticTest();
    {
        System.out.println("构造块");
    }
    static{
        System.out.println("静态块");
    }

    public static void main(String[] args) {
        StaticTest t=new StaticTest();
    }
}

输出结果

构造块
构造块
静态块
构造块

静态代码块

static{

​ java语句;

}

静态代码块在类加载时执行且只此一次,一个类中可出现多个代码块,遵循自上而下的顺序执行

用途

在类加载时需要执行的内容 如:日志记录、数据准备工作(初始化连接池、解析XML文件)

实例代码块

main方法执行时不会执行,当实例代码块所在类的构造方法执行之前会被执行

继承

A is a B 表示继承 A是子类 B是被继承的父类

A has a B 表示类的属性 B是A的属性

子类先执行父类的构造方法再执行本身的构造方法

基本作用:代码复用

最重要的作用:方法的覆盖和多态机制

关键字 extends

子类从父类中继承的内容

私有的不继承

构造方法不继承

其余数据都继承

方法覆盖(方法重写)override

覆盖只针对方法不谈属性

使用情况: 当父类的方法不够子类的需求,子类需要对从父类继承的方法进行重写

书写要求: 子类在对方法重写时方法名要与父类相同,修饰的访问权限可以更高不能更低,抛出异常可以少不能多

静态方法不存在覆盖

多态

两转转换都需要前后两个类存在继承关系

向上转型(upcasting)

子类型转为父类型 自动类型转换 底层还是原来存在的子类型

编译通过 运行肯定不出问题

向下转型(downcasting)

父类型转为子类型 强制类型转换(需要加强制类型转换符)

强转时出现错误会出现 java.lang.ClassCastException 异常

instanceof运算符

为了避免 java.lang.ClassCastException 异常的出现

该运算符结果为true/false

a instanceof A true:a指向的对象确实是A类(指a的底层对象)

访问权限控制
修饰属性、方法

public 任意地方都能访问

protected 同包 子类中可以访问

缺省 default 同包下可以访问

private 只能在本类中进行访问

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gyrlOd0c-1649642398206)(C:/Users/CLY/AppData/Roaming/Typora/typora-user-images/image-20220319131708416.png)]

修饰类

只有public和默认

第四章(抽象类与接口)

抽象类abstract

类和类之间具有共同特征,将这些共同特征提取出来形成抽象类

抽象类本身不存在,所以无法创建对象 属于引用数据类型

抽象类虽然不能实例化,但是有构造方法,供子类使用

正常类继承抽象类必须实现其中的抽象方法

抽象类中不一定有抽象方法

抽象方法

没有实现的没有方法体的方法 public abstract void dosome();

接口interface

架构师制定接口,各个类只需要关心接口 关联的类解耦合 可以分别编写

基础语法

接口是特殊的抽象类 —完全抽象

接口支持多继承,可继承多个接口

接口中只包含两部分内容:抽象方法、常量

接口中抽象方法public abstract可以省略 常量的public static final也可以省略

接口实现implements

与继承一样,实现方法访问权限只能更高。

如果继承和实现同时出现 extends在前implements在后

抽象类和接口的区别

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x46scxTM-1649642398206)(C:/Users/CLY/AppData/Roaming/Typora/typora-user-images/image-20220318190719316.png)]

第五章(各个方法)

equals函数

基本数据类型判断是否相等用==符号

引用数据类型判断用equals String为引用数据类型

public class TestEquals {
    public static void main(String[] args) {
        String a="avc";
        String b="avc";
		//true		String如果相同会生成在常量池中 不会生成新对象 所以比较是相等的
        //但如果String是new出来的不行
        System.out.println(a==b);
        System.out.println(a.equals(b));

        MyTime mytime1=new MyTime(1);
        MyTime mytime2=new MyTime(1);
		//false  此处比较的是内存地址
        //想要通过equals判断值相等要在类中重写 
        System.out.println(mytime1==mytime2);
        System.out.println(mytime1.equals(mytime2));
    }
}
class MyTime{
    int year;

    public MyTime(int year) {
        this.year = year;
    }
}
finalize方法

已被弃用

java对象被垃圾回收时会自动调用此方法

不需要调用 只需要重写

匿名内部类

不建议使用 只能使用一次

在方法中声明的类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XbW6HfH5-1649642398206)(C:/Users/CLY/AppData/Roaming/Typora/typora-user-images/image-20220319215643311.png)]

第六章(数组+StringBuffer)

一维数组

数组是引用数据类型,放在堆内存中

如果存储的是“对象”,那么在数组中存放的是对象的引用(内存地址),数组中引用数据类型占4个字节

数组存储的内存地址是连续的

数组以第一个元素的地址作为整个数组的内存地址

优缺点

查询 存储 检索效率高

增删元素效率低,数组不能存储过大的数据 因为存储空间需要连续

数组初始化
//静态初始化
int[] array={100,200,300};
//动态初始化
int[] array=new int[5];
数组扩容

System.arraycopy(拷贝源,拷贝起始,拷贝目标数组,拷贝目标起始位置,拷贝长度)

数组工具类

java.util.Arrays

sort()方法

binarysearch()二分法查找

StringBuffer

java中字符串是不可变的 每一次拼接会产生新的字符串 所以需要StringBuffer

stringBuffer底层没有用final修饰 初始化为16个容量

字符串拼接 append()

线程安全

性能优化

创建StringBuffer时尽可能给定一个初始化容量

可以减少底层数组的扩容次数

StringBuffer sb=new StringBuffer(capacity); 指定初始化容量

StringBuilder

线程不安全 没有synchronized关键字修饰

Date

new Date(long) 自1970年起的毫秒数

date转String date函数显示时间格式化

Date date=new Date();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(date));

String转Date

SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time="2008-08-08 08:08:08";
try {
    Date datetime=sdf.parse(time);
    System.out.println(datetime);
} catch (ParseException e) {
    e.printStackTrace();
}
Decimal
DecimalFormat format=new DecimalFormat("###,###.##");
String s=format.format(1234.145134);
System.out.println(s);//1,234.15

DecimalFormat format2=new DecimalFormat("###,###.0000");
String s2=format2.format(1234.14);
System.out.println(s2); //1,234.1400
BigDecimal

java.math.BigDecimal

调方法进行计算

加法add

随机数
//int范围内的随机数
Random random=new Random();
int num1=random.nextInt();
//100以内的随机数 不包括100
int num2=random.nextInt(100);

第七章(异常)

​ Object

​ Trowable

​ Error Exception

virtualMachineError IOError || exception直接子类(编译时异常) RuntimeException(运行时异常)

StackOverflowError

编译时异常表示必须在编译时就提前处理,否则不能运行

throws和trycatch

希望调用者自己处理的用throws 其余的采用trycatch

异常报错提示

e.pritStackTrace();

finally

try语句即使出现了问题 finally中的语句也会执行

资源流的关闭 资源的回收

自定义异常

定义一个无参构造和一个带String的构造方法

这个String可以通过 getMessage方法进行获取

第八章(集合)

ArrayList 非线程安全

Vector 线程安全 效率较低 较少使用

HashSet 底层其实是创建了HashMap

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GE04afvp-1649642398207)(C:/Users/CLY/AppData/Roaming/Typora/typora-user-images/image-20220326195623422.png)]

总结(所有的实现类):

ArrayList:底层是数组。LinkedList:底层是双向链表。

LinkedList:底层是双向链表

Vector:底层是数组,线程安全的,效率较低,使用较少。

HashSet:底层是HashMap,放到HashSet,集合中的元素等同于放到HashMap集合key部分了。

TreeSet:底层是TreeMap,放到TreeSet,集合中的元素等同于放到TreeMap,集合key部分了。

HashMap:底层是哈希表。

Hashtable:底层也是哈希表,只不过线程安全的,效率较低,使用较少。

properties:是线程安全的,并且 key和value只能存储字符串String。

TreeMap:底层是二叉树。TreeMap集合的 key可以自动按照大小顺序排序。

Collection

iterator集合只要发生改变 迭代器必须重新获取

在迭代过程中可以通过迭代器来删除元素 但不能通过collection来删除

Collection c=new ArrayList();

c.add(new String("abc"));
c.add("def");
c.add(3.14);
c.add(new Object());

Iterator it=c.iterator();
//hasNext()
//next()
//size()
//contains  比较的是内容 底层调用的equals
String s=new String("abc");
System.out.println(c.contains(s));

while(it.hasNext()){
    System.out.println(it.next());
}
List

常用方法

void add(int index , Object element)

Object get(int index)

int indexOf(Object o)

int lastIndexOf(Object o)

Object remove(int index)

Object set(int index , Object element)

ArrayList

扩容是原容量的1.5倍 底层是数组

尽量减少扩容次数 效率低

Vector

扩容是两倍

所有方法都是线程安全的

HashSet

初始化容量16 扩容为原容量2倍

容量建议为2的倍数 有利于提高效率

TreeSet

底层为TreeMap 为二叉树

无序不可重复(存入取出的顺序无序) 可以按照元素大小顺序自动排序

TreeSet无法对自定义的类型进行排序

需要对自定义的类中实现Comparable接口

Comparable
@Override
public int compareTo(Customer o) {
    return this.age-o.age;
}
Comparator

当比较规则不会发生改变时用Comparable 如果有多个规则之间频繁切换用Comparator

泛型

new ArrayList() 表示该List中只能存储该类型的数据

元素类型统一

JDK8之后可以自动推断泛型类型

List myList=new ArrayList<>();

Collections工具类

1、Collections.synchronizedList( )是的ArrayList线程安全

2、Collections.sort( )只能是List集合 但是Set集合可以封装成List集合

​ List mylist=new ArrayLast<>(set);

Map

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OwFL8I6c-1649642398207)(C:/Users/CLY/AppData/Roaming/Typora/typora-user-images/image-20220326200757779.png)]

Set<Map.Entry<Integer,String>> entry=map.entrySet();
for (Map.Entry<Integer,String> node:entry
     ) {
    System.out.println(node.getKey()+node.getValue());
}

这个方式更快,避免重复获取key和value,直接将map中的entrySet放入Set中

HashMap

需要重写hashCode方法 避免将相同的元素因比较的是地址不同而重复存储

public int hashCode(){

​ return Objcects.hash(name);

}

Hashmap中的key可以为空,但只能有一个 因为会重复

HashTable

hashTable不允许key和value为空

Properties

是一个Map的集合,继承HashTable key和value都是String

被称为属性类对象,是线程安全的

第九章(IO流)

输入流 输出流

字节流 字符流

java.io

以Stream结尾的都是字节流

Reader/Writer结尾的是字符流

Closeable可关闭 流使用完记得关闭

输出流 flush( ) 管道清空

默认当前路径

工程Project的跟就是IDEA的默认当前路径

文件专属
java.io.FileInputStream

read() 读一个字节

read(byte[ ]) 返回读取到的字节数量

文件中的内容为 abcdef

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tlgKIJtF-1649642398207)(C:/Users/CLY/AppData/Roaming/Typora/typora-user-images/image-20220401144739232.png)]

available()还剩多少个字符没读 不适合过大的文件使用

skip()跳过几个字节不读取

java.io.FileOutputStream

用byte[ ]进行读取

文件字节输出流 负责写文件

输出流写完要刷新

true表示在目标文件后追加,false或不写表示清空源文件

fos=new FileOutputStream("src\\JavaLearning\\IOLearning\\tempfile.text",true);
java.io.FileReader

用char[ ]进行读取

java.io.FileWriter

无法读取word 图片 视频等流媒体文件

能用记事本编辑的是文本文件

转换流:将字节流转换为字符流
java.io.InputStreamReader

Input是字节流 Reader是字符流

//        //字节流
//        FileInputStream in=new FileInputStream("src\\JavaLearning\\IOLearning\\FileWriterTest01.java");
//        //字节流转为字符流
//        InputStreamReader reader=new InputStreamReader(in);
//        //BufferedReader只能传字符流
//        BufferedReader br=new BufferedReader(reader);
        
//写成一行
        BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream("src\\JavaLearning\\IOLearning\\FileWriterTest01.java")));
java.io.OutputStreamWriter
BufferedWriter out=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("src\\JavaLearning\\IOLearning\\FileWriterTest01.java")));
缓冲区专属:
java.io.BufferedReader

只能传字符流 不能穿字节流

FileReader reader=new FileReader("src\\JavaLearning\\IOLearning\\FileWriterTest01.java");
//当一个流的构造方法中需要一个流的时候,被传入的流叫做节点流
//外部负责包装的叫包装流  或处理流
//FileReader 节点流    BufferedReader  保留装/处理流
BufferedReader br=new BufferedReader(reader);
//readline方法读的时候不带换行符
String fr=br.readLine();
System.out.println(fr);
String sec=br.readLine();
System.out.println(sec);
//只需要将外部的流关闭就可以 会调用in.close()方法
br.close();

java.io.BufferedWriter
java.io.BufferedInputStream
java.io.BufferedOutputStream

数据流专属:

java.io.DataInputStream

java.io.DataOutputStream

将数据连同数据类型一并写入文件

//专属的字节输出流  完成写入的文件只能通过DataInputStream并且以相同的输入方式才能读出
DataOutputStream dos=new DataOutputStream(new FileOutputStream("data"));
//writeBoolean
//writeByte

DataInputStream dis=new DataInputStream(new FileInputStream("data"));

标准输出流:

java.io.ObjectInputStream
java.io.ObjectOutputStream

对象专属流:

java.io.PrintWriter
java.io.PrintStream

File类

文件和路径的抽象表示形式

file.mkdir()以目录的形式新建文件

file.mkdirs()以多重目录的形式新建文件

file.getname()获取文件名

通过文件目录的File文件 可以通过listFiles()方法来获取File[ ]集合 再通过foreach进行遍历

序列化
  • 序列化:把Java对象转换为字节序列的过程。
  • 反序列化:把字节序列恢复为Java对象的过程。

参与序列化与反序列化的类必须实现Serializable接口 java虚拟机会生成一个序列化版本号

该接口源码没有内容只是一个标志接口

通过list集合存储反序列化的文件

加入transient表示该字段不参与序列化

private static final long SerialVersionUID

Properties

经常改变的数据可以通过以下方式获取 存储在文件中

类似于以上机制的文件叫配置文件

FileReader reader=new FileReader(" ")

Properties pro=new Properties();
//文件内容为key=value形式进行读取
pro.load(reader);
String username=pro.getProperties("username");

第十章(多线程)

线程基础
进程和线程

进程是一个应用程序

线程是一个进程中的执行场景或执行单元

一个进程可以启动多个线程

线程堆内存和方法区共享 但是栈内存独立

线程的start()方法

start方法的作用是在JVM中开辟一个新的栈空间,瞬间就能完成,启动成功的方法会自动调用run方法,并且该方法在分支栈的底部。

没有用start方法而只是单纯的run线程 不会新建分支线程,只会在主线程中运行

实现线程的两种方法

1、extends Thread 并重写run方法

MyThread myThread=new MyThread();
myThread.start();

2、implements Runnable 并重写run方法

第二种方式更常用 不耽误对其他类的继承

Thread t=new Thread(new MyRunnable());
t.start();
线程的生命周期

新建——》调用start方法——》就绪状态(表示当前线程具有强度CPU时间片的权利)——》运行状态(run方法的开始执行标志着这个线程进入运行状态)(如果CPU时间片用尽会回到就绪状态并继续强度CPU时间片,抢夺到了继续之前运行的进度继续执行)——》死亡状态(run方法执行结束标志着线程进入死亡状态)

线程对象相关方法

currentThread 获取当前线程

sleep方法 让当前线程进行休眠 和调用的对象无关

run方法中的异常只能try catch 子类不能比父类抛出更多的异常

interrupt 唤醒睡眠的线程 依靠的是java的异常处理机制 唤醒之后会报异常

终止线程的运行 通过静态外部变量来控制线程的执行判断条件

线程调度

抢占式、均分式

void setPriority(int)默认为5 最高优先级10 最低1

yield 暂停当前线程 并执行其他方法 让当前线程回到就绪状态 不是阻塞

合并线程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cDMmm9pt-1649642398208)(C:/Users/CLY/AppData/Roaming/Typora/typora-user-images/image-20220405155653126.png)]

线程安全
同步和异步

异步:多线程并发

同步:两个线程排队执行 有等待关系

synchronized(此处填写的是所需要锁定的共享对象){

}

在实例方法上也可以加synchronized 锁在方法上时锁的是this 整个方法体都被同步 会扩大范围 效率低

死锁
public class DeadLock {
    public static void main(String[] args) {
        Object o1=new Object();
        Object o2=new Object();
        Thread t1=new MyThread1(o1,o2);
        Thread t2=new MyThread2(o1,o2);
        t1.start();
        t2.start();
    }

}

class MyThread1 extends Thread{
    Object o1;
    Object o2;

    public MyThread1(Object o1, Object o2) {
        this.o1 = o1;
        this.o2 = o2;
    }
    public void run(){
        synchronized (o1){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (o2){
                System.out.println(1);
            }
        }
    }
}
class MyThread2 extends Thread{
    Object o1;
    Object o2;

    public MyThread2(Object o1, Object o2) {
        this.o1 = o1;
        this.o2 = o2;
    }
    public void run(){
        synchronized (o2){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (o1){
                System.out.println(2);
            }
        }
    }
}
守护线程

setDaemon(true)将线程设置为守护线程,主线程结束之后自动结束(不管是否有内容)

定时器
public class TimerTest {
    public static void main(String[] args) throws Exception {
        Timer timer=new Timer();

        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        Date firstTime=sdf.parse("2022-04-06 16:30:10");

        timer.schedule(new LogTimerTask(),firstTime,1000*10);
    }
}

class LogTimerTask extends TimerTask{

    @Override
    public void run() {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String strtime=sdf.format(new Date());
        System.out.println(strtime);
    }
}
实现线程的第三种方式

实现Callable接口

FutureTask

public static void main(String[] args) throws Exception{
    FutureTask future=new FutureTask(new Callable() {
        @Override
        public Object call() throws Exception {
            System.out.println("callable method begin");
            Thread.sleep(5000);
            System.out.println("call Method end");
            int a=100;
            int b=200;
            return a+b;
        }
    });
    Thread t=new Thread(future);
    t.start();
    //可能会导致当前线程受阻 因为需要等待线程结束得到执行结果
    Object obj= future.get();

    System.out.println("helloWorld");
}
notify和wait

wait能作用于任意Object对象 让该线程进入无线等待状态

notify方法唤醒该对象上等待的线程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wFU4vvT6-1649642398208)(C:/Users/CLY/AppData/Roaming/Typora/typora-user-images/image-20220406195200956.png)]

生产者和消费者

第十一章 (反射)

反射机制

可以通过放射机制操作字节码文件

Class.forName( )

通过反射机制创建对象,比直接new要灵活

FileReader reader=new FileReader("sampleStore\\classinfo.properties");

Properties pro=new Properties();

pro.load(reader);

reader.close();

String className=pro.getProperty("className");

Class c=Class.forName(className);
Object obj=c.newInstance();

可以通过反射机制调用静态代码块

文件路径

该方法获取的是绝对路径 项目src作为起点

String path=Thread.currentThread().getContextClassLoader().getResource("classinfo2.properties").getPath();
ResourceBundle

可以直接获取properties文件的信息

填文件名称时不带properties后缀

获取Class的三种方式

Class.forName

对象.getClass

int.getClass/String.getClass

获取Field

Field为类的相关信息

通过类调用方法 getFields 获取所有公开的属性

getDeclaredFields( ) 获取所有的

field.getModifiers( )获取类的访问权限

field.getType( ).getSimpleName( )

使用反射机制给对象赋值
//获取num属性
Field field=studentClass.getDeclaredField("num");
//对obj对象的num属性赋值222
field.set(obj,222);
可变长度参数
//args可作为数组	可以放多个参数
public void m(int... args){
   
}
invoke

返回值=方法.invoke(对象,所需的实参)

通过反射机制创建对象
Class c=Class.forName("JavaLearning.Reflect.Vip");
Constructor con= c.getDeclaredConstructor(int.class,String.class,String.class,boolean.class);

Object newObj=con.newInstance(110,"jackson","1999-07-24",true);

第十二章(Annotation)

Override

在java中如果方法上加@Override的注解的话,表示子类重写了父类的方法。

Deprecated

这个方法或类不再建议使用。在新版本中有其他方法或类可以代替这个使用,以后的版本也不会再更新这个方法或类

Target

用于描述注解的使用范围

Retention

被它所注解的注解保留多久

source:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;被编译器忽略

class:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期

runtime:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在

面试题

1、最底层用native关键字调用C++编写的,那些方法没有方法体。

如Object中存在的方法 public native int hascode();

2、new对象必定在堆内存中开辟空间

3、常量池

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-afTUINYb-1649642398209)(C:/Users/CLY/AppData/Roaming/Typora/typora-user-images/image-20220321103728403.png)]

4、Integer [-128,127]范围内的数字生成在常量池中,不会重复生成对象

5、String int Integer相互转换

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2JKA1es1-1649642398209)(C:/Users/CLY/AppData/Roaming/Typora/typora-user-images/image-20220324160232770.png)]

6、final finally finalize的区别

final是一个关键字 表示最终的不变的

finally与try连用 必定执行

finalize()是Object中的一个方法 finalize是一个标识符

7、

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值