J a v a

J a v a,第1张

多线程
多线程的创建

①:继承于Thread类

  1. 创建一个继承于Thread类的子类

  2. 重写Thread类的run( )方法————>将此线程执行的 *** 作声明在run( )中

    public void run( ){ }

  3. 创建Thread类的子类的对象

  4. 通过此对象调用start( )(来自父类)

    • start的两个作用:1)启动当前线程 2)调用当前线程的run( )

​ 注意:

  • 直接通过对象调用run( )是单线程
  • 一个对象只能调用一次start( )
    • start( )会有个默认值,一旦执行过就不可再调用。
  • Thread也是重写了Runnable类中的run( )方法的。

②:实现Runnable接口(多线程共享数据)

导包:

import java.util.concurrent.Callable;

import java.util.concurrent.FutureTask;

  1. 创建一个实现Runnable接口的类

  2. 实现类去实现Runnable接口中的抽象方法run( )

  3. 创建实现类的对象

    只有一个实现类对象,被作为多个Thread类的参数时,可以实现多线程共享数据

  4. 将实现类的对象作为参数传递到Thread类的构造器中

  5. 通过Thread类的对象调用start( )

注意:

  • 该线程实现过程:

    • start( )调用了Thread类的对象所对应的run( ),而Thread类中的run( )实质是调用Thread类中的Runnable属性的变量的run( )。

    • 将实现了Runnable接口的类的对象作为参数传递给了Thread类中的构造器,构造器给其内的Runnable属性的变量赋值,再通过该Runnable属性的变量调用了其对应的run( )。


③:实现Callable接口

  1. 创建一个实现Callable接口的类

  2. 实现call( )—————>将线程需要执行的 *** 作声明在此内

    public Object call( ){ }

  3. 创建Callable接口实现类的对象

  4. 创建FutureTask类的对象前,将Callable接口实现类的对象传递给FutureTask类的构造器

  5. 将FutureTask类的对象作为参数传递给Thread类的构造器,通过Thread类的对象启用start( )

  6. (可选)若实现的call( )有返回值,可通过FutureTask类的对象调用get( )获取返回值

④:线程池

  1. 提供指定数量的线程池
  2. 执行指定的线程 *** 作(需要提供实现了Runnable接口或Callable接口的实现类的对象)
  3. 关闭线程池
Thread中常用的方法
  1. currentThread( )
    • 静态方法,放回执行当前代码的线程
  2. getName( )
    • 获取当前线程的名字
  3. getName( )
    • 获取当前线程的名字
    • Thread提供了相对应的构造器
  4. yield( )
    • 释放当前CPU的执行权
    • 释放后仍有可能是该线程继续执行
  5. join( )
    • 在线程a中调用线程b的join( ),此时线程a进入阻塞状态,直到线程b完全执行完后,才会结束线程a的阻塞状态
  6. stop( )
    • 当执行此方法时,强制结束当前线程
  7. sleep( x )
    • 让当前线程阻塞x毫秒
  8. isAlive( )
    • 判断当前线程是否存活
线程的优先级
  1. MAX_PRIORITY:10——————>最大线程
  2. MIN_PRIORITY:1——————>最小线程
  3. NORM_PRIORITY:5——————>默认线程

getPriority( ):获取线程优先级

setPriority( int p ):设置线程优先级

线程的安全问题

当一个线程 *** 作未结束,其他线程参与进来,就有可能会产生安全问题。

解决方法:

①同步代码块:

synchronized(同步监视器){ 需要被同步的代码 }

  • *** 作共享数据(多个线程同时 *** 作的变量)的代码,即为需要被同步的代码。
  • 同步监视器(锁):任何一个类的对象,都可以充当锁。
    • 注意:多个线程必须是共用一把锁。

②同步方法:

  • 同步方法仍然涉及同步监视器,只是没有显示的声明出来,根据是否为静态方法,同步监视器的对象也不同

1)非静态的同步方法:this

