Javase
2021-08-27 18:01:15 0 举报
AI智能生成
javase导图
作者其他创作
大纲/内容
java语言基础
注释
单行注释
多行注释
javadoc注释
会生成帮助文档
JDK与jre与jvm三者关系
简单来说就是JDK包含JRE,JRE又包含JVM的关系。
标识符
可自己命名的/且遵守命名规范,不能与关键字重名
关键字
定义数据类型关键字
定义访问权限修饰符关键字
字面值
变量
成员变量
实例变量
静态变量
静态变量以static关键字修饰
局部变量
形参
方法局部变量
在方法中定义
代码块局部变量
在代码块内定义
static修饰的代码块
只执行一次,且在类加载时执行
普通代码块
不常用
数据l类型
基本数据类型
四大类八小种
整数型
byte、short、int、long
整数型通常默认为int型
浮点型
float
这个要在后加f
double
默认是double型
布尔型
boolean
字符型
char
'\n'表示换行 ,‘\t’表示空格
口诀
byte short int long float double boolear char
1 2 4 8 4 8 1 2
引用数据类型 赋值null
例如:类 接口 数组
String也是引用数据类型
引用数据类型存储的是对象的内存地址
数据类型的转换
大到小自动
小到大强转
char和short平级
二进制
字节编码
运算符
算数运算符
+ - = * / % ++ --
赋值运算符
=
比较运算符
== != < > <= >= instanceof(检查是否是类的对象)
逻辑运算符
& | ! && || ^或
位运算符
<<(乘2的除自身的位次) >>(除2的位次)
>>> & | ^ ~
三元运算符
(条件表达式/布尔)?表达式1:表达式2
控制语句
选择结构
if else if switch
循环结构
for 、while、do~while
控制语句顺序
break(跳出)
continue (执行下一个)
方法/函数
作用
提高代码复用性
提供某个功能
基础语法:
修饰符
返回类型
形参
逗号隔开
可变长度参数
nt…args
语法
类型… (三个点)
个数是0~n个
且在形参列表中最后一个
且只能是一个
可以当成一个数组来看待
有lenght属性可遍历输出
也可以传一个数组
方法体
返回值
return
有返回类型 return
没有返回类型/void return 可不写 写代表 方法的终止
调用:
static修饰
类名.方法名
同类 直接方法名
方法定义在内存分配与变化
定义b不分配运行所属内存
调用时才会分配
JAM
内存分三块(多线程时会有多个栈)
栈stack
方法/成员变量
压栈/弹栈
栈帧指向顶元素
特点 先进后出
方法的重载
相同的名字
不同的返回类型
不同的形参
主要用在功能相似的方法地方上
递归
自身调用自身
递归很消耗栈内存
一直调用方法 一直压栈 没有弹栈
容易发生栈内存溢出
所以一定要有停止条件(大概率也会发生栈内存溢出)
面向对象编程
三大特征
封装
特点
提高系统安全性
让对象变成真正的独立体
可重复使用,适应性强
方法步骤:
属性私有化private
对外提高操作入口
get/set方法
可在方法类添加限制条件增强安全性
继承
作用
提高代码复用性
最重要的是有了继承才能有以后的方法的覆盖和多态机制
定义
语法:
修饰符 class 类名 extends 父类
特点
只支持单继承,不支持多继承
私有不支持继承
构造方法不支持继承
其他数据都可以被继承
如果没有显示继承,会默认继承Object类
Object类是根父类,其父类也提供了某些方法 任何一个类都object特性,也可重写父类的方法 例如tostring equals 等等..
多态
前提
存在继承或者实现关系
有覆盖操作
定义
父类 索引=new 子类对象
调用
父类类型引用指向子类对象
转型
强转最好加判断条件
向上转型(子类 转成—》 父类)自动
向下转型(父类 转成—》 子类)强制 (需要加强制转换符)
且俩种需有继承关系
作用
降低耦合度 提高扩展力
特点
优:耦合低 可扩展性强 组件复用性强
缺:前期投入成本高,大量系统分析与设计
面向对象/过程
POP
面向过程编程
面向对象开发软件生命周期OO面向
OOP 面向对象编程
OOD面向对象设计
OOA面向对象设计
JVM内存结构
栈内存
存储实例变量
可存储值
对象的内存地址 指向对象
堆内存
存储对象
对象里有局部变量
局部变量可存储内存地址
垃圾回收机制 System.gc()
方法区
class字节码文件
静态变量
常量池
一个程序的启动至少开启俩个线程
一个是main主线程
一个垃圾回收线程
构造方法
定义
修饰符加方法名 且方法名与类名要一致
自带无参构造
如果自定义构造方法,系统将不再默认提供
且可以重载
调用:
new 构造方法名(实参列表)
作用
1、创建对象
2、创建对象的同时,初始化变量的内存空间
3、也可设置默认赋值
关键字
this
特点:
也是变量
保存自身内存地址 指向自身
存储在堆内存中,表示当前对象
用法:
可用在实例方法中,代表当前对象 this.
可用在构造方法中调用其他的构造方法 this()
不能使用在静态变量中 因为静态变量存储在方法区中
static
修饰
静态变量
静态方法
调用
类名. 调用
在本类 中直接访问
模板级别
如果属性的属性值不会改建议使用static修饰
static修饰都具有类级别的特征 与对象无关
static 修饰的代码块
静态代码块
在main方法之前之前执行
因为在方法区 而main方法在栈内存
且只能执行一次
作用:
静态代码块
看具体需求:例如日志记录
封装工具类
直接类名.调用方法 不用new对象
很方便
final
表示最终的(不可变的)
修饰
类 无法被继承
方法无法被覆盖/重写
不可被重新赋值
修饰实例变量需要手动赋值,系统不会默认赋值
修饰的对象无法被垃圾回收机制回收
final与static联合使用
修饰变量
称为常量
无法修改的类变量
定义
public static final 类型 常量名 = 值;
java语言规范
以常量名命名须用大写
super
调用父类指定操作
访问父类属性
调用父类成员方法
不能出现在静态方法中
调用父类构造器
要放在第一行
在构造方法里调用
super.调用 属性/方法 super(实参)构造方法
insstanceof
检验 是否为类的对象
package/import
表示当前文件路径
如果类名不在同一个包下要假设包名
import 导包
java.lang包下的不用导 包里包要导
转型
对象之间的转型 最好加个instanceof判断
访问权限
public
private
protected
省缺的
抽象类
特点
无法被实例化 无法new 对象
可以定义抽象方法和普通方法
抽象方法
抽象方法加上abstract修饰
没有大括号 以分号结尾
需要被子类重写
普通方法
由于l类不能被实例化
只能用多态才能调用到子类的方法
只能被继承
所以抽象类不能和final关键字写到一起
定义
用abstract修饰
接口
普通接口
定义
interface修饰
implement实现接口
特点:
接口是引用数据类型
接口是完全抽象的 特殊的抽象类 (抽象类是半抽象)
支持多继承 ,多实现
接口中包含俩部分
常量
自动 加上 public static final 修饰
抽象方法
所有的元素都是公开的 会自动加上public abstiact
接口与抽象类的区别
抽象类能有普通方法 接口全是抽象方法
抽象类半抽象 接口完全抽象
抽象类有构造方法 接口没有
接口和接口存在多继承 抽象类只能单继承
接口中只能出现常量和抽象方法
以后接口的使用会比抽象类多 接口一般是对“行为"的抽象
标志接口
标志接口是给java虚拟机看的
例如IO流中的正/反序列都要实现标志接口Serializable
抽象类和接口生来就当爹的 精辟!
类与类之间的关系
猫是动物 继承
我有一支笔 实例变量
厨师像菜单 实现接口
单例模式
私有化构造方法
对外提供唯一实例
类
父类/内部类
Object类
特点
Jdk类库的根类
所有的类都会默认继承Object类
常用方法
toString方法
不重写时会打印 类名@对象的内存地址转换为16进制的形式
输出会默认调用tostring方法
转换成字符串输出
sum公司也建议使用
equals方法
判断俩个对象是否相等
默认是比较俩个对象的内存地址
我们可重写equals方法 使的他比较的对象里面的内容
string类以重写了equals方法和toString方法
hashcode方法
返回的是哈希码
可等同内存地址
因为内存地址通过哈希算法转成数字了
wait(线程等待)与notify(线程唤醒)
内部类
分类
实例
静态
局部
匿名
常用
匿名内部类
只能使用一次
且可直接new 接口 和抽象类
然后对抽象方法进行重写
常用类
String类
调用
直接赋值
分支主题
new 对象赋值到构造器里
特点:
引用数据类型
双引号括起来的都是string对象
存储在字符串常量池中
字符串相同时常量池不会新建,直接用
方法
字符串.charAt(下标) 返回字符串下标的值(掌握)
Contains 是否包含后面的字符串(掌握)
endsWith判断以某个字符串结尾(掌握)
Equals 比较俩个字符串是否相等(掌握)
Equalsignorecase判读俩个字符串是否相等 不管大小写(掌握)
Byte[] 数组 getBytes()字符串对象转化为字节数组 (掌握)
indexOf() 判读当前字符串第一次出现的下标(掌握)
Length 长度(掌握)
Isempty 判断字符串是否为"空字符串“(掌握)
Lastindexof() 字符串最后出现的下标
Replace (a,b) 把a替换成b 返回成新的字符串
Startswith 判断以某个字符串开始 返回值对错
Substring(a,c) 截取字符串a截取 c长度
toCharArray 将字符串转换成char数组
Tolowercas 转小写
touppercase转大写
Trim 去除前后空白
String.Vaueof( ) 将非字符串转换成字符串 静态方法 类名点 调用
Println()
这个方法里面有vaueof 将非字符串转换成字符串
自动调用这个
自动而这个调用tostring方法
StringBuffer类
频繁+号拼接 会浪费方法区常量池的内存
所以我们用StringBuffer类进行拼接
调用:
New 对象初始化 数组
底层是byte【】 数组
append()追加
会自动扩容
Stringbuider类
也是字符串拼接
append()追加
俩者的区别
StringBuffer类线程是安全的
基础类型对应的8个包装类
JDK1.5以后提供了自动拆箱和装箱
日期相关类
Date类 无参构造方法(精确到毫秒)
直接调用输出即可
日期格式化
SimpleDateFormat类
在java,text包下
用构造方法格式化
yyyy年(年是4位数)
MM 月(2位数)
dd 日
mm 分
ss 秒
SSS 毫秒 (三位数)
数字相关类(了解即可)
Dcunauformat数字格式化类
BIgdecimal类精度极高
主要用于财务软件里面
Random 随机数类
new 对象 索引调用
或者匿名调用
里面有一些方法,直接传参即可
Enum 枚举类
特点
可以一枚一枚列举出来的
例如布尔类型只能是ture flase俩种类型
日常开发中 不能只有俩种情况 还有多种
枚举也是引用数据类型 生成class文件 枚举类中的每个值可看做常量
语法:
enum 枚举类名{ 值,值}
调用
例如修饰在方法上时
我们满足什么类型就可以返回自己定义的值
有多种返回标志结果
System类
方法
System,out [out是system类的静态变量}
System.out.println() 【println是println类的方法】
System.gc() 建议启动垃圾回收器
System.currentTimeMillis() 获取1970年到当前的总毫秒数
System.exit (0) 退出JVM
File类
特点
文件和路径名的抽象表现形式
可对文件目录进行操作 但不能读写文件
创建对象 在构造器传入文件路径
方法
索引.exists()判断文件是否存在
索引.createNewFile()以文件的形式创建
索引.mkdir 以目录的形式创建
索引.mkdirs 多重目录
分支主题
索引,getParentFile 获取上层目录
索引.getAbsolutepath()绝对路径
getname获取文件名
isFile判断是否文件
lastModified 最后一次修改时间 (毫秒数)
length大小
listfiles数组方法 获取这个目录全部子文件(循环打印)
忘记了查帮助文档
数组
特点
引用数据类型 分类object (相当于容器)
可存储基本数据类型与引用数据类型
数组存储在堆内存中
存储对象的话 是存取对象的内存地址
所有数组对象都自带length属性
有下标 以0开始 以一递增
分类
一维数组
定义:
数据类型[] 索引={存储的值,对象,数组,。。。}
数据l类[] 索引=数据类型[长度]
调用
索引[下标]
二维数组
定义:
数据类型[] [] 索引={{存储的值,对象},{数组,。}。。}
调用/赋值
索引[外层下标][内存下标]
多维数组
动态数组
Arraylist
遍历
for
倒叙
从来索引,length-1开始 大于0 自减
打印输出
正序
从0开始 到length结束 递增
打印输出
foreach
左边数组类型 索引:数组索引
打印 索引
常见算法
排序算法
冒泡
选择
查找算法
二分法查找
Arrays工具类
里面封装了这些常见的算法
因为用Static修饰
类名点调用
数组扩容
语法
System.arraycopy(ints,1,ints1,3,2);
将ints 数组 起始位置下标1 拷贝对象 ints1 起始位置下标3 长度为2
进行拷贝
异常
概述:
控制台的异常都jvm打印的
异常在java中以类的形式存在
jvm在执行异常程序时会自动new异常对象
只有运行阶段才能new对象,异常都是在运行阶段发生的 异常发生就要new对象
Exception(编译时异常)或者RuntimeExcention(运行时异常 )
作用
提醒程序员
让程序更加健壮
自定义异常
1编写一个类 继承 Exception或者RuntimeExcention
2:提供俩构造方法
无参构造
带有String参数的有参构造
surper传入字符串的索引
调用自定义异常
在需要发生异常的方法里
throw new 异常类 手动抛出异常 即可
对异常的处理机制
抛出
thorow抛出异常 上报给调用者 在方法声明的位置上使用
捕捉
使用try..catch语句进行异常捕捉
catch可写多个 原则从上到下 从小到大
finally最后一定执行的 一般流的结束 会放在这里
编译时y异常与运行时异常的区别
编译时异常发生概率比较高 编译器会爆红
运行时异常发生概率较低
集合
概念
数组是集合
集合实际上就是容器/载体 可以一次容纳多个对象(存储的是内存地址)
可以容纳其他类型的数据
使用不同的集合就会使用不同的数据结构
集合接口与集合类都在java.util包下
俩大类
Collection超级父接口(单方式存储)
继承Iterable接口
拿到迭代对象
迭代对象的方法
hasNext()(判断是否还有下一个元素)
next()(拿到下一个元素 并返回)
remove
被继承
List接口
特点
有序可重复
存储元素有下标 从零开始以一递增
实现类
Arraylist集合(常用)
特点
底层采用数组数据结构,非线程安全 可用工具类来抵消线程安全问题
默认初始化容量为10 在构造器里面里面初始化
你也可以自己new 对象时手动初始化
底层是object数组
扩容到原容量的1.5倍
检索效率较高 向数组末尾添加元素效率高
但随机增删元素效率低
无法存储大数据量
优化:建议预估记元素个数 给定一个初始化容量
方法
Linkedlist集合
特点
底层采用双向链表
链表
优点
在空间存储的内存地址不连续
随机增删元素时不会有大量元素位移,因此随机增删效率高
以后开发中,如果遇到随机增删集合中元素的业务比较多时,建议使用Linkedlist
缺点
不能通过数学表达式查找元素内存地址
链表数据结构
链表数据结构(双向链表)
链表基本单元是节点Node。
对应单向链表来说,任何一个节点Node中都有俩个属性:
第一:存储的数据结构。第二:下一节点的内存地址
优点:随机增删效率高
缺点:查询效率低 (每一次都从头开始找)
arraylist/linkedlist
Arraylist:把搜索发挥到极致
linkedlist:把随机增删发挥到极致
//现在加元素都是往末尾加 所以Arraylist用的比Linkedlist多
方法
vector集合(很少用)
也是数组结构
list接口常用方法
add ( int指定位置,添加元素)
get(int指定位置) 返回指定位置的元素
Indexof() 返回第一次出现的索引 没有返回-1
Lastindexof 最后一次出现的
Remove 移除下标
分支主题
Set {替换 第几个元素 下标,重新赋值)
Set接口
特点
无序不可重复
存储元素无下标
实现类
Hashset集合
特点
new在创建对象时 底层创建实现上了new了HashMap集合
向Hashset集合存储元素,实际上是存储到HashMap中
HashMap集合是哈希链表数据结构
使用遍历
hashset集合不可重复 我们可以往hashset集合里面添加元素
然后在把这个索引传参给 我们arraylist 实现类的构造方法里面
就可以用arraylist遍历里面元素倒序正序都可以 然后用arraylist的get方法打印
继承
sortedset接口
实现类
Treeset集合
特点
底层是TreeMap集合
Treeset集合放数据时会将数据放入TreeMap中
TreeMap底层底层是二叉树结构
放在TreeSet集合中的元素需要实现java.lang.Comparable接口。
继承Comparable《排的类》接口
并且实现compareTo方法。equals可以不写。(String类型已经重写了)
返回0 value覆盖 >0右树上找 <0 左数上找
排序
TreeSet集合可排序的第二种方法 使用比较器的方式
编写比较器类 实现comparator接口 并且重写compare方法
然后在Treeset对象的构造方法里传入比较器对象
特点
无序不可重复
元素可自动排序
总结:
这里面只有Arraylist,linkedlist,vector,Hashset,TreeSet是实现类
其他全部都是接口
Collection常用方法
索引.add向里面添加元素 new对象 和基本数据类型
因为在jdk8后会自动装箱拆箱 把内存地址加进去
索引.size 集合的长度
索引.clear 清空集合
索引.contains(obj某元素) 判断集合里面是否包含 某元素 返回布尔值
索引.remove(obj元素) 删除集合中的某个元素
索引.isEmpty() 判断集合是否为空 返回布尔值
分支主题
索引.toArray() 把集合转成数组
集合遍历
迭代器调用
是collection即子类中都能使用 (map不能用)
第一步:
获取集合对象的迭代器对象Iterator
第二步
获取以上迭代器对象 开始迭代/遍历集合
以下俩个方法是迭代器对象的Iterator的方法:
hasNext()如果仍有元素可以迭代ture 返回布尔值
next()返回迭代下一个元素 元素 object
迭代器最好里遍历循环近一点,以便数据结构发生改变 要重新获取
for循环遍历
foreach循环遍历
Map超级父接口(键值对方法存储)
特点
Map集合与collection集合没有关系
map集合以key和value这种键值对的方式存储元素
key和value都是存储对象的内存地址
所有的key都是无序不可重复的
key和set集合存储元素的特点相同
key起到主导的地位,value是key的附属品
实现
Hashmap集合
特点
哈希表是一个数组和单向链表的结合体
哈希表数组和单向链表这俩种数据结构融合
充分发挥他们各种的优点
无序,不可重复
用equals方法保证hashmao集合的key不可重复
如果重复就覆盖
hashmao集合部分元素放到Hashset集合中所以HashSet集合中的元素也需同时重写hashcode+equals方法
方法
Map.put(k,v)
v.map.get(k);
注意
放在hashmap集合的key部分的元素,以及放在hashset集合中的元素,需要同时重写hascode和equals方法
jdk8之后如果哈希表这种数据结构单向链表超过8个
会变成红黑树数(二叉树)据结构,红黑树上的节点数量小于6又会变成单向链表
非线程安全的
hashtable集合
特点
底层是哈希链表数据结构
线程安全
继承
properties属性类对象
特点
线程安全
方法
存:
索引.setProperty( key , value ) //key和value都是字符串
取:
索引.getproperty(key);
继承
sortedMap接口
实现
TreeMap集合
特点
方法
常用方法
clear 清空map集合
containskey(key) 是否包含key
containsvalue(value) 是否包含value
get(key) 通过key获得value
Isempty 判读元素个数是否为0
Keyset 获取 map集合所有的key
put(k,v)添加键值对
remove(key)通过key删除键值对
Size 获取键值对的个数
Values 获取所有的values
Set<map.Entry<k,v>> entrySet() 将map集合转换成set集合
遍历Map集合
方法
第一种
通过set《泛型》 获取 map.seyset() 获取key值
然后通过 迭代器 Iterator 进行遍历
第二种
通过forEach循环遍历
第三种
Set<map.Entry《k,v>> entry set()
将map集合全部转换成Set集合。
set集合的类型是Map.Entry
第三种方法开发效率比较高,转成set集合在用foreach循环遍历
集合工具类
Collections:是集合的工具类
Collections.synchronizedList(Arraylist索引);
可以把Arraylist数组非线程安全转换成线程安全的
Collections.sort 排序 对list元素排序需要保证list集合中的元素实现compareble接口
COllections。sync。。。实现线程安全
如果set想实现排序 要对set进行转化 转成 list
new对象 把set索引传入 list构造器中
总结
所有的实现类
Arraylist:底层是数组
Linkedlist:底层是双向链表。
Vertor:底层是数组,线程安全,效率低。使用少。
HashSet:底层是HashMap;放到HashSet集合中的元素等同放到HashMap集合Key部分了
TreeSet:底层是TreMap,放到TreeSet集合中的元素等同于放入TreeMap集合key部分
HashMap:底层是哈希表。
Hashtable:底层也是哈希表,只不过线程安全的,效率较低,使用少。
Properties:是线程安全的,并且Key和value只能存储字符串String
TreeMap: 底层是二叉树,TreeMap集合的key可以自动按照大小排序
集合需要掌握什么内容?
1.每一个集合对象的创建(new)
2.向集合中添加元素
3.从集合中取出某个元素
4.遍历集合
5.主要的集合类:
Arraylist
LinkedList
HashSet、(hashmap的key需重写hascode+equals)
TreeSet
HashMap
Properties
TreeMap
泛型
特点
指定数据类型
使集合的元素更加统一
不加泛型时默认是object类型
想要调用存储对象时
需要转型
加l了泛型后可不用转型直接调用
也可配合多态使用抽象类、接口,重写他们的方法,拿到构造器泛型 循环判断 直接调用 如果调用子类特有方法需要转型
自定义泛型
类名<名称自己定义>
调用
类名<传入数据类型> 索引=new 类名<>();
后面<>表示自动判断
JDK8的新特性
IO流
Java.IO包下需要掌握的流有16个
文件专属:
FileInputStream(掌握)
byte[]数组装
标识符=0 循环判断 标识符=对象索引.read(数组)!=-1
打印控制台
new String(读取文件,从那里开始,从那里结束/标识符)
关闭流/包装流
常用方法:
Int available()返回流当中剩余的没读到的字节数量
Long skip(long n)跳过几个字节不读。
FileOnputStream(掌握)
创建数组
标识符 循环
对象索引.Write(写入文件,那里开始,标识符结束)
刷入硬盘
关闭l流
默认是覆盖/追加的话要在构造方法那里加上true
FileReader
用char数组装 方法都差不多
FileWrter
转换流:(字节转字符)
inputSttreamReader
OnputStreamWriter;
缓冲流:
BufferedReader
不需要带自定义数组
可读取一行readline()
BufferedWriter
BufferedInputStream
创建节点流
创建包装流 节点流传入包装流的构造方法中
创建标识符 String类 赋值null
while循环 判断标识符=读的没一行!=null;
输出控制台
关闭包装流即可
BufferedOutputStream
数据流
DataInputStream
DataOutputStream
标准输出流:
PrintWriter
printStream(掌握)
PrintStream标准的字节输出流。默认输出到控制台
且不需要手动close()关闭
对象专属流
ObjectInputStream(掌握)
序列化
参与序列化/反序列化的对象
对象类必须要实现Serializable接口,接口是标识接口
否则会出现序列化异常
一次序列化多个对象,用数组装
ObjectOutputStream(掌握)
反序列化
反序列化(拿到读到的obj)判断往下转型 转成数组 然后打印输出
结论
凡是一个类实现了Serializable接口,建议给该类提供一个固定不变的序列号版本号。
这样即使该类的代码修改,版本号不变,java虚拟机会认为是同一个类
手动生成序列号
Private static final long serialVersionUID=23442342L;
注意:
在java中只要"类名"
以Stream结尾的都是字节流
字节流,一次读取一个字节8byte
万能流,可读取视频,图片,声音
以Reader/Writer 都是字符流
一次读取一个字符
方便读取普通文件
视频、声音、word等文档不可读取
输入与输出
I: Input(输入)/Read
O:Output(输出流)/Write
最后需要.flush刷入键盘
特点:
所有的流动实现了:Closeable接口 都是可关闭的
都有close()方法 用完要关闭 不然会耗费很多资源
所有的输出流都实现了:Flushable都是可以刷新的
都有flush方法 在最终输出之后要记得刷新一下
刷新的作用就是清空管道
如果没有可能会导致丢失数据
IO流和properties属性集合的联合使用
IO流文件的读写
properties;是map集合,key和value都是String类型
很好的设计理念,编写好代码时不需要改动 直接在配置文件更换value值就可以调用到不同对象
反射机制
JDBC可能会用上
配置文件
内容格式Key=value
Key=value
java规范中 属性文件建议以.properties结尾
多线程
特点
一个java程序中至少有俩个线程并发,main方法主线程 垃圾回收线程
使用多线程后,main方法结束了只是主栈结束了,还有可能其他的栈在压栈弹栈
进程内存独立不共享
在java中,线程A与线程B,堆内存和方法区内存共享
但是栈内存独立,一个线程一个栈,每个栈之间互不干扰
各自执行各自的,这就是多线程并发
作用
多线程机制就是提高程序处理效率
java三大变量
实例变量:在堆中 成员变量包括实例和静态
静态变量:方法区
局部变量:栈中
局部+常量永远都不存在线程安全问题
因为局部变量存在栈中 局部变量不共享(一个线程一个栈)
堆只有一个
方法区也只有一个
堆和方法区都是多线程共享的
实现方法
以Thread类形式创建
创建一个类 继承Thread类
重写run方法
new 对象
Start方法启动
Runable接口的形式创建
创建一个类实现Runable接口
重写run方法
new 对象
再new 一个Thread对象 把接口对象传入Thread构造方法中
start启动线程
或者直接匿名调用 接口
接口比较常用 因为java只能单继承却能实现多个接口
实现Callable接口
有返回值
优点
可以获取返回值 获取线程的执行结果
缺点
效率较低,在获取返回值时,需要线程执行完才能返回值,会造成堵塞
线程的生命周期
新建状态
就绪状态
运行状态
堵塞状态
死亡状态
线程的方法
setname修改线程名字(默认的名字是Thread 0开始往后自增
getname获得线程名字
Thread.currentThread() 静态方法 获取当前线程对象(出现在那个栈中就获取那个栈的线程)
Thread.sleep() 静态方法 让当前线程进入休眠状态 参数跟的是毫秒数
Interrupt 唤醒线程 (比如你让一个线程睡眠一年,用这个方法可直接唤醒他)
join合并线程
实例方法
合并线程
就是并发变成同步
不是栈合并 是栈等待了
stop终止线程(已过时)
容易丢失数据
常用终止线程的方法
定义一个布尔标识符
初始值为true
if判断标记为true 执行 在else中return结束方法
在return之前也可以保存好数据在结束方法
终止线程时调用这个对象的标识符改成false
java调度
setpriority设置线程优先级
getpriority获取线程优先级
最低1默认5最高10
Yield 静态让位方法 不是堵塞 是让位当前线性
运行阶段回到就绪状态 就绪之后他有可能又会去抢占
调度模型(了解)
抢占式线程模型
抢占cpu时间片
java采用的
均分式线程模型
平均分配时间片
有些编程语言也采用这个
线程同步机制
语法
synchronized(){ 线程同步代码块数据 }
小括号里面传入的是共享数据的对象
模型
异步编程模型(并发)
多线程并发(效率高)
同步编程模型(排队)
俩个线程存在等待关系(效率低)
synchronized四种写法
同步代码块(灵活)
实例方法上使用synchronized
在静态方法上使用synchronilzed
FutureTask方式.实现Callable接口
以后开发怎么解决线程安全问题?
synchronized会让程序效率降低(用户吞吐量降低,用户体验差)
第一种方案:尽量使用局部变量代替实例变量和静态变量
第二种方案:如果必须要用实例变量,那么考虑创建多个对象
第三种方案:最后前面俩个不行的话再synchronizedx线程同步机制
定时器
间隔特定的时间,执行特定的程序
例如:备份操作
Java.util.Timer类
实现定时器
定时任务的对象要继承TimerTask 线程
要重写run方法
守护线程
特点:
一般守护线程都是一个死循环
所有的用户线程结束,守护线程自动结束。
主线程main也是用户线程
用在那里?
进行数据定点备份
java语言线程分为俩大类
一类是:用户线程
一类是:守护线程(后台 线程)
调用
在启动线程之前
用setDaemon(true)方法
设置为守护线程
生产者与消费者
Object类中的wait(线程等待)和notify(线程唤醒)方法
简介
wait和notify是所有类中都有的不是线程对象的,
因为所有类都继承object类
所以调用时不是通过线程对象调用
wait方法作用
当前线程
让活跃的对象线程进入等待状态 无期限 直到被唤醒为止
Notify
唤醒等待线程 对象点调用 唤醒当前线程
对象不是线程对象
一般wait与notify联合使用
还有notifyALL是唤醒 在这obj对象上的所有线程
调用
比如先new了一个o对象
然后o对象开启了俩个线程 一个A一个B
调用时用o索引.方法调用
反射机制
作用
可以操作class字节码文件
类似黑客,可以读写修改字节码文件
创建拿到对象三种方式
Class c=Class.forName(完整包名类名)
Class c=对象.getClass()
Class c=类型.class
分支主题
c返回的是类型 还要将其实例化才能用
实例化对象
Newinstance方法 (jdk9已过时)
实例化对象
拿到对象类型 然后对象.newinstance
调用时要保证有无参构造
反射机制相关的重要的类
Java.lang.class 代表字节码文件
Method 字节码中的方法字节码
反射的方法
获取反射对象
对象实例化
对象。getDeclaredfield ("属性名")
获取属性
Set(对象,"修改的值")
get(对象) 获取值
想访问私有的
setAcceessible(true)打破封装
获取父类接口
getsuperclass获取父类
getinterfaces获取接口
接口是多个 所以是数组 可以遍历获取
调用方法
例子
Classc=Class.forName("practice01.EEE");
//实例化
Objecto=c.newInstance();
//获取方法
Methodmodifiers=c.getDeclaredMethod("sum",int.class,int.class);
//调用什么对象的什么方法方法传参
Objectjieguo=modifiers.invoke(o,12,13);
//输出返回值
System.out.println(jieguo);
Constructor 字节码中构造方法字节码
调用构造方法:
//获取构造方法
getDeclaredConstructor( 类型.class ….)
//调用构造方法
构造方法的索引.newInStance(传入参数)
Field 字节码中的属性字节码
修改属性
拿到反射对象实
Object类型 多态索引.newinstance实例化
Fieldfield=c.getDeclaredField("age");
//给属性赋值obj的age属性赋值19
field.set(obj,15);
//这里也可以赋值到配置文件里修改配置文件的东西
反射机制的灵活性
java代码写一遍 在不改变原代码的基础
可以做到不同对象的实例化
非常灵活(符合OCP开闭原则:对象扩展开发,对修改关闭)
后期:学习的高级框架,工作过程中也使用高级框架
包括:ssh ssm
这些框架底层实现原理:都采用了反射机制
所以学习反射机制有利用你去理解框架底层原代码
反射反编译(了解即可)
可拿一个整个类的到属性方法源码
文件路径问题
特点:
通用方式 即使代码换位置也有效
通用方式的前提是:这个文件必须在类路径下
凡是在src下的都是类路径(其实是out class文件 现在就当这么理解)
如果将来项目放到linux上运行的话 linux没有C D盘符时 这个通用方法也依然有效
获取通用绝对路径方法
String path=Thread.currentThread().getContextClassLoader()
.getResource("输入从src开始的文件名").getPath();
这种方式获取的是绝对路径是通用的
Thread.currentThread()当前线程对象
getContextClassloader()线程对象的方法,可以获取当前线程的类加载对象
getResource()获取资源
资源绑定器
获取属性配置文件 配置文件 key=value
属性配置文件xxx.properties必须放在类路径下
且后缀名properties不能写
这种方式连IO流的影子都不用写
直接获取key值
例
ResourceBundlebundle=ResourceBundle.getBundle("Peizhiwenj\\classinf");
//资源绑定器只获取属性配置文件后缀名不能写
String text04=bundle.getString("Text04");
System.out.println(text04)
//此时输出的是value 如果这配置文件value保存是路径名
我们就可以通过反射机制来传入这个路径名 调用这个类
获取文件绝对路径通用三种方式
1用字符串获取 再传入io流中
2直接用io流获取
InputStream inputStream=Thread.currentThread().getContextClassLoader().getResourceAsStream("Peizhiwenj\\classinf.properties");
还有第三种方法 sum公司写好的资源绑定器
IO与propertier属性集合与反射机制联合调用
通过IO流读取配置文件
创建propertier集合
把读到的文件
放入 propertier的load方法里面
关闭流
然后获取getproperty(key) 路径名
然后放入 class.forName中
然后用索引点,newInstance 实例化对象
类加载器(了解)
启动类加载器
扩展类加载器
应用类加载器
注解
注解Annotation是引用数据类型 编译生成xxx.class文件
自定义注解
语法格式:
【修饰符列表】@interface 注解类型名{}
@interface修饰 属性、数据类型 变量名();
调用时要给属性没有值时要赋值
注解直接(属性名=值,…...)
有属性必须赋值
如果后面有default 值 ;
可以给属性赋值一个默认值
这样在调用时可以不赋值
如果后面有default 值 ;
可以给属性赋值一个默认值
这样在调用时可以不赋值
调用格式
@注解类型名
可出现在类、属性、方法、变量上等。。。
注解还可以出现在注解类型上。
JDK内置了那些注解
Java.lang包下的注解类型:
Deprecated用@Deprecated注释的程序元素(掌握)
告诉其他程序员不鼓励使用,通常是因为他很危险 或存在更好的选择 就是告诉别的程序员 这个程序以过时
Override表示一个方法声明打算重写超类中的另一个方法声明(掌握)
Suppresswarnings 指示应该在注解元素中取消显示指定的编译器警告(不用掌握)
元注解
用来标注注解类型的注解;称为元注解
分支主题
常见的元注解有:以下
Target注解:
是元注解 用来标志 被标志的注解
能出现在什么位置上
@Target(ElementType.METHOD) //只能出现在方法上
Retention注解
元注解,这个用来标注被标注的注解最终保存在那里
例:
@Retention(RetentionPolicy.SOURCE)//表示保留在java原文件当中
@Retention(RetentionPolicy.CLASS)//表示保留在Class文件当中
@Retention(RetentionPolicy.RUNTIME)//表示保留在class文件当中,并且可以被反射机制读取到
0 条评论
下一页