多线程的创建
①:继承于Thread类
-
创建一个继承于Thread类的子类
-
重写Thread类的run( )方法————>将此线程执行的 *** 作声明在run( )中
public void run( ){ }
-
创建Thread类的子类的对象
-
通过此对象调用start( )(来自父类)
- start的两个作用:1)启动当前线程 2)调用当前线程的run( )
注意:
- 直接通过对象调用run( )是单线程
- 一个对象只能调用一次start( )
- start( )会有个默认值,一旦执行过就不可再调用。
- Thread也是重写了Runnable类中的run( )方法的。
②:实现Runnable接口(多线程共享数据)
导包:
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
-
创建一个实现Runnable接口的类
-
实现类去实现Runnable接口中的抽象方法run( )
-
创建实现类的对象
只有一个实现类对象,被作为多个Thread类的参数时,可以实现多线程共享数据
-
将实现类的对象作为参数传递到Thread类的构造器中
-
通过Thread类的对象调用start( )
注意:
-
该线程实现过程:
-
start( )调用了Thread类的对象所对应的run( ),而Thread类中的run( )实质是调用Thread类中的Runnable属性的变量的run( )。
-
将实现了Runnable接口的类的对象作为参数传递给了Thread类中的构造器,构造器给其内的Runnable属性的变量赋值,再通过该Runnable属性的变量调用了其对应的run( )。
-
③:实现Callable接口
-
创建一个实现Callable接口的类
-
实现call( )—————>将线程需要执行的 *** 作声明在此内
public Object call( ){ }
-
创建Callable接口实现类的对象
-
创建FutureTask类的对象前,将Callable接口实现类的对象传递给FutureTask类的构造器
-
将FutureTask类的对象作为参数传递给Thread类的构造器,通过Thread类的对象启用start( )
-
(可选)若实现的call( )有返回值,可通过FutureTask类的对象调用get( )获取返回值
④:线程池
- 提供指定数量的线程池
- 执行指定的线程 *** 作(需要提供实现了Runnable接口或Callable接口的实现类的对象)
- 关闭线程池
- currentThread( )
- 静态方法,放回执行当前代码的线程
- getName( )
- 获取当前线程的名字
- getName( )
- 获取当前线程的名字
- Thread提供了相对应的构造器
- yield( )
- 释放当前CPU的执行权
- 释放后仍有可能是该线程继续执行
- join( )
- 在线程a中调用线程b的join( ),此时线程a进入阻塞状态,直到线程b完全执行完后,才会结束线程a的阻塞状态
- stop( )
- 当执行此方法时,强制结束当前线程
- sleep( x )
- 让当前线程阻塞x毫秒
- isAlive( )
- 判断当前线程是否存活
- MAX_PRIORITY:10——————>最大线程
- MIN_PRIORITY:1——————>最小线程
- NORM_PRIORITY:5——————>默认线程
getPriority( ):获取线程优先级
setPriority( int p ):设置线程优先级
线程的安全问题当一个线程 *** 作未结束,其他线程参与进来,就有可能会产生安全问题。
解决方法:
①同步代码块:
synchronized(同步监视器){ 需要被同步的代码 }
- *** 作共享数据(多个线程同时 *** 作的变量)的代码,即为需要被同步的代码。
- 同步监视器(锁):任何一个类的对象,都可以充当锁。
- 注意:多个线程必须是共用一把锁。
②同步方法:
- 同步方法仍然涉及同步监视器,只是没有显示的声明出来,根据是否为静态方法,同步监视器的对象也不同
1)非静态的同步方法:this
2)静态的同步方法:当前类本身(静态修饰的方法随类的加载而加载)
补充:
- 同步的方式解决了线程的安全问题,但 *** 作同步代码时,只能有一个线程参与,其他线程等待,此时就相当于是一个单线程的过程。
③Lock锁:
-
导包:
import java.util.concurrent.locks.ReentrantLock
-
实例化 ReentrantLock类
-
调用锁定方法 lock( )
-
调用解锁方法 unlock( )
注意:
- 需要手动的解锁
- 锁也要保证是同一个锁
涉及3个方法(只适用于同步代码块和同步方法中):
-> wait( ):一旦执行此方法,当前线程会进入阻塞状态,并释放同步监视器
-> notify( ):一旦执行此方法,会唤醒一个被wait( )的线程(以线程优先级决定)
-> notifyAll( ):一旦执行此方法,会唤醒所有被wait( )的线程
注意:
- 三个方法的调用对象和同步监视器必须是一致的
- 三个方法都声明在Object类中(为方便各类对象的调用)
关于sleep( )和wait( )
相同点:
- 都可以使线程进入阻塞状态
- 都会抛出异常
不同点:
- sleep( )声明于Thread类,wait( )声明于Object类
- sleep( )可在任何需要的情况下调用,wait( )只能在同步代码块或同步方法中调用
- 若两者同时作用于同步代码块或同步方法中,sleep( )不会释放同步监视器,wait( )会释放同步监视器
关于Callable接口比Runnable接口创建多线程强大的原因
- call( )可以有返回值
- call( )可以抛出异常
- Callable支持泛型
String
String基本要点
- 字符串,用" "引起来,具有不可变性,代表不可变的字符序列
1.String是final修饰的,表示不能被继承
2.String实现了Serializable接口:表示字符串支持序列化
3.String实现了Comparable接口:表示String可比较大小
4.String在底层是为final修饰的char[ ],用于存储字符串数据,final表示其引用地址不可被修改,char[ ]内的元素被赋值后不能被改变 ,且长度固定后也不可更改
5.当通过字面量的方式给字符串赋值时,此时的字符串值声明在字符串常量池中
6.字符串常量池不会存储相同内容的字符串
7.不可变性的体现:
- 对字符串重新赋值时,不会对原有的值进行覆盖
- 对字符串进行连接 *** 作时,会重新指定一块内存区域
- 调用String的replace( )修改指定的字符串,也要重新指定内存区域
8.String实例化的两种方式:
1)通过字面量赋值的方式
- 存放在字符串常量池中
2)通过new+构造器的方式
- 在堆中生成一个地址,该地址赋值给变量,而地址又会指向字符串常量池
9.字符串拼接时:
- 如果都是常量拼接,存放在字符串常量池中(包括final修饰的变量)
- 如果含有变量,则会在堆中
- 如果调用了intern( ),则调用了该方法的字符串的返回值是存放在字符串常量池中的
注意:字符串的不可变性
①int length()
:返回字符串长度
②char charAt(int index)
:获取指定下标的字符
③boolean isEmpty()
:判断是否为空字符串
④String toLowerCase()
:将字符串中的字符转为小写
⑤String toUpperCase()
:将字符串中的字符转为大写
⑥String trim()
:忽略头部空白和尾部空白
⑦boolean equals(Object obj)
:比较字符串内容是否相同
⑧boolean equalsIgnoreCase(String anotherString)
:忽略大小写的情况下比较字符串内容是否相同
⑨String concat(String str)
:将指定字符串连接到尾部,等价于+
⑩int compareTo(String anotherString)
:比较两字符串大小,返回两者相减的值(用括号内的字符串减去调用该方法的字符串)
⑪String substring(int beginIndex)
:返回从beginIndex
开始,往后截取到的字符串(包含beginIndex
)
⑫String substring(int beginIndex,int endIndex)
:返回从beginIndex
开始,到endIndex
结束,中间所截取到的字符串(包含beginIndex
,不包含endIndex
)
⑬boolean endsWith(String suffix)
:判断调用该方法的字符串是否以指定的字符串为后缀结束的
⑭boolean startsWish(String prefix)
:判断调用该方法的字符串是否以指定的字符串为前缀开始
⑮boolean startsWith(String prefix,int toffset)
:判断调用该方法的字符串从toffset
位置开始,是否以指定的字符串开头
⑯boolean contains(CharSequence s)
:判断调用该方法的字符串中是否有包含指定字符串中的字符
⑰int indexOf(String str)
:返回指定的字符串 在调用该方法的字符串中 第一次出现的位置,如果未找到,返回-1
⑱int indexOf(String str,int fromIndex)
:从指定的位置开始往后找,返回指定的字符串 在调用该方法的字符串中 第一次出现的位置,如果未找到,返回-1
⑲int lastIndexOf(String str)
:返回指定的字符串 在调用该方法的字符串中最右边第一次出现的位置,找不到返回-1
⑳int lastIndexOf(String str,int fromIndex)
:从最右边的指定位置开始,寻找指定的字符串 在调用该方法的字符串中 处于该位置前的最右边的位置,若找不到,返回-1
⑳-①String replace(char oldChar,char newChar)
:将所有和前者匹配的字符替换为后者的字符
⑳-②String replace(CharSequence tager,CharSequence replacement)
:将所有与前者匹配的字符串替换为后者的字符串
①String ----> 基本数据类型、包装类:
- 包装类型 . parse基本类型( String类型变量 )
- 返回值是基本类型
②基本数据类型、包装类 ----> String:
- 1.使用+连接符
- 2.调用String . valueOf( 对应类型的变量 )
- 返回值是包装类型
③String ----> char[ ]
- 要转的String类型变量 . toCharArray( )
④char[ ] ----> String
- 创建String类型的对象,调用其构造器
⑤String ----> byte[ ](编码)
- 要转的String类型变量 . getBytes( )
- ( )可以传特定的编码集的String类型名称,进行编码
⑥byte[ ] ----> String(解码)
- 创建String类型的对象,调用其构造器
- 构造器内可以传特定的编码集的String类型名称,进行解码
(增)①StringBuffer append(xxx)
:可传多种数据类型,用于进行字符串拼接
(删)②StringBuffer delete(int start,int end)
:删除从start
位置开始,到end
位置前一个的内容
(改)③StringBuffer replace(int start,int end,String str)
:把从start
位置开始,到end
位置的前一个,其中的内容替换为指定的字符串
(插)④StringBuffer insert(int offset,xxx)
:可插入多种数据类型,在指定的位置插入
⑤StringBuffer reverse()
:将当前的字符串逆序
⑥public int indexOf(String str)
:返回指定的字符串 在调用该方法的字符串中 第一次出现的位置,如果未找到,返回-1
⑦public String substring(int start,int end)
:返回一个从start
开始,到end
的前一个结束,之间的字符串,原本的字符串不会发生改变
⑧String toString()
:返回String类型的字符串
Date类
1)java.util.Date
(父类):
- 两个方法使用:
- toString( ):显示当前的年、月、日、时、分、秒
- getTime( ):获取当前Date对象对应的毫秒数(时间戳)
- 两个构造器:
- Date( ):创建一个当前时间的Date对象
- Date(Long time):创建一个指定毫秒数的对象
2)java.sql.Date
(子类)
实例化对象:使用不同的构造器(不同构造器解析格式不同)
- 格式化:日期 —> 字符串
- (返回String类型)对象名 . format( Date类型数据 )
- 解析:字符串 —> 日期
- (返回Date类型)对象名 . parse( 传对应字符串格式 )
1)实例化:
- 创建子类(GregorianCalendar)的对象
- 调用Calendar . getInstance( )(静态方法)
2)常用方法:
- get( Calendar的静态属性 )
- 获取特定时间
- set( Calendar的静态属性 , 对应时间 )
- 将Calendar的静态属性对应的时间替换为指定的时间(无返回值,在原有基础上修改)
- getTime( ):日历类 —> Date
- 将当前对象对应的日期转化为Date的日期格式
- setTime( Date类型数据 ):Date —> 日历类
- 将指定的Date类型数据转化为Calendar类型数据(无返回值,在原有基础上修改)
LocalDate、LocalTime、LocalDateTime注意:月份从0开始,星期日是1
1.now( ):获取当前的日期、时间、日期+时间
2.of( ):设置指定的年、月、日、时、分、秒,没有偏移量
3.getXxx( ):获取指定的属性的值
4.withXxx( ):设置指定的属性的值(有返回值,不可变性)
5.plusXxx( ):对指定的属性进行添加 *** 作(有返回值,不可变性)
6.minusXxx( ):对指定的属性进行减 *** 作(有返回值,不可变性)
Instant瞬时点1.now( ):获取本初子午线对应的标准时间
2.toEpochMilli( ):获取从1970年1月1日0时0分0秒开始的毫秒数
3.ofEpochMilli( ):通过给的毫秒数,获取Instant实例
DateTimeFormatter- 格式化或解析日期、时间
①实例化方式:
- 预定义的标准格式
- ISO_LOCAL_DATE_TIME ; ISO_LOCAL_DATE ; ISO_LOCAL_TIME
- 本地化相关的格式
- ofLocalizedDateTime( FormatStyle.LONG )
- 自定义的格式
- ofPattern( “yyyy-MM-dd hh:mm:ss” )
②常用方法:
1.ofPattern( String pattern ):
- 静态方法,返回一个指定字符串格式的DateTimeFormatter
2.format( TemporalAccessor t ):
- 格式化一个日期、时间,返回字符串
3.parse( CharSequence text ):
- 将指定格式的字符序列解析为一个日期、时间
Comparable接口(自然排序)
- String、包装类等实现了Comparable接口,重写了compareTo(obj)方法,已经指明了两个对象的比较方式(默认从小到大排序)
1、让自定义类实现Comparable接口
2、重写compareTo(obj)方法
public int compareTo(Object obj)
{ 指明不同类之间的排序的方式 }
- 重写compareTo(obj)的规则:
- 如果当前对象this大于形参对象obj,返回正整数
- 如果当前对象this小于形参对象obj,返回负整数
- 如果当前对象this等于形参对象obj,返回零
- 通常使用匿名对象的匿名类直接一次性使用
1、构建匿名对象的匿名类
2、重写compare(obj1,obj2)
public int compare(Object obj1,Object obj2)
- 重写compare(obj1,obj2)的规则:
- 如果obj1大于obj2,返回正整数
- 如果obj1小于obj2,返回负整数
- 如果obj1等于obj2,返回零
java.lang
包下
①(native long)currentTimeMillis()
- 获取当前时间距离1970-01-01 00:00:00的毫秒数
②(void)exit( int status )
- 退出程序,status值为0表示正常退出,非0表示异常退出
③(void)gc( )
- 请求系统进行垃圾回收
java.lang.Math
①abs( )
- 求绝对值
②sqrt( )
- 求平方根
③pow( double a , double b )
- a的b次幂
④log( )
- 自然对数
⑤exp( )
- e为底指数
⑥random( )
- 返回0.0到1.0的随机数
⑦PI
-
获取π的值
关于String、StringBuffer、StringBuilder三者的异同
String:不可变的字符序列,底层用char[ ]存储
StringBuffer:可变的字符序列,线程安全,效率低,底层用char[ ]存储
StringBuider:可变的字符序列,线程不安全,效率高,底层用char[ ]存储
-
通过对应的构造器可以实现三者的相互转换
-
StringBuffer创建一个对象时,会在原有的字符串的长度上加上16,若空间不足时,会扩容2倍+2
-
StringBuffer返回的长度是实际存储的数据的长度
-
尽量使用可以指定空间大小的
StringBuffer(int capacity)
-> 相同点:
①都是用于对象的比较
②一般都用于Arrays . sort( )中
③在返回值前使用-
表示按从大到小的顺序排列
-> 不同点:
Ⅰ、Comparable接口一般用类去实现,相当于一次定义,永久成型
Ⅱ、Comparator接口一般使用匿名对象的匿名子类方式(在调用Array . sort( )时传值)定义,采用一次性使用的方式
枚举类- 类的对象的个数有限、确定(类比单例模式)
- 多用来定义一组常量
自定义枚举类:
- 声明对象的属性(private final)
- 私有化类的构造器,给对象属性赋初始值
- 提供当前枚举类的多个对象(public static final)
使用enum关键字定义枚举类:
默认继承于
java.lang.Enum
类
- 创建当前枚举类的对象,多个对象间有
,
隔开,末尾用;
结束(对象默认为 public static final 修饰)- 创建格式 ----> 对象名( 构造器参数 )
- 声明对象的属性(private final)
- 私有化类的构造器,给对象属性赋初始值
Enum类中的常用方法:
- values( ):返回枚举类型的对象数组,常用来遍历所有的枚举值
- valueOf( String objName ):返回枚举类中对象名为objName的对象
- toString( ):返回当前调用的对象的名称
enum类实现接口:
- 在enum类中实现接口的抽象方法
- 让枚举类的对象分别实现接口中的抽象方法
- 创建格式 ----> 对象名( 构造器参数 ) { 重写的方法 }
①生成文档相关的注解
②在编译时进行格式检查
- @Override:限定重写父类方法,只能用于方法
- @Deprecated:表示修饰的类或方法等已过时
- @SuppressWarnings:抑制编译器警告
③跟踪代码依赖性,实现替换配置文件功能
自定义注解:
- 声明为:@interface
- 定义内部成员(类似无参方法的属性)
- 可以指定成员的默认值,在定义内部成员后用default定义
- 有成员的话,在使用注解时,必须指明其成员的值
- 没有成员时,表明是一个标识作用
元注解:对现有注解进行解释说明的注解
- Retention:指定所修饰的注解的生命周期:SOURCE、CLASS(默认)、RUNTIME(反射可用)
- Target:指明注解可被用于哪些元素
- Documented:使指定的注解在被JavaDoc解析时仍保留下来
- Inherited:使指定的注解具有继承性(可被子类使用)
框架
(一)Collection接口:单列集合,存储一个一个的数据
①List接口:存储有序、可重复的数据
- 要求需要重写equals( )
动态数组
- ArrayList:List接口的主要实现类,线程不安全,效率高,底层使用Object[ ]存储
- LinkedList:对应频繁的插入、删除等 *** 作,效率比ArrayList高,底层使用双向链表存储
- Vector:List接口的古老实现类,线程安全,效率低,底层使用Object[ ]存储
②Set接口:存储无序、不可重复的数据
- 要求需要重写equals( )和hashCode( ),TreeSet类除外
无序:使用哈希值存储
不可重复:用哈希值存储,必要时使用equals进行判断
-
HashSet:Set接口的主要实现类,线程不安全,可以存放null值,底层使用数组+链表存储
a.LinkedHashSet:作为HashSet的子类,遍历数据时,可以按照添加时的顺序遍历,对于频繁使用遍历 *** 作时,效率高于HashSet
-
TreeSet:对添加对象的特定属性进行排序
- 添加的数据要求是同类的对象
- 排序方法本质是用到自然排序和定制排序
- 底层是树型结构,因此不能存放相同数据
(二)Map接口:双列集合,存储一对一对(key - value)的数据
key:不可重复、无序的,使用Set存储,要求所在的类要重写equals( )和hashCode( ),TreeMap例外
values:可重复、无序的,使用Collection存储,要求所在的类要重写equals( )
一个key-values构成了一个Entry对象,无序的、不可重复的,使用Set存储
-
HashMap:Map的主要实现类,线程不安全,可以存储null的key和value
a.LinkedHashMap:遍历元素时,可以按照添加是顺序遍历
-
TreeMap:按照添加的key-value进行排序,按照key来进行排序
- 要求key必须是同一个类型创建的对象
- 排序方法本质是用到自然排序和定制排序
- 底层是树型结构,因此不能存放相同数据
-
Hashtable:古老实现类,线程安全,不能存储null的key和value
a.Properties:常用来处理配置文件,key和value都是String类型
Collection接口中的常用方法底层实现原理:
计算key的哈希值,得到在Entry中的存储位置,判断是否有数据,有的话会比较存储位置上的数据的哈希值是否一样,如果一样,会调用equals方法进行比较,如果比较结果返回true,则会将原数据的values替换为新的key对应的values
①add(Object obj)
:将元素obj添加到集合中
②addAll(Collection e)
:将集合e的所有元素添加到集合中
③size()
:获取已添加的元素的个数
④clear()
:清空集合中的所有元素
⑤isEmpty()
:判断当前集合是否为空
⑥contains(Object obj)
:判断集合中是否包含元素obj
- 比较时调用的是元素obj中的equals( )
⑦containsAll(Collection e)
:判断集合e中的所有元素是否都存在于集合中
⑧remove(Object obj)
:移除集合中的元素obj,返回boolean
- 移除时会调用元素obj中的equals( )
⑨removeAll(Collection e)
:移除和集合e共有的元素,会修改当前集合
⑩retainAll(Collection e)
:获取和集合e共有的元素,会修改当前集合
⑪equals(Object obj)
:判断集合和元素obj是否相同,返回boolean
- 当元素obj是集合时,会根据调用该方法的对象是List接口的子类还是Set接口的子类,确定是有序还是无序,因此不同类型的对象调用时判断的要求会有所不同
- 会调用元素obj中的equals( )
⑫toArray()
:将集合转化为数组,返回Object[ ]
- 数组转集合:调用Arrays类的静态方法asList( )
⑬iterator()
:生成集合的迭代器,用于集合的遍历,返回一个Iterator的对象
- 调用Iterator对象的方法:
hasNext( )
:判断是否还有下一个元素next( )
:指针下移并返回下移后集合上的元素remove()
:删除集合内的元素
- Iterator不具有承载对象的能力,需作为集合的迭代器使用
- 集合对象每次调用iterator( ),都会生成一个全新的Iterator对象,指向第一个元素之前的位置
①void add(int index,Object e)
:在index位置插入元素e
②boolean addAll(int index,Collection e)
:从index位置开始将集合e中的所有元素添加进来
③Object get(int index)
:获取指定位置的元素
④int indexOf(Object obj)
:返回obj在集合中首次出现的位置
⑤int lastIndexOf(Object obj)
:返回obj在当前集合中末次出现的位置
⑥Object remove(int index)
:移除指定位置的元素,并返回该元素
⑦Object set(int index,Object e)
:设置指定位置为元素e,不会修改原集合
⑧List subList(int fromIndex,int toIndex)
:返回一个从fromIndex到toIndex前一个位置之间的集合
常用方法
增:add(Object obj)
删:remove(int index)
、remove(Object obj)
改:set(int index,Object e)
查:get(int index)
插:add(int index,Object e)
长度:size()
遍历:①Iterator迭代器 ②增强for循环 ③普通for循环
Map接口中的常用方法- 添加、删除、修改:
①Object put(Object key,Object value)
:将指定的key-values存放到当前Map对象中(key相同时符合底层存放原理)
②void putAll(Map m)
:将m中的所有key-values存放到当前Map对象中
③Object remove(Object key)
:移除指定的key对应的values,并返回
④void clear()
:清空当前Map对象的所有值
- 查询:
⑤Object get(Object key)
:获取指定的key对应的values
⑥boolean containsKey(Object key)
:判断是否包含指定的key
⑦boolean containsValue(Object values)
:判断是否有指定的values
⑧int size()
:返回当前Map对象中的key-values对的个数
⑨boolean isEmpty()
:判断当前Map对象是否为空
⑩boolean equals(Object obj)
:判断当前Map对象与obj对象是否相等
- 遍历:
⑪Set keySet()
:返回所有key构成的Set集合
⑫Collection values()
:返回所有values构成的Collection集合
⑬Set enrtySet()
:返回所有key-values对构成的Set集合(获取到的值为Map接口中的Empty类(内部类),有相应的getKey()
和getValue()
方法)
常用方法
增:put(Object key,Object value)
删:remove(Object key)
改:put(Object key,Object value)
查:get(Object key)
长度:size()
遍历:keySet()
、values()
、entrySet()
在集合中使用泛型:
- 实例化集合类时,可以指明具体的泛型类型,否则默认为Object类型
- 泛型的类型必须是类,不能是基本数据类型
- 静态方法不能使用类的泛型(静态方法的创建早于泛型的定义)
- 异常类不能声明为泛型
自定义泛型类:
- 在类声明处用
< T >
表明一个未知类型的泛型类 - 在类的内部定义一个类型为T的变量,此时该变量的T默认存放Object类型
- 在创建对象时表明T的具体类型后,此时的T就会对应指定的泛型
- 若子类继承该类时未表明T的类型,则也会默认为Object类型
- 子类也可以再声明多个泛型
自定义泛型方法:
- 泛型方法与该类是否为泛型类无关
- 声明的泛型类型与该类的泛型类型无关
- 泛型方法可以为静态方法
- 在返回类型前加
< T >
表明该方法是泛型方法,而非变量名
泛型在继承方面的体现:
- 类A是类B的父类,但
G< A >
和G< B >
两者间不具有子父类关系,但有共同的父类G< ? >
,称为通配符 - 类A是类B的父类,
A< G >
是B< G >
的父类(多态)
通配符:
- 不能添加数据(null除外)
- 允许获取数据,返回类型为Object
?
的范围可以看成是负无穷到正无穷
限制条件的通配符:
< ? extends A >
:- extends可以看作是
<=
,即该泛型表示的范围为A类或A类的子类 - 该泛型读取数据可以用A类或A类的父类的对象接收
- 该泛型不能添加数据(负无穷到A类)
- extends可以看作是
< ? super A >
:- super可以看作是
>=
,即该泛型表示的范围为A类或A类的父类 - 该泛型读取数据只能用Object类的对象接收
- 该泛型可以添加A类或A类的子类的对象(A类到正无穷,可利用多态性)
- super可以看作是
File类
java.io
类的创建:
File(String filePath)
:相对路径下创建文件File(String parentPath,String childPath)
:绝对路径下创建文件File(File parentFile,String childPath)
:某文件的相对路径下创建文件
常用方法:
①public String getAbsolutePath()
:获取绝对路径
②public String getPath()
:获取路径
③public String getName()
:获取名称
④public String getParent()
:获取上层目录路径,若无,返回null
⑤public long length()
:获取文件长度(字节数)
⑥public long lastModified()
:获取最后一次修改时间(毫秒数)
⑦public String[] list()
:获取指定目录下所有文件或文件目录的名称数组
⑧public File[] listFiles()
:获取指定目录下所有文件或文件目录的File数组
⑨public boolean renameTo(File dest)
:将文件重命名为指定路径下的文件(当dest不存在,调用该方法的文件存在时,返回true)
⑩public boolean isDirectory()
:判断是否为文件目录
⑪public boolean isFile()
:判断是否是文件
⑫public boolean exists()
:判断是否存在
⑬public boolean canRead()
:判断是否可读
⑭public boolean canWrite()
:判断是否可写
⑮public boolean isHidden()
:判断是否隐藏
⑯public boolean createNewFile()
:创建文件,若存在,返回false
⑰public boolean delete()
:删除文件或文件夹
⑱public boolean mkdir()
:创建文件目录,若上层文件不存在,不创建
⑲public boolean mkdirs()
:创建文件目录,若上层文件不存在,一并创建
input
:读取外部数据到内存中
output
:将内存数据输出到存储设备中
流的分类:
-
按 *** 作数据单位:
1)字节流(8b):存储二进制数
2)字符流(16b):存储字符
-
按数据流向:
1)输入流
2)输出流
-
按流的角色:
1)节点流:链接内存和数据的通道
2)处理流:处理节点流
抽象基类:
- 字节流、输入流:
InputStream
- 字节流、输出流:
OutputStream
- 字符流、输入流:
Reader
- 字符流、输出流:
Writer
节点流(文件流):
FileInputStream
FileOutputStream
FileReader
FileWriter
缓冲流(处理流之一):
BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter
转换流(处理流之一):
InputStreamReader
OutputStreamWriter
对象流(处理流之一):
ObjectOutputStream
ObjectInputStream
随机存取文件流:
RandomAccessFile
其他常用流:
ByteArrayOutputStream
:底层是一个byte[]
,会自动扩容,一般调用其对象的方法来存放数据(用来防止出现乱码),可直接调用其空参构造器,具有对应的Input流write(byte[],int,int)
:用来存放byte[]
toString
:用来将byte[]
转换为字符串
- 实例化File对象,指明要 *** 作的文件
- 提供具体的流的对象
- 通过流的对象调用方法进行数据的写入或读取
- 通过流的对象调用
close()
进行流的关闭
从文件中读取数据到内存:
- 读取的文件必须存在,否则会抛异常
read()
每次调用会返回一个int型,如果到达文件末尾,会返回-1read(Array[] arr)
:返回每次读取到arr数组里的元素个数,返回-1时表示到达文件末尾
从内存中写入数据到文件:
-
写入的数据可以不存在,会自动生成对应文件
-
调用
write(String)
:-
FileWriter(File,false)
或FileWriter(File)
:每次调用方法,会对原有文件进行覆盖(覆盖文件!) -
FileWriter(File,true)
:每次调用方法,会在原有的文件上进行内容添加(追加内容!)
-
flush()
:将缓冲区的数据写出
数据加密和解密:
- 在写出数据前,对数组的元素进行
^
*** 作, - 再次异或相同数值时进行解密
节点流:
-
字节流:
FileInputStream
-
用字节流处理文本文件有可能会出现乱码(字符编码集)
-
调用
read(Array[] arr)
时,调用的为字节数组
-
-
字符流:
FileRead
- 调用
read(Array[] arr)
时,调用的为字符数组
- 调用
缓冲流:
-
提高流的读写速度(内置缓冲区)
-
在关闭外层流时,内层流也会关闭
-
*** 作节点流
-
缓冲字节流两个新方法:
BufferedReader
:String readLine()
:每次读取一行字符串,不包括换行符,返回null表示文件末尾
BufferedWriter
:newLine()
:换行作用
转换流:
-
*** 作节点流
-
传递参数时可以指定编码集格式
-
属于字符流,参数为
stream
类型 -
解码格式取决于解码格式,否则会出现乱码
-
解码:字节、字节数组 ——> 字符数组、字符串
InputStreamReader
:将字节的输入流转换为字符的输入流 -
编码:字符数组、字符串 ——> 字节、字节数组
OutputStreamWriter
:将字符的输出流转换为字节的输出流
对象流:
- 用于存储和读取基本数据类型或对象的处理流。
- Output时需要手动调用
flush()
进行缓冲区的刷新 - 自定义类实现序列化:
- 需要实现接口:
Serializable
- 为自定义类提供一个
long
型全局常量:serialVersionUID
- 要求其内部的所有属性也必须可以序列化(基本数据类型默认可序列化)(被 static 、transient 修饰的成员不可序列化)
- 需要实现接口:
ObjectOutputStream
:序列化- 将内存中的对象保存到磁盘文件中或通过网络传输出去
ObjectInputStream
:反序列化- 将磁盘文件中的对象还原为内存中的对象
随机存取文件流:
- 直接继承于Object类,实现了DataInput和DataOutput接口,因此即属于输入流,也属于输出流
- 传递参数时需指明mode参数:
r
:只读的方式打开- 文件不存在会抛异常
rw
:打开用于读取和写入- 文件不存在会创建文件,存在则会对文件内容进行覆盖
- 两个方法:
long getFilePointer()
:获取文件记录指针的当前位置void seek(long pos)
:将文件记录指针定位到下标pos处
实例化InetAddress
(构造器被私有化):调用方法
getByname(String host)
:获取IP地址,host可为IP地址,也可为域名getLocalHost()
:获取本机IP地址
常用方法:
getHostName()
:获取IP域名getHostAddress()
:获取IP地址
TCP网络编程
客户端:
- 创建
Socket
对象,指明连接的服务端的IP以及端口号- 一般调用构造器
Socket(String IP,int port)
- 一般调用构造器
- 获取对象的流,进行对应的写出数据的 *** 作
- 一般调用
getOutputStream
方法来获取OutputStream
流
- 一般调用
- 关闭资源
服务端:
- 创建
ServerSocket
对象,指明端口号- 一般调用构造器
SeverSocket(int port)
- 一般调用构造器
- 调用对象的
accept()
方法,返回来自客户端的Socket
- 可通过
Socket
调用getInetAddress()
获取客户端IP
- 可通过
- 调用
Socket
的流的方法,进行数据读取 *** 作- 一般调用
getInputStream
方法来获取InputStream
流
- 一般调用
- 资源关闭
UDP网络编程
发送端:
- 创建
DatagramSocket
对象,用于发送数据 - 创建
DatagramPacket
对象,指明接收的数据以及端口号,用于包装数据 - 调用
DatagramSocket
对象的send()
,将DatagramPacket
对象作为其参数 - 关闭资源
接收端:
- 创建
DatagramSocket
对象,指明端口号,用于接收数据 - 创建
DatagramPacket
对象,指明接收的数据,用于获取数据 - 调用
DatagramSocket
对象的receive()
,将DatagramPacket
对象其作为参数 - 关闭资源
URL编程:
- 格式:协议+主机名+端口号+资源地址+参数列表
- 创建
URL
对象,通过对象调用其openConnection()
,并强转为对应的协议URLConnection
- 调用强转后的
URLConnection
对象的connect()
方法,建立连接 - 调用强转后的
URLConnection
对象的流的方法,进行数据的读入。 - 调用强转后的
URLConnection
对象的disconnect()
,关闭资源 - 常用的方法:
getProtocol()
:获取该URL的协议名getHost()
:获取该URL的主机名getPort()
:获取该URL的端口号getPath()
:获取该URL的文件路径getFile()
:获取该URL的文件名(端口号后全部)getQuery()
:获取该URL的查询名(参数列表)
三部曲
获取Class类的对象:
- 直接调用运行时类:
类名.class
- 创建运行时类的对象,通过该对象调用其
getClass()
- 调用Class的静态方法:
Class.forName(String classPath)
- classPath为运行时类的全类名(含有包名的类名)
- 使用类的加载器:
ClassLoader
获取对象:
-
newInstance()
:获取当前运行时类的对象-
内部调用了空参构造器,因此要求此空参构造器必须存在且权限不能过小
-
返回值为Object类型,若Class有使用泛型,则为对应类型
-
获取指定属性、方法、构造器
获取属性:
- 通过运行时类的对象调用
Field getDeclaredField(String name)
,获取指定的属性 - 通过返回的Field对象调用
setAccessible(true)
,打开对属性的访问权 - 可通过返回的Field对象调用
set(Object obj,Object field)
修改属性值- obj为运行时类的对象,field为要修改的值
- 可通过返回的Field对象调用
get(Object obj)
来获取当前属性的值- obj为运行时类的对象
获取方法:
- 通过运行时类的对象调用
Method getDeclaredMethod(String name,Class type...)
,获取指定的方法- name为方法名,type…为方法形参所对应的Class类的对象(
.class
)
- name为方法名,type…为方法形参所对应的Class类的对象(
- 通过返回的Method对象调用
setAccessible(true)
,打开对方法访问权 - 通过返回的Method对象调用
Object invoke(Object obj,type)
传递参数来实现方法的调用- obj为运行时类的对象,type为传递给方法的参数,返回值为对应方法的返回值
- 若是静态方法,obj可以为Class类的实例,也可以为null
获取构造器:
- 通过运行时类的对象调用
Constructor getDeclaredConstructor(Class type...)
获取指定构造器 - 通过返回的Constructor对象调用
setAccessible(true)
,打开对构造器的访问权 - 通过返回的Constructor对象调用
Object newInstance(type)
创建对象
代理模式:
- 被代理类和代理类共同实现一个接口,被代理类将需要被代理的内容写入实现方法里
- 创建代理类和被代理类对象,将被代理类对象作为参数传给代理类构造器
- 代理类拥有一个接口类型的属性(多态),该属性存放的实质上是被代理类对象,代理类需要提供一个构造器来初始化该属性的值
- 在调用代理类的实现方法时,可以通过代理类的属性调用被代理类所重写的方法
- 这种在代理类里实现被代理类的内容的模式,即为代理模式
动态代理:
- 提供一个接口,并让被代理类实现接口
- 创建一个动态代理类,提供一个获取该类的对象的方法
- 该方法需要将被代理类作为形参,被代理类类型不能确定,所有应为形参类型应为Object
- 该方法需要返回动态代理类的对象,代理类对象类型根据被代理类而定,因此应声明为Object
- 使用
Object Proxy.newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)
来获取动态代理类的对象- loader是和形参(被代理类)相同的类加载器
- interfaces是和形参相同的实现接口
- h是InvocationHandler接口实现类的对象,因此需要实现该接口并提供一个实现类的对象
- 实现
InvocationHandler
接口,并实现其对应方法public Object invoke(Object proxy, Method method, Object[] args)
(在调用h对象时,会自动调用该方法)- proxy为调用该方法(动态代理类)的对象,仅是自动调用该方法的要求
- method为通过代理类对象调用的方法,
- args为方法的参数
- 调用method的
Object invoke(Object,args)
,返回值即为method方法返回值- Object为调用该方法(被代理类)的对象,可通过一个属性,通过
InvocationHandle
构造器来初始化该属性为被代理类对象 - args为方法的参数
- Object为调用该方法(被代理类)的对象,可通过一个属性,通过
思路:
通过方法获取到动态代理类对象后,动态代理类对象调用和被代理类共同实现的接口的方法时,就会自动转到h对象所包含的invoke方法中,调用其method.invoke()
方法,从而实现了通过调用代理类的方法而实现被代理类的方法。由于全过程都没有确定代理类的真正类型,这就实现了动态代理的效果。
理解Class类:
- 当对字节码文件(.class)进行解释运行时,每个被加载到内存中的类,我们称之为运行时类,而运行时类,就作为Class类的对象
- 加载到内存中的运行时类会缓存一定的时间,在此期间获取到的该运行时类都为同一个
- 维度相同且同类型的数组共享一个Class类对象
- 接口、枚举、注解、void、基本数据类型,都有相应的Class类对象
Class类对象的不太常用的方法:
-> 获取属性、方法、构造器:
-
Field[] getFields()
Method[] getMethods()
Constructor[] getConstructors()
获取当前运行时类及父类(构造器除外)中声明为public的属性、方法、构造器
-
Field[] getDeclareFields()
Method[] getDeclareMethods()
Constructor[] getDeclareConstructors()
获取当前运行时类声明的所有属性、方法、构造器
-> 获取父类:
-
不带泛型:
Class getSuperclass()
-
带泛型:
Type getGenericSuperclass()
-> 获取父类的泛型:
- 调用
Type getGenericSuperclass()
- 将其返回值强转为
ParameterizedType
类型 - 调用强转后的
Type[] getActualTypeArguments()
-> 获取实现的接口:
Class[] getInterfaces()
-> 获取所在的包:
Package getPackage()
-> 获取声明的注解:
Annotation[] getAnnotations()
Arrays工具类
java.util.Arrays
①判断两数组是否相等:
Arrays.equals ( int[ ] a,int[ ] b )
- ()内为数组变量名
- 返回类型为boolean
②输出数组信息:
Arrays.toString ( int[ ] a )
- ()内为数组变量名
- 打印带[ ]
- 返回类型为String
③将指定值填充到数组中:
Arrays.fill ( int[ ] a,int val )
- ()内左边为数组变量名,右边为要填充的值
- 是将数组的所有值替换为要填充的值
- 返回类型为void
④对数组进行排序:
Arrays.sort ( int[ ] a )
- ()内是数组变量名
- 返回类型是void型
⑤对数组某个值二分查找:
Arrays.binarySearch ( int[ ] a,int key )
- ()内左边是数组变量名,右边是要查找的数
- 返回的是所查找的数的下标
- 返回负数说明查找的数不存在
- 二分查找的前提是数组必须有序
- 返回类型是int类型
①reverse(List)
:反转List集合中的元素顺序
②shuffle(List)
:对List集合中的元素进行随机排序
③sort(List)
:根据元素的自然排序对指定List集合中的元素进行升序排序
④sort(List,Comparator)
:根据Comparator指定的排列顺序对List集合中的元素进行排序
⑤swap(List,int,int)
:将指定的List集合中的两元素进行交换
⑥Object max(Collection)
:根据元素的自然排序,返回集合中的最大元素
⑦Object max(Collection,Comparator)
:根据Comparator指定的排列顺序,返回集合中的最大元素
⑧Object min(Collection)
:根据元素的自然排序,返回集合中的最小元素
⑨Object min(Collection,Comparator)
:根据Comparator指定的排列顺序,返回集合中的最小元素
⑩int frequency(Collection,Object)
:返回集合中指定元素出现的次数
⑪void copy(List dest,List src)
:将src中的内容复制到dest中(dest必须要有足够的空间存储)
⑫boolean replaceAll(List list,Object oldVal,Object newVal)
:将List中所有的oldVal替换为newVal
⑬synchronizedXxx()
:将指定集合包装为线程同步的集合(解决线程安全问题)
lambda表达式
(o1,o2) -> { 方法体 }
:函数式接口的实现方式- 只有一个抽象方法的接口即为函数式接口,可用注解
@FunctionalInterface
表示
- 只有一个抽象方法的接口即为函数式接口,可用注解
使用方式:
- lambda形参列表(->左边):
()
内为实现接口的实现方法的形参列表,其参数类型可以省略(类型推断),当形参列表只有一个参数时,其()
可以省略 - lambda体(->右边):
{}
内为实现接口的实现方法的方法体,但只有一条执行语句时,可以省略{}
(若有return
也必须省略)
- 用于防止空指针异常
常用方法:
Optional Optional.empty()
:创建内部value=null的Optional的对象
boolean isPresent()
:判断Optional对象的内部数据是否有数据
Optional.of(T t)
:封装数据t生成Optional对象,要求t非空
T get()
:获取Optional对象封装的数据
Optional.ofNullable(T t)
:封装数据t生成Optional对象,t可为空
T orElse(T c)
:获取Optional对象封装的数据,若数据为空,则返回c
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)