2)静态的同步方法:当前类本身(静态修饰的方法随类的加载而加载)

补充:

  1. 同步的方式解决了线程的安全问题,但 *** 作同步代码时,只能有一个线程参与,其他线程等待,此时就相当于是一个单线程的过程。

③Lock锁:

  1. 导包:import java.util.concurrent.locks.ReentrantLock

  2. 实例化 ReentrantLock类

  3. 调用锁定方法 lock( )

  4. 调用解锁方法 unlock( )

注意:

  • 需要手动的解锁
  • 锁也要保证是同一个锁
线程通信

涉及3个方法(只适用于同步代码块和同步方法中):

-> wait( ):一旦执行此方法,当前线程会进入阻塞状态,并释放同步监视器

-> notify( ):一旦执行此方法,会唤醒一个被wait( )的线程(以线程优先级决定)

-> notifyAll( ):一旦执行此方法,会唤醒所有被wait( )的线程

注意:

  • 三个方法的调用对象和同步监视器必须是一致的
  • 三个方法都声明在Object类中(为方便各类对象的调用)
总结

关于sleep( )和wait( )

相同点:

  1. 都可以使线程进入阻塞状态
  2. 都会抛出异常

不同点:

  1. sleep( )声明于Thread类,wait( )声明于Object类
  2. sleep( )可在任何需要的情况下调用,wait( )只能在同步代码块或同步方法中调用
  3. 若两者同时作用于同步代码块或同步方法中,sleep( )不会释放同步监视器,wait( )会释放同步监视器

关于Callable接口比Runnable接口创建多线程强大的原因

  1. call( )可以有返回值
  2. call( )可以抛出异常
  3. 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( ),则调用了该方法的字符串的返回值是存放在字符串常量池中的
String常用方法

注意:字符串的不可变性

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相关的转换

①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的常用方法

(增)①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(子类)

SimpleDateFormat

​ 实例化对象:使用不同的构造器(不同构造器解析格式不同)

  • 格式化:日期 —> 字符串
    • (返回String类型)对象名 . format( Date类型数据 )
  • 解析:字符串 —> 日期
    • (返回Date类型)对象名 . parse( 传对应字符串格式 )
Calendar日历类(抽象类)

​ 1)实例化:

  • 创建子类(GregorianCalendar)的对象
  • 调用Calendar . getInstance( )(静态方法)

​ 2)常用方法:

  • get( Calendar的静态属性 )
    • 获取特定时间
  • set( Calendar的静态属性 , 对应时间 )
    • 将Calendar的静态属性对应的时间替换为指定的时间(无返回值,在原有基础上修改)
  • getTime( ):日历类 —> Date
    • 将当前对象对应的日期转化为Date的日期格式
  • setTime( Date类型数据 ):Date —> 日历类
    • 将指定的Date类型数据转化为Calendar类型数据(无返回值,在原有基础上修改)

注意:月份从0开始,星期日是1

LocalDate、LocalTime、LocalDateTime

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,返回零
Comparator接口(定制排序)
  • 通常使用匿名对象的匿名类直接一次性使用

1、构建匿名对象的匿名类

2、重写compare(obj1,obj2)

public int compare(Object obj1,Object obj2)

  • 重写compare(obj1,obj2)的规则:
    • 如果obj1大于obj2,返回正整数
    • 如果obj1小于obj2,返回负整数
    • 如果obj1等于obj2,返回零
System类

java.lang包下

①(native long)currentTimeMillis()

  • 获取当前时间距离1970-01-01 00:00:00的毫秒数

②(void)exit( int status )

  • 退出程序,status值为0表示正常退出,非0表示异常退出

③(void)gc( )

  • 请求系统进行垃圾回收
Math类

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)

关于Comparable接口和Comparator接口的异同

-> 相同点:

​ ①都是用于对象的比较

​ ②一般都用于Arrays . sort( )中

​ ③在返回值前使用-表示按从大到小的顺序排列

