Java常用类

1、Object

Object类是所有类的父类,也就是说任何一个类在定义时如果没有明确地继承一个父类,那它就是Object类的子类,也就是说以下两种类定义的最终效果是完全相同的。

class Book{                                           class Book extends Object{

    
}                                                     }                                                

Object类提供无参构造方法 ,之所以提供这样的无参构造,是因为在子类对象实例化时都会默认调用父类中的无参构造方法,这样在定义类时即使没有明确定义父类为Object,读者也不会感觉代码的强制性要求。

方法说明
Object clone()创建与该对象的类相同的新对象
boolean equals(Object)比较两个对象是否相等。默认比较的是地址值。
void finalize()当垃圾回收器确定不存在对该对象的更多引用时,对象的圾回收器调用该方法
Class getClass()返回一个对象运行时的实例类(.class文件)
int hashCode()返回该对象的散列码值
void notify()激活等待在该对象的监视器上的一个线程
void notifyAll()激活等待在该对象的监视器上的全部线程
String toString()返回该对象的字符串表示,默认返回运行时类名+@+对象的hashCode的16进制数
void wait()在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待

注意:

  • 如果两个对象的哈希码值不同,那这两个对象一定不等;
  • 如果两个对象的哈希码值相同,不能确保这两个对象一定相等。
  • 克隆对象对应的类需要实现Cloneable接口,否则会报错:java.lang.CloneNotSupportedException

如何获取类的字节码文件对象?

  1. 类名.class 说明: JVM将使用类装载器, 将类装入内存(前提是:类还没有装入内存),不做类的初始化工作.返回Class的对象
  2. Class.forName(“类名字符串”) (注:类名字符串是包名+类名) 说明:装入类,并做类的静态初始化,返回Class的对象
  3. 实例对象.getClass() 说明:对类进行静态初始化、非静态初始化; 返回引用o运行时真正所指的对象(因为:子对象的引用可能会赋给父对象的引用变量中) 所属的类的Class的对象

常覆写Object类的3个方法:toString(),equals(Object obj),hashCode()

为什么notify(), wait()等函数定义在Object中,而不是Thread中?

Object中的wait(), notify()等函数,和synchronized一样,会对“对象的同步锁”进行操作。

wait() 会使“当前线程”等待,因为线程进入等待状态,所以线程应该释放它锁持有的“同步锁”,否则其它线程获取不到该“同步锁”而无法运行!
OK,线程调用wait()之后,会释放它锁持有的“同步锁”;而且,根据前面的介绍,我们知道:等待线程可以被notify()或notifyAll()唤醒。现在,请思考一个问题:notify()是依据什么唤醒等待线程的?或者说,wait()等待线程和notify()之间是通过什么关联起来的?答案是:依据“对象的同步锁”。

负责唤醒等待线程的那个线程(我们称为“唤醒线程”),它只有在获取“该对象的同步锁”(这里的同步锁必须和等待线程的同步锁是同一个),并且调用notify()或notifyAll()方法之后,才能唤醒等待线程。虽然,等待线程被唤醒;但是,它不能立刻执行,因为唤醒线程还持有“该对象的同步锁”。必须等到唤醒线程释放了“对象的同步锁”之后,等待线程才能获取到“对象的同步锁”进而继续运行。

总之,notify(), wait()依赖于“同步锁”,而“同步锁”是对象锁持有,并且每个对象有且仅有一个!这就是为什么notify(), wait()等函数定义在Object类,而不是Thread类中的原因。

2、String

表示的是字符串,字符串是常量(值定义了之后,不可修改)

字符串可以看成是多个字符的连接

String 类是不可变类,也就是String对象声明后,将不可修改

1)构造方法

String(): 创建一个空的字符串

String(byte[] bys):通过字节数组创建字符串

String(char[] chs):通过字符数组创建字符串

String(byte[] bys,int offset,int length):通过字节数组一部分创建字符串

String(char[] chs,int offset,int length):通过字符数组一部分创建字符串

String(String original):通过字符串常量值创建字符串

/*
     关于字符串常用构造方法
 */

public class StringTest02 {
    public static void main(String[] args) {

        String s1 = "abc";

        String s2 = new String("abc");

        byte[] bytes = {97,98,99,100};
        String s3 = new String(bytes);
        System.out.println(s3);   // abcd  String已经重写了Object中的toString

        String s4 = new String(bytes,1,2);
        System.out.println(s4);

        char[] c1 = {'我','是','中','国','人'};
        String s5 = new String(c1);
        System.out.println(s5);    // 我是中国人

        String s6 = new String(c1,2,2);
        System.out.println(s6);   // 中国
        
    }
}

