03-Java核心类库_常用类库

200 阅读14分钟

一,常用类库

1,泛型

1.1 概述

1,泛型,即“参数化类型”。就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定 义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。

2,注意

在编译之后程序会采取去泛型化的措施。

  • 也就是说Java中的泛型,只在编译阶段有效。
  • 在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦出,并且在对象进入和离开方法的边界处添加 类型检查和类型转换的方法。也就是说,泛型信息不会进入到运行时阶段

3,作用

  • 1、 提高代码复用率
  • 2、 泛型中的类型在使用时指定,不需要强制类型转换(类型安全,编译器会检查类型)

1.2 使用

1,泛型类

public class ClassName<T>{ 
    private T data; 
    public T getData() { 
        return data; 
    }
    public void setData(T data) { 
        this.data = data; 
    } 
}

2,泛型接口

public interface IntercaceName<T>{ 
    T getData(); 
}

实现接口时,可以选择指定泛型类型,也可以选择不指定, 如下:
指定类型:

public class Interface1 implements IntercaceName<String> { 
    private String text; 
    @Override 
    public String getData() { 
        return text; 
    } 
} 

不指定类型:

public class Interface1<T> implements IntercaceName<T> { 
    private T data; 
    @Override 
    public T getData() { 
        return data; 
    } 
}

3, 泛型方法

方法的类型是泛型,返回值也是泛型

private static <T> T 方法名(T a, T b) {}

另一个例子

1.3 实例

1,假设在定义时不确定类型,但使用时可以确定:

2,测试方法

1.4 限制泛型类型

在使用泛型时, 可以指定泛型的限定区域 ,

- 例如: 必须是某某类的子类或 某某接口的实现类,格式:

<T extends 类或接口1 & 接口2>

1.5 泛型中的通配符

类型通配符是使用?代替方法具体的类型实参。

  • 1 <? extends Parent> 指定了泛型类型的上届
  • 2 <? super Child> 指定了泛型类型的下届
  • 3 <?> 指定了没有限制的泛型类型

上界限定(限定父类)

下界确定

2,java.util.Objects

2.1 Object与Objects

1,Object

2,Objects

2.2 Objects中的equals

1,使用对象的equals方法

2,使用Objects中的equals方法

3,源码

2.3 Objects中的requireNonNull

判断对象是否为空,若为空则抛出异常 。常用于要求对象不能为空的场景:

3,java.lang.Math

4,java.util.Arrays

4.1 二分查找binarySearch

1,相关API

2,应用

4.2 比较两个数组compare

4.3 复制数组copyOf、copyOfRange

1,相关API

2,应用

4.4 判断数组是否相等equals

4.5 填充数组fill

4.6 数组排序sort、parallelSort

1,相关API

2,应用

4.7 数组转换为字符串形式toString

1,相关部分API

2,应用

3,源码

5,java.math.BigDecimal

5.1 问题引入

1,输出两个小数之和

通过在控制台运行0.1+0.2。 会发现float和double的运算误差

由于float类型和doub1 e类型在运算时可能会有误差,为了实现精确运算则需要借助java.math. BigDecima 类加以描述

5.2 常用方法及使用

1,需要通过BigDecimal创建对象,相要参与运算的小数的字符串形式作为参数。

2,常用方法

3,转换为特定类型

6,java.util.Date

6.1 概念

在JDK 1.1之前, Date类还有两个附加功能。 它允许将日期解释为年,月,日,小时,分钟和秒值。 它还允许格式化和解析日期字符串。 不幸的是,这些功能的API不适合国际化。 从JDK 1.1开始, Calendar类应该用于在日期和时间字段之间进行转换,而DateFormat类应该用于格式化和解析日期字符串。 不推荐使用Date中的相应方法。

目前常用的方法:

1,当前时间

2,指定时间

3,获取时间戳

6.2 应用

1,打印当前时间

2,打印提前一小时的时间

7,java.text.DateFormat

7.1 概念

用于格式化和解析字符串。DateFormat是一个抽象类,经常使用他的直接子类SimpleDateFormat

7.2 应用

1, 格式定义。将时间转换为指定格式

2,使用方法format转换为想要的格式

3,使用方法parse 将指定格式的时间字符串转换为date对象

4,计算时间差

8,java.util.Calendar

可以解决国际化的问题。Calendar为抽象类,需要通过getInstance获得对象;

8.1 对象创建过程源码解析

1,创建calendar对象,进入Calendar类,找到getInstance方法

2,再次进入createCalendar方法

3,可以看到标准化操作,不同地区的创建方法

8.2 如何获取年月日时分秒:get(不能通过getDay之类的方法直接得到)

1,找到Calendar类中的fields数组,存放年月日时分秒相关的信息

2,这些常量表示相应字段在数组中的下标

3,实际使用运行效果

4,调用过程:get-》internalGet

8.3 如何获得今天是一年中的第几天:get

1,使用get方法,并传入相应参数

2,运行效果

8.4 如何设置日历来方便计算:set

1,使用set方法

8.5 通过加减修改年月日等参数:add

1,增加年份add

2,增加月份

注意国外月份0-11表示1-12.此外国外的星期日表示一周的开始

8.6 将Calendar对象转换为Date对象:getTime

8.7 获得字段的最大值:getActualMaxmum

9,String

String类表示字符串。 Java程序中的所有字符串文字(例如"abc" )都实现为此类的实例。

  • 字符串是不变的; 它们的值在创建后无法更改。
  • 字符串缓冲区支持可变字符串。
  • 因为String对象是不可变的,所以可以共享它们。(如果两字符串内容完全相同,则采用同一块内存地址)