-> 不同点:

​ Ⅰ、Comparable接口一般用类去实现,相当于一次定义,永久成型

​ Ⅱ、Comparator接口一般使用匿名对象的匿名子类方式(在调用Array . sort( )时传值)定义,采用一次性使用的方式

枚举类
  • 类的对象的个数有限、确定(类比单例模式)
  • 多用来定义一组常量

自定义枚举类:

  1. 声明对象的属性(private final)
  2. 私有化类的构造器,给对象属性赋初始值
  3. 提供当前枚举类的多个对象(public static final)

使用enum关键字定义枚举类:

默认继承于java.lang.Enum

  1. 创建当前枚举类的对象,多个对象间有,隔开,末尾用;结束(对象默认为 public static final 修饰)
    • 创建格式 ----> 对象名( 构造器参数 )
  2. 声明对象的属性(private final)
  3. 私有化类的构造器,给对象属性赋初始值

Enum类中的常用方法:

  1. values( ):返回枚举类型的对象数组,常用来遍历所有的枚举值
  2. valueOf( String objName ):返回枚举类中对象名为objName的对象
  3. toString( ):返回当前调用的对象的名称

enum类实现接口:

  1. 在enum类中实现接口的抽象方法
  2. 让枚举类的对象分别实现接口中的抽象方法
    • 创建格式 ----> 对象名( 构造器参数 ) { 重写的方法 }
注解(Annocation)

①生成文档相关的注解

②在编译时进行格式检查

  1. @Override:限定重写父类方法,只能用于方法
  2. @Deprecated:表示修饰的类或方法等已过时
  3. @SuppressWarnings:抑制编译器警告

③跟踪代码依赖性,实现替换配置文件功能

自定义注解:

  1. 声明为:@interface
  2. 定义内部成员(类似无参方法的属性)
  • 可以指定成员的默认值,在定义内部成员后用default定义
  • 有成员的话,在使用注解时,必须指明其成员的值
  • 没有成员时,表明是一个标识作用

元注解:对现有注解进行解释说明的注解

  1. Retention:指定所修饰的注解的生命周期:SOURCE、CLASS(默认)、RUNTIME(反射可用)
  2. Target:指明注解可被用于哪些元素
  3. Documented:使指定的注解在被JavaDoc解析时仍保留下来
  4. Inherited:使指定的注解具有继承性(可被子类使用)
集合
框架

(一)Collection接口:单列集合,存储一个一个的数据

​ ①List接口:存储有序、可重复的数据

  • 要求需要重写equals( )

动态数组

  1. ArrayList:List接口的主要实现类,线程不安全,效率高,底层使用Object[ ]存储
  2. LinkedList:对应频繁的插入、删除等 *** 作,效率比ArrayList高,底层使用双向链表存储
  3. Vector:List接口的古老实现类,线程安全,效率低,底层使用Object[ ]存储

​ ②Set接口:存储无序、不可重复的数据

  • 要求需要重写equals( )和hashCode( ),TreeSet类除外

无序:使用哈希值存储

不可重复:用哈希值存储,必要时使用equals进行判断

  1. HashSet:Set接口的主要实现类,线程不安全,可以存放null值,底层使用数组+链表存储

    ​ a.LinkedHashSet:作为HashSet的子类,遍历数据时,可以按照添加时的顺序遍历,对于频繁使用遍历 *** 作时,效率高于HashSet

  2. TreeSet:对添加对象的特定属性进行排序

    • 添加的数据要求是同类的对象
    • 排序方法本质是用到自然排序和定制排序
    • 底层是树型结构,因此不能存放相同数据

(二)Map接口:双列集合,存储一对一对(key - value)的数据

key:不可重复、无序的,使用Set存储,要求所在的类要重写equals( )和hashCode( ),TreeMap例外

values:可重复、无序的,使用Collection存储,要求所在的类要重写equals( )