2)成员方法

1》判断功能

equals(Object obj): 比较两个字符串是否相等

equalsIngnoreCase(Object obj):忽略大小写比较两个字符串是否相等

contains(String str): 是否包含指定字符串

startsWith(String str): 是否以指定的字符串开头

endWith(String str): 是否以指定的字符串结尾

isEmpty(): 是否为空,当且仅当length()为0时返回true

matches(String regex): 判断字符串是否匹配给定的正则表达式。

/*

 1、字符串一旦创建不可再改变。"hello"字符串对象一旦创建,不可再改变成"hello1"

 2、提升字符串的访问效率,在程序中使用了”缓存“技术。所以在java中所有使用”双引号“括起来的字符串都会在”字符串常量池“中创建一份。
 字符串常量池在方法区中被存储

 3、在程序执行过程中,如果程序用到某个字符串,例如"hello",那么程序会在字符串常量池中去搜索该字符串,如果没有找到则
   在字符串常量池中新建一个"hello"字符串,如果找到就直接拿过来用(字符串常量池是一个缓存区,为了提高访问字符串的效率)


 * 字符串做连接操作


 * 如果是两个变量进行连接,先开辟空间,再连接


 * 如果是两个常量进行连接,先连接,获取连接结构值。然后在常量池里面查找有没有这个结果值,如果有,直接给地址值;没有,开辟空间


 */


public class StringTest01 {

    public static void main(String[] args) {

        // 创建一个"hello"字符串对象,该对象的内存地址,让s1变量保存
        // s1 是一个引用,s1指向"hello"对象
        String s1 = "hello";  // 在字符串常量池中新建一个"hello"字符串对象,该对象不可变

        String s2 = "hello"; // 从字符串常量池中直接拿来用

        String s3 = "world";

        String s4 = "helloworld";

        // 该程序创建了3个对象,堆中两个,方法区常量池中各一个
        String s5 = new String("hello");

        System.out.println(s4 == s2 + s3);                 // false

        // 比较两个字符串相等,必须使用String类提供的equals方法
        System.out.println(s1 == s2);                  // true
        System.out.println(s1 == s5);                  // false
        System.out.println(s2.equals(s1));             // true
        System.out.println(s2.equals(s5));             // true

        System.out.println(s4 == "hello"+"world");        // true

        System.out.println(s4.equals("hello"+"world"));   // true

        System.out.println("====================");

        // 忽略大小写比较两个字符串是否相等
        System.out.println("abc".equalsIgnoreCase("ABC")); // true

        System.out.println("===================");

        // 是否以指定的字符串结尾
        System.out.println("HelloWorld.java".endsWith("java"));   // true
        System.out.println("HelloWorld.java".endsWith(".java"));   // true
        System.out.println("HelloWorld.java".endsWith("HelloWorld.java"));   // true
        System.out.println("HelloWorld.java".endsWith("java "));   // false


    }


}

2》获取功能
length(): 获取长度

charAt(int index): 获取指定索引位置处的字符

indexOf(int ch): 获取指定字符第一次出现的索引值(从0开始)

indexOf(int ch,int fromIndex): 获取从指定索引位置开始,获取指定字符第一次出现的索引值
indexOf(String s): 获取指定字符串第一次出现的索引值

indexOf(String s,int fromIndex): 获取从指定索引位置开始,获取指定字符串第一次出现的索引值

lastIndexOf(int ch): 获取指定字符最后一次出现的索引值

substring(int start): 从指定位置开始一直截取到末尾

substring(int start,int end): 截取[start,end-1]范围

public class StringTest03 {
    public static void main(String[] args) {

        // 1.char charAt(int index);
        String s1 = "我是王勇!";
        char c1 = s1.charAt(2);
        System.out.println(c1);   // 王

        // 2.int indexOf(String str);
        System.out.println("ahsjahdi".indexOf("ah"));   // 0

        // 3.int indexOf(String str,int fromIndex);
        System.out.println("javaeejavasejavaweb".indexOf("java",1)); // 6

        // 4.int lastIndexOf(String str);
        System.out.println("javaeejavasejavaweb".lastIndexOf("java"));  // 12

        // 5.int length();
        System.out.println("abc".length());  // 3

        // 6.String subString(int beginIndex);
        System.out.println("abcd".substring(1));  //bcd

        // 7.String subString(int beginIndex,int endIndex);
        System.out.println("abcd".substring(1,3));  //bc [1,3)
        
    }

}

3》转换功能