之前的操作中,可以发现,使用String可以表示出一个字符串,但是使用此类的时候也会发现有一点的问题。

从String命名风格可以发现,String 是一一个类, 但是此类在使用的时候却发现可以不用构造方法而直接赋值,那么这样操作有那些特点呢?

9.1 为什么字符串类型无法更改长度

数组的长度无法更改

9.3 String对象可共享

如果两字符串内容完全相同,则采用同一块内存地址(前提是不通过new实现,只要使用了new就一定会开辟两个不同的内存空间)

9.4 字符串常量池

1,方法区

方法区(Method Area),又称永久代(Permanent Generation)(永久存储在内存中,就像静态代码块不会执行两次一样), 又称非堆区( Non-Heap space)方法区,又称永久代(Permanent Generation) ,常称为PermGen,位于非堆空间,又称非堆区(Non-Heap space)。

方法区是被所有线程共享。

  • 所有字段和方法字节码,以及一些特殊方法如构造函数,接口代码也在此定义。
  • 简单说,所有定义的方法的信息都保存在该区域,此区属于共享区间。
  • 这些区域存储的是:静态变量 +常量+类信息(构造方法/接口定义) +运行时常量池。

但是,实例变量 存在堆内存中,和方法区无关。

以上,只是逻辑上的定义。在HotSpot中,方法区仅仅只是逻辑上的独立,实际上还是包含在Java堆中,也是就说,方式区在物理上属于Java堆区中的一部分,而永久区(Permanent Generation) 就是方法区的实现。

2、堆(heap)

一个JW实例只存在一一个堆内存,堆内存的大小是可以调节的。类加载器读取了类文件后,需要把类、方法、常变量放到堆内
存中,保存所有引用类型的真实信息,以方便执行器执行。

堆在逻辑上分为三部分(Perm) :

  • 新生代(Young Generation, 常称为YoungGen)
  • 老年代(01d Generation, 常称为oldGen、TenuringGen)
  • 永久代(Permanent Generation, 常称为PermGen)

2.1、新生区(New/Young Generation)

新创建的对象都在新生代,在15次GC回收中被回收,就是新生代

  • 新生代(Young Generation) ,常称为YoungGen,位于堆空间;
  • 新生区又分为Eden区和Survior (幸存区)。

Eden :新创建的对象

Survior 0、1:经过垃圾回收,但是垃圾回收次数小于15次的对象

2.2、养老代(01d Generation)

  • 老年代(old Generation) ,常称为oldGen,位于堆空间;
  • old :垃圾回收次数超过15次,依然存活的对象

2.3、永久区(Permanent Generat ion)

字符串都存在于永久代,所以两个内容相同的字符串引用会指向同一地址(除了new出来的String,因为new一定会开辟新的内存空间)

永久代(Permanent Generation) , 常称为PermGen, 位于非堆空间。

永久区是一个常驻内存区域,用于存放JDK自身所携带的Class , Interface的元数据,也就是说它存储的是运行环境必须的类信息,被装载进此区域的数据是不会被垃圾回收器回收掉的,关闭JVM才会释放此区域所占用的内存。

2.3.1、方法区的实现的演变:

  • Jdk1.7之前: hotspot虚拟机对方法区的实现为永久代;
  • Jdk1. 8及之后: hotspot移除了永久代用元空间(Metaspace),

2.3.2、运行时常量池存和字符串常量池的变化

JDK1.7之前:

  • 运行时常量池(包含字符串常量池)存放在方法区,此时hotspot虚拟机对方法区的实现为永久代。

JDK1.7 :

  • 字符串常量池被从方法区拿到了堆中;
  • 运行时常量池剩下的东西还在方法区,也就是hotspot中的永久代。

JDK1.8 :

  • hotspot移除了永久代,用元空间(Metaspace)取而代之。这时候,
  • 字符串常量池还在堆,
  • 运行时常量池还在方法区,只不过方法区的实现从永久代变成元空间(Metaspace)。

9.5 被双引号包含的都是字符串对象

只要是被双引号包住的都是字符串对象,如果没有赋予名称的话,属于匿名对象

9.6 其他常用的字符串构造方法(最常用的还是直接赋值)

9.7 常用的字符串方法

9.8 字符串拼接中的问题

1,先声明三个字符串对象 text1,text2,text3

2,将三个字符串对象连接后新地址存放在text1中

3,造成的结果

4,实际应用场景中的副作用

爬虫时,把爬取到的字符串全都拼接起来,很快就会发现内存不够用,因为有很多垃圾在里面(拼接一次产生一次垃圾)。所以拼接字符串,能少做尽量少做,尤其是通过+号拼接;

5,如何拼接大量的字符串?

找到String实现的父类接口CharSequence。可以看到其的两个子类:StringBuffer,StringBuilder。

6,拼接方法

首先通过无参方式创建空的StringBuffer/StringBuilder;

其次通过append方式,进行添加,容量不够就根据动态扩容算法进行扩容。重点是不会在缓冲区存储,通过+号连接,因为是在常量缓冲池中存储,所以不会被回收;

7,将结果转换为String

8,虽然麻烦但是节省内存,所以对字符串操作时,推荐使用此方法

章节汇总在这里(づ ̄3 ̄)づ╭❤~@&再见萤火虫&【03-Java核心类库】

有问题欢迎提问,大家一起在学习Java的路上打怪升级!(o゜▽゜)o☆[BINGO!]