一个key-values构成了一个Entry对象,无序的、不可重复的,使用Set存储

  1. HashMap:Map的主要实现类,线程不安全,可以存储null的key和value

    ​ a.LinkedHashMap:遍历元素时,可以按照添加是顺序遍历

  2. TreeMap:按照添加的key-value进行排序,按照key来进行排序

    • 要求key必须是同一个类型创建的对象
    • 排序方法本质是用到自然排序和定制排序
    • 底层是树型结构,因此不能存放相同数据
  3. Hashtable:古老实现类,线程安全,不能存储null的key和value

    ​ a.Properties:常用来处理配置文件,key和value都是String类型

底层实现原理:

计算key的哈希值,得到在Entry中的存储位置,判断是否有数据,有的话会比较存储位置上的数据的哈希值是否一样,如果一样,会调用equals方法进行比较,如果比较结果返回true,则会将原数据的values替换为新的key对应的values

Collection接口中的常用方法

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对象,指向第一个元素之前的位置
ArrayList类中常用的方法

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()

泛型

在集合中使用泛型:

  1. 实例化集合类时,可以指明具体的泛型类型,否则默认为Object类型
  2. 泛型的类型必须是类,不能是基本数据类型
  3. 静态方法不能使用类的泛型(静态方法的创建早于泛型的定义)
  4. 异常类不能声明为泛型

自定义泛型类:

  1. 在类声明处用< T >表明一个未知类型的泛型类
  2. 在类的内部定义一个类型为T的变量,此时该变量的T默认存放Object类型
  3. 在创建对象时表明T的具体类型后,此时的T就会对应指定的泛型
  4. 若子类继承该类时未表明T的类型,则也会默认为Object类型
  5. 子类也可以再声明多个泛型

自定义泛型方法:

  1. 泛型方法与该类是否为泛型类无关
  2. 声明的泛型类型与该类的泛型类型无关
  3. 泛型方法可以为静态方法
  4. 在返回类型前加< T >表明该方法是泛型方法,而非变量名

泛型在继承方面的体现:

  1. 类A是类B的父类,但G< A >G< B >两者间不具有子父类关系,但有共同的父类G< ? >,称为通配符
  2. 类A是类B的父类,A< G >B< G >的父类(多态)

通配符:

  1. 不能添加数据(null除外)
  2. 允许获取数据,返回类型为Object
  3. ?的范围可以看成是负无穷到正无穷

限制条件的通配符:

  1. < ? extends A >
    • extends可以看作是<=,即该泛型表示的范围为A类或A类的子类
    • 该泛型读取数据可以用A类或A类的父类的对象接收
    • 该泛型不能添加数据(负无穷到A类)
  2. < ? super A >
    • super可以看作是>=,即该泛型表示的范围为A类或A类的父类
    • 该泛型读取数据只能用Object类的对象接收
    • 该泛型可以添加A类或A类的子类的对象(A类到正无穷,可利用多态性)
IO流
File类

java.io

类的创建:

  1. File(String filePath):相对路径下创建文件
  2. File(String parentPath,String childPath):绝对路径下创建文件
  3. 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)处理流:处理节点流

抽象基类:

  1. 字节流、输入流:InputStream
  2. 字节流、输出流:OutputStream
  3. 字符流、输入流:Reader
  4. 字符流、输出流:Writer

节点流(文件流):

  1. FileInputStream
  2. FileOutputStream
  3. FileReader
  4. FileWriter

缓冲流(处理流之一):

  1. BufferedInputStream
  2. BufferedOutputStream
  3. BufferedReader
  4. BufferedWriter

转换流(处理流之一):

  1. InputStreamReader
  2. OutputStreamWriter

对象流(处理流之一):

  1. ObjectOutputStream
  2. ObjectInputStream

随机存取文件流:

  • RandomAccessFile