byte[] getBytes(): 将字符串转成字节数组

// byte[] getBytes();
byte[] bytes = "abc".getBytes();
for (int i = 0; i <bytes.length ; i++) {
    System.out.println(bytes[i]+" ");  // 换行的97 98 99
}

char[] toCharArray(): 将字符串转成字符数组

// char[] toCharArray();
char[] c2 = "我是琉璃酱".toCharArray();
for (int i = 0; i <c2.length ; i++) {
    System.out.println(c2[i]);  // 换行的 我 是 琉 璃 酱
}

static valueOf(char[] chs): 将char[]转成字符串

static valueOf(int num): 将int类型转成字符串

static valueOf(Object obj):将任意类型转成字符串

// String valueOf(Object obj);
Object o = null;
System.out.println(o); // 不会,因为并不是直接调用toString方法,其实是调用了String.valueOf(o),这个方法对空值处理了
System.out.println(String.valueOf(o)); // null
// System.out.println(o.toString());  // 会出现空指针

toLowerCase(): 转成小写

// 转换成小写
System.out.println("ABCDEF".toLowerCase());  // abcdef

toUpcase(): 转成大写

// 转换成大写
System.out.println("Abdcfg".toUpperCase());  // ABDCFG

concat(String str): 字符连接

4》其他功能
replace(char old,char new):将old字符替换成new字符

replace(String old,String new):将old字符串替换成new字符串

trim():去除两边空格

// String trim();
System.out.print("     a  bc d    ".trim());    // a  bc d

int compareTo(String s):字典比较,如果前面值小于后面值返回负数,否则

返回正数,先比较第一个元素,如果相等再比较第二个元素…返回元素之间的

差值;如果比较字符串有包含关系,返回的值是它们长度的差值int

compareToIgnoreCase(String s): 忽略大小写字典比较

StringreplaceAll(String regex, String replacement):使用给定的

replacement 替换此字符串所有匹配给定的正则表达式的子字符串。

// String replaceAll(Strin s1,String s2);
       System.out.println("javaeejavasejavaweb".replaceAll("java","mysql")); // mysqleemysqlsemysqlweb

String replaceFirst(String regex, Stringreplacement):使用给定的

replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。

String[] split(String regex): 根据给定正则表达式的匹配拆分此字符串。

        // String[] split(String regex);
        String myTime = "2020,08,13";
        String[] ymd = myTime.split(",");
        for (int i = 0; i <ymd.length ; i++) {
            System.out.println(ymd[i]);  // 换行的2020 08 13
        }

String[] split(String regex, int limit): 根据匹配给定的正则表达式来拆分此字符串。

3)编码表

编码表:由现实世界的字符和对应的数值组成的一张表

常见的有:
1)ASCII码:最高为是符号为,其他是数值位

2)ISO-8859-1:拉丁码表

3)BG2312:中文编码表

4)GBK:GB2312的升级版,1个汉字对应2个字节

5)GB18030:GBK的升级版

6)BIG-5:中文繁体编码表,俗称"大5码"

7)Unicode:国际标注码。所有字符都有两个字节表示
Java默认使用该编码表

8)UTF-8:万国码,一个汉字对应3个字节
tips:所有编码表都兼容ASCII码表

String中与字符集相关的方法

String(byte[] by,String charset):通过指定的字符集,将指定的字节数组转成字符串(解码)

byte[] getBytes(String charset):通过指定的字符集,将字符串转成字节数组(编码)

4)正则表达式

负责字符串的匹配处理(一般用于校验字符串格式,也可用于在一段文本中查找满足要求的内容)

^a{2}$ 表示两个a字符,等同于aa

规则

1)字符

x: x字符,a表a字符

\: 反斜线字符

\n: 换行符

\r: 回车符

2)字符类

3)预定义字符类

. : 表示任意字符

. : 表示’.'字符(前面加了一个转义字符)

\d: 表示数字字符,0-9

\w: 表示单词字符,[a-zA-Z_0-9]

4)边界匹配器

^: 表示行的开头

$: 表示行的结尾

\b: 表示单词的边界

例:^a{2}$ 表示两个a字符,等同于aa

5)数量词

? : 表示0次或者1次

*: 表示0次或者多次

+: 表示1次或者多次

{n}: 表示n次

{n,}: 表示至少n次

{n,m}:n~m次

3、StringBuilder类

线程不安全的可变字符序列

1)构造方法

StringBuilder():以默认容量创建空的StringBuilder对象

StringBuilder(int capacity):以指定容量创建空的StringBuilder对象