其他常用流:

  1. ByteArrayOutputStream:底层是一个byte[],会自动扩容,一般调用其对象的方法来存放数据(用来防止出现乱码),可直接调用其空参构造器,具有对应的Input流
    • write(byte[],int,int):用来存放byte[]
    • toString:用来将byte[]转换为字符串
流的 *** 作
  1. 实例化File对象,指明要 *** 作的文件
  2. 提供具体的流的对象
  3. 通过流的对象调用方法进行数据的写入或读取
  4. 通过流的对象调用close()进行流的关闭

从文件中读取数据到内存:

  • 读取的文件必须存在,否则会抛异常
  • read()每次调用会返回一个int型,如果到达文件末尾,会返回-1
  • read(Array[] arr):返回每次读取到arr数组里的元素个数,返回-1时表示到达文件末尾

从内存中写入数据到文件:

  1. 写入的数据可以不存在,会自动生成对应文件

  2. 调用write(String)

    • FileWriter(File,false)FileWriter(File):每次调用方法,会对原有文件进行覆盖(覆盖文件!)

    • FileWriter(File,true):每次调用方法,会在原有的文件上进行内容添加(追加内容!)

flush():将缓冲区的数据写出

数据加密和解密:

  • 在写出数据前,对数组的元素进行^ *** 作,
  • 再次异或相同数值时进行解密
流的特点

节点流:

  1. 字节流:FileInputStream

    • 用字节流处理文本文件有可能会出现乱码(字符编码集)

    • 调用read(Array[] arr)时,调用的为字节数组

  2. 字符流:FileRead

    • 调用read(Array[] arr)时,调用的为字符数组

缓冲流:

  • 提高流的读写速度(内置缓冲区)

  • 在关闭外层流时,内层流也会关闭

  • *** 作节点流

  • 缓冲字节流两个新方法:

    BufferedReader

    • String readLine():每次读取一行字符串,不包括换行符,返回null表示文件末尾

    BufferedWriter

    • newLine():换行作用

转换流:

  • *** 作节点流

  • 传递参数时可以指定编码集格式

  • 属于字符流,参数为stream类型

  • 解码格式取决于解码格式,否则会出现乱码

  • 解码:字节、字节数组 ——> 字符数组、字符串

    InputStreamReader:将字节的输入流转换为字符的输入流

  • 编码:字符数组、字符串 ——> 字节、字节数组

    OutputStreamWriter:将字符的输出流转换为字节的输出流

对象流:

  1. 用于存储和读取基本数据类型或对象的处理流。
  2. Output时需要手动调用flush()进行缓冲区的刷新
  3. 自定义类实现序列化:
    1. 需要实现接口:Serializable
    2. 为自定义类提供一个long型全局常量:serialVersionUID
    3. 要求其内部的所有属性也必须可以序列化(基本数据类型默认可序列化)(被 static 、transient 修饰的成员不可序列化)
  4. ObjectOutputStream:序列化
    • 将内存中的对象保存到磁盘文件中或通过网络传输出去
  5. ObjectInputStream:反序列化
    • 将磁盘文件中的对象还原为内存中的对象

随机存取文件流:

  1. 直接继承于Object类,实现了DataInput和DataOutput接口,因此即属于输入流,也属于输出流
  2. 传递参数时需指明mode参数:
    • r:只读的方式打开
      • 文件不存在会抛异常
    • rw:打开用于读取和写入
      • 文件不存在会创建文件,存在则会对文件内容进行覆盖
  3. 两个方法:
    1. long getFilePointer():获取文件记录指针的当前位置
    2. void seek(long pos):将文件记录指针定位到下标pos处
网络编程

实例化InetAddress(构造器被私有化):调用方法

  1. getByname(String host):获取IP地址,host可为IP地址,也可为域名
  2. getLocalHost():获取本机IP地址

常用方法:

  1. getHostName():获取IP域名
  2. getHostAddress():获取IP地址

TCP网络编程