StringBuilder(String str):以指定的字符串创建StringBuilder对象

2)成员方法

获取功能

int capacity(): 获取容量

int length(): 获取长度

添加功能

append(int value): 追加。可以追加多种类型

insert(int offset,String s): 在指定的位置插入指定数据

删除功能

deleteCharAt(int index): 删除指定索引处的元素

delete(int start,int end): 删除[start,start-1]范围内的元素

替换功能

replace(int start,int end,String s):将[start,end-1]范围内的元素替换成指定字

符串

反转功能

reverse():元素反转

截取功能

String subString(int start): 截取指定位置一直到末尾

String subString(int start,int end): 截取[start,end-1]范围

3)String、StringBuilder和StringBuffer的区别?

String内容不可改变

StringBuilder和StringBuffer内容可变

StringBuilder是线程不安全的,不同步,效率高

StringBuffer是线程安全的,同步,效率低

示例1:StringBuffer

/*
   如果以后需要大量字符串的拼接操作,建议使用JDK中自带的:
        java.lang.StringBuffer
        java.lang.StringBuilder

   如何优化StringBuffer的性能?
      在创建StringBuffer的时候尽可能给定一个初始化容量
      最好减少底层数组扩容次数。预估计一下,给一个大一些的初始化容量
      关键点:给一个合适的初始化容量。可以提高程序的执行效率
 */

public class StringBufferTest {

    public static void main(String[] args) {

        // 创建一个初始化容量为16个byte[] 数组。(字符串缓冲区对象)
        StringBuffer stringBuffer = new StringBuffer();

        // 拼接字符串,以后拼接字符串统一调用 append() 方法。
        // append 是追加的意思。
        stringBuffer.append("a");
        stringBuffer.append("b");
        stringBuffer.append(3.14);
        stringBuffer.append(true);
        // append方法底层在进行追加的时候,如果byte数组满了,会自动扩容
        stringBuffer.append(100L);

        System.out.println(stringBuffer.toString());  // ab3.14true100

        // 指定初始化容量的StringBuffer对象(字符串缓冲区对象)
        StringBuffer sb = new StringBuffer(100);
        sb.append("hello");
        sb.append("world");
        sb.append("hello");
        sb.append("kitty");

        System.out.println(sb);  // helloworldhellokitty

    }


}

示例2:StringBuilder

/*

java.lang.StringBuilder
StringBuffer和StringBuilder的区别?
    StringBuffer中的方法都有synchronized关键字修饰,表示StringBuffer在多线程环境下运行是安全的
    StringBuilder中的方法都没有synchronized关键字修饰,表示StringBuilder在多线程环境下运行是不安全的

    StringBuffer 是线程安全的
    StringBuilder 是非线程安全的

 */

public class StringBuilderTest {

    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();
        sb.append(100);
        sb.append(true);
        sb.append("hello");
        sb.append("kitty");
        System.out.println(sb);   // 100truehellokitty
    }

}

4、Scanner

1)构造方法

Scanner(InputStream is)

构造一个文本扫描器,它生成的值是从指定的值输入流扫描的

System.in 是一个标准的输入流,属于InputStream

2)成员方法

boolean hasNext(): 是否有下一个数,有true,没有false

String next(): 获取下个数

int nextInt(): 获取下个int数据

String nextLine(): 获取一行数据

5、Math类

成员方法

abs(int a): 绝对值

ceil(double d): 向上取整

floor(double d): 向下取整

max(int a,int b): 最大值

pow(double a,double b): a的b次幂

random(): 随机数[0.0,1.0]

round(float f): 四舍五入

sqrt(double d): 算术平方根

6、Random类

1)构造方法

Random(): 以当前时间毫秒值作为种子,创建Random对象

Random(long seed): 以指定种子创建Random对象

2)成员方法

nextInt(): 生成1个int类型范围的随机数

nextInt(int n): 产生1个[0,n-1]范围内的随机数

生成0~n之间的数

①(int)Math.random()*(n+1)
②Random r = new Random();
r.nextInt(m)表示生成[0,m-1]之间的随机数,也就是说random.nextInt(m+1),将生成[0,m]之间的随机整数。
r.nextInt(n+1)
生成n~m之间的随机数
①n+(int)(Math.random()
(m+1-n));
②Random r = new Random();
r.nextInt(m+1-n)+n;

public class RandomTest01 {