客户端:

  1. 创建Socket对象,指明连接的服务端的IP以及端口号
    • 一般调用构造器Socket(String IP,int port)
  2. 获取对象的流,进行对应的写出数据的 *** 作
    • 一般调用getOutputStream方法来获取OutputStream
  3. 关闭资源

服务端:

  1. 创建ServerSocket对象,指明端口号
    • 一般调用构造器SeverSocket(int port)
  2. 调用对象的accept()方法,返回来自客户端的Socket
    • 可通过Socket调用getInetAddress()获取客户端IP
  3. 调用Socket的流的方法,进行数据读取 *** 作
    • 一般调用getInputStream方法来获取InputStream
  4. 资源关闭

UDP网络编程

发送端:

  1. 创建DatagramSocket对象,用于发送数据
  2. 创建DatagramPacket对象,指明接收的数据以及端口号,用于包装数据
  3. 调用DatagramSocket对象的send(),将DatagramPacket对象作为其参数
  4. 关闭资源

接收端:

  1. 创建DatagramSocket对象,指明端口号,用于接收数据
  2. 创建DatagramPacket对象,指明接收的数据,用于获取数据
  3. 调用DatagramSocket对象的receive(),将DatagramPacket对象其作为参数
  4. 关闭资源

URL编程:

  1. 格式:协议+主机名+端口号+资源地址+参数列表
  2. 创建URL对象,通过对象调用其openConnection(),并强转为对应的协议URLConnection
  3. 调用强转后的URLConnection对象的connect()方法,建立连接
  4. 调用强转后的URLConnection对象的流的方法,进行数据的读入。
  5. 调用强转后的URLConnection对象的disconnect(),关闭资源
  6. 常用的方法:
    • getProtocol():获取该URL的协议名
    • getHost():获取该URL的主机名
    • getPort():获取该URL的端口号
    • getPath():获取该URL的文件路径
    • getFile():获取该URL的文件名(端口号后全部)
    • getQuery():获取该URL的查询名(参数列表)
反射
三部曲

获取Class类的对象:

  1. 直接调用运行时类:类名.class
  2. 创建运行时类的对象,通过该对象调用其getClass()
  3. 调用Class的静态方法:Class.forName(String classPath)
    • classPath为运行时类的全类名(含有包名的类名)
  4. 使用类的加载器:ClassLoader

获取对象:

  • newInstance():获取当前运行时类的对象

    • 内部调用了空参构造器,因此要求此空参构造器必须存在且权限不能过小

    • 返回值为Object类型,若Class有使用泛型,则为对应类型

获取指定属性、方法、构造器

获取属性:

  1. 通过运行时类的对象调用Field getDeclaredField(String name),获取指定的属性
  2. 通过返回的Field对象调用setAccessible(true),打开对属性的访问权
  3. 可通过返回的Field对象调用set(Object obj,Object field)修改属性值
    • obj为运行时类的对象,field为要修改的值
  4. 可通过返回的Field对象调用get(Object obj)来获取当前属性的值
    • obj为运行时类的对象