    public static void main(String[] args) {

        // 创建随机对象
        Random random = new Random();

        // 随机产生一个int类型取值范围内的数字。
        int num1 = random.nextInt();

        System.out.println(num1);

        // 产生[0,100]之间的随机数,不能产生101.
        // nextInt 翻译为:下一个int类型的数据是101,表示只能取到100
        int num2 = random.nextInt(101);  // 不包括101
        System.out.println(num2);

    }

}

题目:编写程序,生成5个[0,100]不重复的随机数,重复的话重新生成

​ 最终生成的5个随机数放到数组中,要求数组中这5个随机数不重复

/*
编写程序,生成5个[0,100]不重复的随机数,重复的话重新生成
最终生成的5个随机数放到数组中,要求数组中这5个随机数不重复
 */

public class RandomTest02 {

    private static int[] a;
    private static int key;

    public static void main(String[] args) {
        // 创建random对象
        Random random = new Random();

        // 准备一个长度为5的一维数组。
        int[] a = new int[5];   // 默认都是0
        for (int i = 0; i < a.length ; i++) {
            a[i] = -1;
        }

        //  循环,生成随机数
        int index = 0;
        while(index < a.length){
            // 生成随机数
            int num = random.nextInt(101);
            // 判断a数组中有没有这个num
            // 如果没有这个num,就放进去。
            if(!contains(a,num)){
                a[index++] = num;
            }
        }

        // 遍历以上的数组
        for (int i = 0; i < a.length ; i++) {
            System.out.println(a[i]);
        }
    }

    /**
     * 单独编写一个方法,这个方法专门用来判断数组中是否包含某个元素
     * @param a   数组
     * @param key 元素
     * @return  true表示包含,false表示不包含
     */

    public static boolean contains(int[] a,int key){
        RandomTest02.a = a;
        RandomTest02.key = key;
        /*
        这个方案bug(排序出问题了)
        对数组进行升序
        Arrays.sort(arr);
        进行二分法查找
        二分法查找的结果 >= 0说明,这个元素找到了,找到了表示存在!
        return Arrays.binarySearch(arr,kry) >=0
         */

        for (int i = 0; i < a.length; i++){
            if(a[i] == key){
                // 条件成立了表示包含,返回true
                return true;
            }
        }
        //这个就表示不包含
        return false;
    }

}

7、Date类

表示特定的瞬间,精确到毫秒值

1)构造方法

Date(): 以当前时间毫秒值创建Date对象

Date(long time): 以指定的毫秒值创建Date对象

public static void main(String[] args) throws Exception{

    // 获取系统当前时间(精确到毫秒的系统当前时间)
    // 直接调用无参数构造方法就行
    Date nowTime = new Date();
    // java.lang.Date类的toString()方法已经被重写了
    // 输出的应该不是一个对象的内存地址,应该是一个日期字符串
    System.out.println(nowTime);   // Sun Aug 16 15:48:47 CST 2020
}

2)成员方法

getTime(): 获取Date对象的毫秒值

setTime(long time): 设置Data对象的毫秒值

/*
获取自1970年1月1日 00:00:00 000到当前系统时间的总毫秒数
 */
public class DateTest02 {

    public static void main(String[] args) {
        // 获取自1970年1月1日 00:00:00 000到当前系统时间的总毫秒数
        long nowTimeMillis = System.currentTimeMillis();
        System.out.println(nowTimeMillis);  // 1597566877825
    }

}

8、DateFormat

它是一个抽象类,用来格式化或者解析日期

格式化:Date————》String

解析:String————》Date

getDateInstance(int style,Locale loc): 获取日期格式器,该格式器具有给定的语言环境和给定的格式化风格

String format(Date date): 格式化

Date parse(String time): 解析

SimpleDateFormat的使用差不多

9、SimpleDateFormat

它是DateFormat的子类

1)构造方法

SimpleDateFormat(): 以默认模式创建对象

SimpleDateFormat(String pattern): 以指定模式创建对象

常用模式

yyyy: 年 MM:月 dd:日

HH: 时 mm:分 ss:秒

2)常成员方法

String format(Date date): 格式化

Date parse(String time): 解析

public class DateTest01 {

    public static void main(String[] args) throws Exception{

        // 日期可以格式化吗?
        // 将日期类型Date,按照指定的格式进行转换:Date -- 转换成具有一定的日期字符串-->String
        // SimpleDateFormat是java.text包下的。专门负责日期格式化的。
        /*
        yyyy    年(年是四位)
        MM      月(月是2位)
        dd      日
        HH      时
        mm      分
        ss      秒
        SSS     毫秒(毫秒三位,最高999.1000毫秒代表1秒)
         */
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        String nowTimeStr = sdf.format(nowTime);
        System.out.println(nowTimeStr);    // 2020-08-16 15:48:47

        // String --> Date
        String time = "2020-08-16 16:03:20 888";
        // 括号里面的格式不能随便写,要和日期字符串格式相同
        // 注意:字符串的日期格式和SimpleDateFormat 对象指定的日期格式要一致。不然会出现异常
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        Date dateTime = sdf2.parse(time);
        System.out.println(dateTime);

    }


}

10、Calendar类

日历类,用于获取或者操作日历字段(年月日)

该类是一个抽象类,不可以实例化

成员方法

static Calender getInstance():以默认时区和语言创建日历

int get(int field): 获取指定字段的日历值

set(int field,int value): 给指定的日历字段设置指定的值

set(int year,int month,int date):设置年月日

Date getTime(): 获取日历对象的日期

setTime(Date d): 设置日历对象的日期

add(int field,int amount):对指定的日历字段添加指定的值

11、System类

没有构造方法

成员方法

gc():运行垃圾回收处理机制(系统会在某个不确定的时间调用该方法)

会调用finalize(),进行垃圾回收

exit(int status):退出JVM,0表示非异常退出

currentTimeMills():获取当前时间毫秒值

arrayCopy(Object[] srcArr,int srcPos,Object[] desArr,int destPos,int len):数组复制

简单总结一下System类的相关属性和方法

System.out [out是System类的静态变量]

System.out.println() [println()方法不是System类的,是PrintStream类的方法]

12、BigInteger类

1)构造方法创建BigInteger对象

BigInteger(int num, Random rnd):获取随机大整数,范围: [0 ~ 2的num次方-1]

BigInteger(String val, int radix):获取指定进制的大整数
(字符串中的数字必须是整数、字符串中的数字必须要跟进制吻合,比如二进制中,那么只能写0和1,写其他的就报错。
BigInteger bd4 = new BigInteger(“123”,2);
System.out .println(bd4); // 报错)

BigInteger(String val):获取指定的大整数,通过字符串创建BigInteger对象
(字符串中必须是整数,否则会报错,像"1.1"或者"abc"这种都是会报错的)

2)静态方法创建BigInteger对象

public static BigInteger valueOf(long val) :能表示范围比较小,只能在1ong的取值 范围之内,如果超出1ong的范围就不行了(long的最大值为9223372036854775807
)。在内部对常用的数字:-16 ~ 16进行了优化。提前把-16 ~ 16先创建好BigInteger的对象,如果多次获取不会重新创建新的。(BigInteger bd5 = BigInteger.value0f(16);
BigInteger bd6 = BigInteger . value0f(16);
System.out.println( bd5 == bd6); // true,如果括号里换成17,输出结果就是false了

3)细节

  1. 如果BigInteger表示的数字没有超出long的范围,可以用静态方法获取。
  2. 如果BigInteger表示的超出long的范围,可以用构造方法获取。
  3. 对象一旦创建,BigInteger内部记录的值不能发生改变。
  4. 只要进行计算都会产生一个新的BigInteger对象。

4)成员方法

BigInteger add(BigInteger bi):加

BigInteger subtract(BigInteger bi):减

BigInteger multiply(BigInteger bi):乘

BigInteger divide(BigInteger bi):除(整数相除只保留整数部分)

BigInteger[] divideAndRemainder(BigInteger val):除,获取商和余数,数组的0索引表示商,1表示余数

boolean equals(Object x):比较是否相同(内部重写了equals方法,所以比较的是内容)

BigInteger pow( int exponent):次幂

BigInteger max/min(BigInteger val):返回较大值/较小值

int intValue(BigInteger val):转为int类型整数,超出范围数据有误

13、BigDecimal类

用于解决浮点型运算精度损失的问题。

BigDecimal 属于大数据,精度极高。不属于基本数据类型,属于java对象(引用数据类型)。这

是SUN提供的一个类,专门用在财务软件当中。

1)构造方法创建BigDecimal对象

public BigDecimal(double val):这种方式有可能是不精确的,所以不建议使用

public BigDecimal(String val):通过字符创建BigDecimal对象,建议使用

2)静态方法创建BigDecimal对象

public static BigDecimal value0f(double val):如果我们传递的是0~10之间的整数,包含0,包含10,那么方法会返回已经创建好的对象,不会重新new

3)细节

  1. 如果要表示的数字不大,没有超出double的取值范围,建议使用静态方法
  2. 如果要表示的数字比较大,超出了double的取值范围, 建议使用构造方法

4)成员方法

BigDecimal add(BigDecimal bi):加