获取方法:

  1. 通过运行时类的对象调用Method getDeclaredMethod(String name,Class type...),获取指定的方法
    • name为方法名,type…为方法形参所对应的Class类的对象(.class
  2. 通过返回的Method对象调用setAccessible(true),打开对方法访问权
  3. 通过返回的Method对象调用Object invoke(Object obj,type)传递参数来实现方法的调用
    • obj为运行时类的对象,type为传递给方法的参数,返回值为对应方法的返回值
    • 若是静态方法,obj可以为Class类的实例,也可以为null

获取构造器:

  1. 通过运行时类的对象调用Constructor getDeclaredConstructor(Class type...)获取指定构造器
  2. 通过返回的Constructor对象调用setAccessible(true),打开对构造器的访问权
  3. 通过返回的Constructor对象调用Object newInstance(type)创建对象
动态代理

代理模式:

  1. 被代理类和代理类共同实现一个接口,被代理类将需要被代理的内容写入实现方法里
  2. 创建代理类和被代理类对象,将被代理类对象作为参数传给代理类构造器
  3. 代理类拥有一个接口类型的属性(多态),该属性存放的实质上是被代理类对象,代理类需要提供一个构造器来初始化该属性的值
  4. 在调用代理类的实现方法时,可以通过代理类的属性调用被代理类所重写的方法
  5. 这种在代理类里实现被代理类的内容的模式,即为代理模式

动态代理:

  1. 提供一个接口,并让被代理类实现接口
  2. 创建一个动态代理类,提供一个获取该类的对象的方法
    • 该方法需要将被代理类作为形参,被代理类类型不能确定,所有应为形参类型应为Object
    • 该方法需要返回动态代理类的对象,代理类对象类型根据被代理类而定,因此应声明为Object
    • 使用Object Proxy.newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)来获取动态代理类的对象
      • loader是和形参(被代理类)相同的类加载器
      • interfaces是和形参相同的实现接口
      • h是InvocationHandler接口实现类的对象,因此需要实现该接口并提供一个实现类的对象
  3. 实现InvocationHandler接口,并实现其对应方法public Object invoke(Object proxy, Method method, Object[] args)(在调用h对象时,会自动调用该方法)
    • proxy为调用该方法(动态代理类)的对象,仅是自动调用该方法的要求
    • method为通过代理类对象调用的方法,
    • args为方法的参数
  4. 调用method的Object invoke(Object,args),返回值即为method方法返回值
    • Object为调用该方法(被代理类)的对象,可通过一个属性,通过InvocationHandle构造器来初始化该属性为被代理类对象
    • args为方法的参数

思路:

通过方法获取到动态代理类对象后,动态代理类对象调用和被代理类共同实现的接口的方法时,就会自动转到h对象所包含的invoke方法中,调用其method.invoke()方法,从而实现了通过调用代理类的方法而实现被代理类的方法。由于全过程都没有确定代理类的真正类型,这就实现了动态代理的效果。

总结

理解Class类:

  • 当对字节码文件(.class)进行解释运行时,每个被加载到内存中的类,我们称之为运行时类,而运行时类,就作为Class类的对象
  • 加载到内存中的运行时类会缓存一定的时间,在此期间获取到的该运行时类都为同一个
  • 维度相同且同类型的数组共享一个Class类对象
  • 接口、枚举、注解、void、基本数据类型,都有相应的Class类对象

Class类对象的不太常用的方法:

-> 获取属性、方法、构造器:

  1. Field[] getFields()

    Method[] getMethods()

    Constructor[] getConstructors()

    获取当前运行时类及父类(构造器除外)中声明为public的属性、方法、构造器

  2. Field[] getDeclareFields()

    Method[] getDeclareMethods()

    Constructor[] getDeclareConstructors()

    获取当前运行时类声明的所有属性、方法、构造器

-> 获取父类:

  • 不带泛型:Class getSuperclass()

  • 带泛型:Type getGenericSuperclass()

-> 获取父类的泛型:

  1. 调用Type getGenericSuperclass()
  2. 将其返回值强转为ParameterizedType类型
  3. 调用强转后的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类型
Collections工具类

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():将指定集合包装为线程同步的集合(解决线程安全问题)

JDK8 新特性
lambda表达式
  • (o1,o2) -> { 方法体 }:函数式接口的实现方式
    • 只有一个抽象方法的接口即为函数式接口,可用注解@FunctionalInterface表示

使用方式:

  1. lambda形参列表(->左边):()内为实现接口的实现方法的形参列表,其参数类型可以省略(类型推断),当形参列表只有一个参数时,其()可以省略
  2. lambda体(->右边):{}内为实现接口的实现方法的方法体,但只有一条执行语句时,可以省略{}(若有return也必须省略)
Optional
  • 用于防止空指针异常

常用方法:

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

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/923745.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-16
下一篇 2022-05-16

发表评论

登录后才能评论

评论列表(0条)

保存