BigDecimal subtract(BigDecimal bi):减

BigDecimal multiply(BigDecimal bi):乘

BigDecimal divide(BigDecimal bi):除(整数相除只保留整数部分)

BigDecimal divide(BigDecimal val,精确几位,舍入模式):除,例如divide(BigDecimal val,2,RoundingMode.HALF_UP),表示保留两位小数并四舍五入

public class BigDecimalTest {

    public static void main(String[] args) {
        // 这个100不是普通的100,是精度极高的100
        BigDecimal b1 = new BigDecimal(100);
        // 精度极高的200
        BigDecimal b2 = new BigDecimal(200);
        // 求和 不能直接b1+b2,必须调用方法
        BigDecimal b3 = b1.add(b2);
        System.out.println(b3);
        // 相除 调用方法
        BigDecimal b4 = b2.divide(b1);
        System.out.println(b4);
        // 通过静态方法获取对象
        BigDecimal bd6 = BigDecimal.value0f(10);
        BigDecimal bd7 = BigDecimal.value0f(10);
        System.out.println(bd6 == bd7);   // true,如果bd6和bd7括号里面是10.0,则输出结果为false

    }
}

14、包装类

即8种数据类型对应的包装类型,重点以java.lang.Integer为代表进行学习,其它的类型照葫芦画瓢就行。

基本数据类型包装类型
bytejava.lang.Byte(父类Number)
shortjava.lang.Short(父类Number)
intjava.lang.Integer(父类Number)
longjava.lang.Long(父类Number)
floatjava.lang.Float(父类Number)
doublejava.lang.Double(父类Number)
booleanjava.lang.Boolean(父类Object)
charjava.lang.Character(父类Object)

示例1:

public class IntegerTest01 {
    public static void main(String[] args) {

        // 123这个基本数据类型,进行构造方法的包装达到了:基本数据类型向引用类型的转换
        // 基本数据类型-(转换为)->引用数据类型(装箱)
        Integer i = new Integer(123); // 123

        // 将引用数据类型--(转换为)->基本数据类型
        float f = i.floatValue();
        System.out.println(f);  // 123.0

        // 将引用数据类型--(转换为)->基本数据类型(拆箱)
        int intValue = i.intValue();
        System.out.println(intValue);  // 123

    }
}

八种包装类中其中6个都是数宇对应的包装类,他们的父类都是Number,可以先

研究一TNumber 中公共的方法:

Number是一个抽象类,无法实例化对象。

Number类中有这样的方法:

​ byte byteValue() 以byte形式返回指定的数值。

​ abstract double doubleValue() 以 double形式返回指定的数值。

​ abstract float floatValue() 以 float 形式返回指定的数值。

​ abstract int intValue() 以 int形式返回指定的数值。

​ abstract long longValue() 以 long形式返回指定的数值。

​ short shortValue() 以 short形式返回指定的数值。

这些方法其实所有的数字包装类的子类都有,这些方法是负责拆箱的。

Integer类的构造方法(已过时)

Integer(int)

Integer(String)

示例:

public class IntegerTest02 {
    public static void main(String[] args) {

        // Java9之后不建议使用这个构造方法了。出现横线表示已过时
        // 将数字100转换成Integer包装类型(int --> Integer)
        Integer x = new Integer(100);    // 100
        System.out.println(x);

        // 将String类型的数字,转换成Integer包装类型。(String --> Integer)
        Integer y = new Integer("123");     // 123
        System.out.println(y);

        // double --> Double
        Double d = new Double(1.23);
        System.out.println(d);

        // String --> Double
        Double e = new Double("3.14");
        System.out.println(e);

    }
}

通过访问包装类的常量,来获取最大值和最小值

public class IntegerTest03 {
    public static void main(String[] args) {

        // 通过访问包装类的常量,来获取最大值和最小值
        System.out.println("int的最大值" + Integer.MAX_VALUE);
        System.out.println("int的最小值" + Integer.MIN_VALUE);
        System.out.println("byte的最大值" + Byte.MAX_VALUE);
        System.out.println("byte的最小值" + Byte.MIN_VALUE);
    }

}

经典题目:

  1. 面试题:String为什么是不可变的?

    我看过源代码, String类中有一个byte[]数组 ,这个byte[]数组采用了final修

    饰,因为数组一旦创建长度不可变。并且被final修饰的引用且指向某个对象之后,不可再指向其它对象,所以lstring是不可变的!

    ​ "abc"无法变成"abcd”

  2. StringBuilder/StringBuffer为什么是可变的呢?

    我看过源代码, StringBuffer/StringBuilder内部实际上是一个byte[]数組 ,

    这个byte[]数组没有被final修饰, StringBuffer/StringBuilder的初始化

    容量我记得应该是16 ,当存满之后会进行扩容,底层调用了数組拷贝的方法

    Sys tem. arrgycopy()…是这样扩容的。所以StringBuilder/StringBuffer

    适合于使用宇符串的频繁拼接操作。

自动装箱和自动拆箱

  • 自动装箱:基本数据类型自动转换成包装类。
  • 自动拆箱:包装类自动转换成基本数据类型。
public class InterTest04 {
    public static void main(String[] args) {

        Integer a = 128;
        Integer b = 128;
        System.out.println(a == b);   // false
        
        /*
        java中为]掘高程序的执行效學,糊[-128到127]之间所有的包装对象捏前创建好
        放到了一个方法区的“整数型常量池”当中了, 目的是只要用这个区间的数据不需要
        再new了,直接从整数型常量池当中取出来。
        
        原理:x变量中保存的对象的内存地址称y变量中保存的时象的内存地址是一样的。
         */

        Integer x = 127;
        Integer y = 127;
        // == 永远判断的都是两个对象的内存地址是否相同
        System.out.println(x == y);  // true

    }
}

15、enum枚举类型

  1. 枚举是一种引用数据类型

  2. 枚举类型的定义格式:

    enum 枚举类型名{
        枚举值1,枚举值2...
    }
    
  3. 结果只有两种情况的,建议使用布尔类型

    结果超过两种并且还是可以一枚一枚列举出来的,建议使用枚举类型。

    ​ 例如:颜色、四季、星期等都可以使用枚举类型。

示例:计算两个int类型数据的商

import java.util.Random;

public class enumTest01 {

    public static void main(String[] args) {

        // 创建Random对象
        Random random = new Random();

        // 准备一个长度为5的一维数组
        int[] a = new int[5];  // 默认值都是0
        for (int i = 0; i < a.length ; i++) {
            a[i] = -1;
        }

        // 循环,生成随机数
        int index = 0;
        while(index < a.length){
            // 生成随机数
            int num = random.nextInt(101);
            // 判断a数组中有没有这个num
            // 如果没有这个num,就放进去。
            if(!contains(a,num)){
                a[index++] = num;
            }
        }

        // 遍历以上的数组
        for (int i = 0; i < a.length; i++) {
            System.out.println(a[i]);
        }

    }


    /**
     * 单独编写一个方法,这个方法专门用来判断数组中是否包含某个元素
     * @param a
     * @param key
     * @return true表示包含,false表示不包含
     */
    public static boolean contains(int[] a,int key){
        /*
        // 这个方案bug。(排序出问题了)
        // 对数组进行升序
        Arrays.sort(a);
        // 进行二分法查找
        // 二分法查找的结果 >= 0 说明,这个元素找到了,找到了表示存在!
        return Arrays.binarySearch(a,key) >= 0;
        */
        for (int i = 0; i < a.length; i++) {
            if(a[i] == key){
                // 条件成立了表示包含,返回true
                return true;
            }
        }
        // 这个就表示不包含!
        return false;
    }

}

思考:以上的这个方法设计没毛病,挺好,返回true和false表示两种情况,但是在以后的开发中,有可能遇到一个方法·的执行结果可能包括三种情况,四种情况,五种情况不等,但是每一个都是可以数清楚的,一枚一枚都是可以列举出来的。这个布尔类型就无法满足需求了。此时需要使用Java语言中的枚举类型。

// 采用枚举的方式改造程序
public class enumTest02 {

    public static void main(String[] args) {

        Result r = divide(10,0);
        System.out.println(r == Result.SUCCESS ?"计算成功":"计算失败");

    }

    /**
     * 计算两个int类型数据的商
     * @param a  int数据
     * @param b  int数据
     * @return   Result.SUCCESS表示成功,Result.FAIL表示失败!
     */
    public static Result divide(int a, int b){

        try {
            int c = a / b;
            return Result.SUCCESS;
        } catch (Exception e) {
            return Result.FAIL;
        }

    }

    // 枚举:一枚一枚可以列举出来的,才建议使用枚举类型
    // 枚举编译之后也是生成class文件
    // 枚举也是一种引用数据类型
    // 枚举中的每一个值可以看做是常量
    enum Result{
        // SUCCESS 是枚举Result类型中的一个值
        // FAIL 是枚举Result类型中的一个值
        // 枚举中的每一个值可以看做是常量
        SUCCESS,FAIL
    }

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值