Java笔记六——Java核心类

字符串和编码

String

String是引用类型,它也是一个class,"…"表示一个字符串
String s = "Hello!";
String内部是通过一个char[ ]数组表示的
String s = new String(new char[ ]{‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘!’} );`

字符串比较

比较字符串内容是否相同,必须用equal()方法而不能用==。
Java字符串具有不可变性,字符串生成后就存放在常量池中,引用的指向可以改变,但是字符串内容不可变

String s1 = "hello";//s1指向“hello”
String s2 = "hello";//s2指向“hello”
String s3 = "HELLO".toLowerCase();//创建新对象“HELLO”
System.out.println(s1==s2);//true,因为s1、s2都指向hello这同一个对象
System.out.println(s1==s3);//false,s1、s3的引用不同
System.out.println(s1.equals(s3));//true,字符串内容相同

String类常用方法

搜索子串

"Hello".contains("ll");//true,注意contains()方法的参数是CharSequence,是String的父类
"Hello".indexOf("l");//2,返回子串第一次出现的位置
"Hello".lastIndexOf("l");//3,返回子串最后一次出现的位置
"Hello".startsWith("He");//true,判断字符串是否以"..."开头
"Hello".endsWith("lo");//true,判断字符串是否以"..."结尾

提取子串

"Hello".substring(2);//"llo"
"Hello".substring(2,4);//"ll",提取到4-1=3那个字符

去除首尾空白字符

*下面这些方法返回的是新字符串,旧字符串还在常量池里,字符串内容具有不变性 *
trim()方法可以移除字符串首位空白字符,空白字符包括空格,\t, \r, \n
strip()方法类似中文的空格字符\u3000也会被移除
String提供isEmpty()和isBlank()来判断字符串是否为空和空白字符串

"  \tHello\r\n".trim();//"Hello"
"\u3000Hello\n".strip();//"Hello"
" Hello ".stripLeading();//"Hello "   去除开头空白字符
" Hello ".stripTrailing();//" Hello"   去除尾部空白字符
"".isEmpty();//true,因为字符串长度为0,这里注意一点和C语言不同,Java字符串没有以'\0'结尾
" \n".isBlank();//true,只包含空白字符

替换子串

根据字符或字符串替换,通过正则表达式替换

String s = "hello";
s.replace('l','w');//"hewwo"
s.replace("ll","~~");//"he~~o"

String s = "A,,B;C ,D";
s.replaceAll("[\\,\\;\\s]+", ","); // "A,B,C,D"

上面的代码通过正则表达式,把匹配的子串同意替换为","

分割字符串

使用split()方法,传入的也是正则表达式

String s = "A,B,C,D";
String[] ss = s.split("\\,"); // {"A", "B", "C", "D"}

拼接字符串

静态方法join(),用指定的字符串连接字符串数组

String[] arr = {"A", "B", "C"};
String s = String.join("***", arr); // "A***B***C"

格式化字符串

字符串提供了formatted()方法和format()静态方法,可以传入其他参数,替换占位符,然后生成新的字符串:

public class Main(){
	public static void main(String[] args){
		String s = "Hi %s, your score is %d!";
		System.out.println(s.formatted(Alice, 80));
		System.out.println(String.format("Hi %s, your score is %.2f!", "Bob", 59.5));
	}
}

占位符和参数一致(类型,数量)。常用的占位符:
%s:显示字符串
%d:显示整型
%x:显示十六进制整数
%f:显示浮点数

类型转换

使用静态方法valueOf(),把任意基本类型或者引用类型转换为字符串

String.valueOf(123);//"123"
String.valueOf(45.67); // "45.67"
String.valueOf(true); // "true"
String.valueOf(new Object()); // 类似java.lang.Object@636be97

把字符串转换为其他类型

int n1 = Integer.parseInt("123");//123
int n2 = Integer.parseInt("ff",16);//按十六进制转换,255
//字符串转换为boolean类型
boolean b1 = Boolean.parseBoolean("ture");//true
boolean b2 = Boolean.parseBoolean("FALSE");//false

要特别注意,Integer有个getInteger(String)方法,它不是将字符串转换为int,而是把该字符串对应的系统变量转换为Integer:
String和char[ ]类型可以互相转换

char[] cs = "Hello".toCharArray(); // String -> char[]
String s = new String(cs); // char[] -> String

字符编码

Java的String和char在内存中总是以Unicode编码表示。
关于字符编码的详细解释可以参考廖雪峰老师的Java教程
字符编码

小结
Java字符串String是不可变对象;
字符串操作不改变原字符串内容,而是返回新字符串;
常用的字符串操作:提取子串、查找、替换、大小写转换等;
Java使用Unicode编码表示String和char;
转换编码就是将String和byte[]转换,需要指定编码;
转换为byte[]时,始终优先考虑UTF-8编码。

StringBuilder

直接用+拼接字符串,每次拼接都会创建新的String对象,浪费内存
高效拼接内存->StringBuilder(Java标准库提供)

StringBuilder sb = new StringBuilder(1024);//参数是缓冲区大小
for(int i = 0; i < 1000; i++){
	sb.append(',');
	sb.append(i);
}
String s = sb.toString();

StringBuilder还可以进行链式操作,每次append返回this对象

public class Main {
    public static void main(String[] args) {
        var sb = new StringBuilder(1024);
        sb.append("Mr ")
          .append("Bob")
          .append("!")
          .insert(0, "Hello, ");
        System.out.println(sb.toString());
    }
}
//Hello, Mr Bob!

小结
StringBuilder是可变对象,用来高效拼接字符串;
StringBuilder可以支持链式操作,实现链式操作的关键是返回实例本身;
StringBuffer是StringBuilder的线程安全版本,现在很少使用

StringJoiner

用分隔符拼接字符串数组的需求很常见,Java标准库提供了StringJoiner来实现,还可以指定“开头”和“结尾”

import java.util.StringJoiner;

public class Main {
    public static void main(String[] args) {
        String[] names = {"Bob", "Alice", "Grace"};
        var sj = new StringJoiner(", ", "Hello ", "!");
        for (String name : names) {
            sj.add(name);
        }
        System.out.println(sj.toString());
    }
}

包装类型

Java数据类型

  • 基本类型:byte,short,int,long,boolean,float,double,char
  • 引用类型:所有class和interface类型,引用类型可以复制为null,

将基本类型变成引用类型->包装类型
在这里插入图片描述

public class Main {
    public static void main(String[] args) {
        int i = 100;
        // 通过new操作符创建Integer实例(不推荐使用,会有编译警告):
        Integer n1 = new Integer(i);
        // 通过静态方法valueOf(int)创建Integer实例:
        Integer n2 = Integer.valueOf(i);
        // 通过静态方法valueOf(String)创建Integer实例:
        Integer n3 = Integer.valueOf("100");
        System.out.println(n3.intValue());
    }
}

自动装箱和拆箱

自动装箱和拆箱发生在编译阶段,目的是少写代码

Integer n = 100; // 编译器自动使用Integer.valueOf(int)
int x = n; // 编译器自动使用Integer.intValue()

引用类型的比较一定要用equals()
** 创建新对象时,优先选用静态工厂方法而不是new操作符。**
例如 优先方法2
方法1:Integer n = new Integer(100);
方法2:Integer n = Integer.valueOf(100);

进制转换

Interger类中的静态方法parsenInt()可以把字符串解析成整数

int x1 = Integer.parseInt("100"); // 100
int x2 = Integer.parseInt("100", 16); // 256,因为按16进制解析

所有的整数和浮点数都继承自Number

处理无符号数

Java并没有无符号整型(Unsigned)的基本数据类型。无符号整型和有符号整型的转换需要借助包装类型的静态方法完成
例如byte是有符号整形,范围是-128+127,但是如果把byte看成无符号整型,范围就是0255。

public class Main {
    public static void main(String[] args) {
        byte x = -1;
        byte y = 127;
        System.out.println(Byte.toUnsignedInt(x)); // 255
        System.out.println(Byte.toUnsignedInt(y)); // 127
    }
}

小结
Java核心库提供的包装类型可以把基本类型包装为class;
自动装箱和自动拆箱都是在编译期完成的(JDK>=1.5);
装箱和拆箱会影响执行效率,且拆箱时可能发生NullPointerException;
包装类型的比较必须使用equals();
整数和浮点数的包装类型都继承自Number;
包装类型提供了大量实用方法。

JavaBean

JavaBean是一种符合命名规范的class,它通过getter和setter来定义属性;
属性是一种通用的叫法,并非Java语法规定;
可以利用IDE快速生成getter和setter;
使用Introspector.getBeanInfo()可以获取属性列表。

枚举类

使用enum来定义枚举类

enum Weekday {
    SUN, MON, TUE, WED, THU, FRI, SAT;
}

使用enum定义枚举的好处:num常量带有类型信息,赋值时如果类型不匹配,编译器会报错

enum的比较

==比较的是两个引用类型的变量指向是否一致(是否指向同一个对象)
equals()比较的是变量值
引用类型的比较一定要用equals()方法,但是enum类型可以例外,因enum类型的每个常量在JVM中只有一个唯一实例,所以可以直接用==比较

enum类型的方法

name()

返回常量名

String s = Weekday.SUN.name(); // "SUN"

ordinal()

返回定义的常量的顺序,从0开始计数
int n = weekday.MON.ordinal();//1

enum类型用于switch语句

public class Main {
    public static void main(String[] args) {
        Weekday day = Weekday.SUN;
        switch(day) {
        case MON:
        case TUE:
        case WED:
        case THU:
        case FRI:
            System.out.println("Today is " + day + ". Work at office!");
            break;
        case SAT:
        case SUN:
            System.out.println("Today is " + day + ". Work at home!");
            break;
        default:
            throw new RuntimeException("cannot process " + day);
        }
    }
}

enum Weekday {
    MON, TUE, WED, THU, FRI, SAT, SUN;
}

加上default语句,可以在漏写某个枚举常量时自动报错,从而及时发现错误。

小结
Java使用enum定义枚举类型,它被编译器编译为final class Xxx extends Enum { … };
通过name()获取常量定义的字符串,注意不要使用toString();
通过ordinal()返回常量定义的顺序(无实质意义);
可以为enum编写构造方法、字段和方法
enum的构造方法要声明为private,字段强烈建议声明为final;
enum适合用在switch语句中。

记录类

String,Integer都是不变类
Java 14开始,引入了新的Record类,使用关键字record定义Record类
例如定义一个Point类,他是Record类

public class Main(){
	public static void main(String[ ] args) {
		Point p = new point(123,456);
		System.out.println(p.x());
		System.out.println(p.y());
		System.out.println(p);
	}
}

public record Point(int x, int y){}/

自动用final修饰class以及每个地段,自动创建构造方法,重写toString()、equals()、hashCode()方法名
小结
小结
从Java 14开始,提供新的record关键字,可以非常方便地定义Data Class:
使用record定义的是不变类;
可以编写Compact Constructor对参数进行验证;
可以定义静态方法。

BigInteger

BigInteger内部用一个int[ ]数组来模拟超大整数

import java.math.BigInteger

BigInteger bi = new BigInteger("1234567890");
System.out.println(bi.pow(5)); // 2867971860299718107233761438093672048294900000

只能用实例方法对BigInteger做运算(不能用±这些)

BigInteger i1 = new BigInteger("1234567890");
BigInteger i2 = new BigInteger("12345678901234567890");
BigInteger sum = i1.add(i2); // 1234567890246913578

BigInteger继承自Number类,Number定义了转换为基本类型的几个方法
转换为byte:byteValue()
转换为short:shortValue()
转换为int:intValue()
转换为long:longValue()
转换为float:floatValue()
转换为double:doubleValue()
BigInteger转换成基本类型会有高位丢失的风险(溢出),可以使用intValueExact()、longValueExact()等方法,在转换时如果超出范围,将直接抛出ArithmeticException异常。

BigInteger i = new BigInteger("123456789000");
System.out.println(i.longValue()); // 123456789000
System.out.println(i.multiply(i).longValueExact()); // java.lang.ArithmeticException: BigInteger out of long range

小结
BigInteger用于表示任意大小的整数;
BigInteger是不变类,并且继承自Number;
将BigInteger转换成基本类型时可使用longValueExact()等方法保证结果准确。

BigDecimal

BigDecimal可以表示一个任意大小且精度完全准确的浮点数。
同样有各种方法,详细参考廖老师的Java教程
BigDecimal

常用工具类

Math

求绝对值:
Math.abs(-100);//100
Math.abs(-7.8); // 7.8
取最大或最小值:
Math.max(100, 99); // 100
Math.min(1.2, 2.3); // 1.2
计算x的y次方:
Math.pow(2, 10); // 2的10次方=1024
计算√x
Math.sqrt(2); // 1.414…
计算e的x次方:
Math.exp(2); // 7.389…
计算以e为底的对数:
Math.log(4); // 1.386…
计算以10为底的对数:
Math.log10(100); // 2
三角函数:
Math.sin(3.14); // 0.00159…
Math.cos(3.14); // -0.9999…
Math.tan(3.14); // -0.0015…
Math.asin(1.0); // 1.57079…
Math.acos(1.0); // 0.0
Math还提供了几个数学常量:
double pi = Math.PI; // 3.14159…
double e = Math.E; // 2.7182818…
Math.sin(Math.PI / 6); // sin(π/6) = 0.5
生成一个随机数x,x的范围是0 <= x < 1:
Math.random(); // 0.53907… 每次都不一样
如果我们要生成一个区间在[MIN, MAX)的随机数,可以借助Math.random()实现,计算如下:

// 区间在[MIN, MAX)的随机数
public class Main {
    public static void main(String[] args) {
        double x = Math.random(); // x的范围是[0,1)
        double min = 10;
        double max = 50;
        double y = x * (max - min) + min; // y的范围是[10,50)
        long n = (long) y; // n的范围是[10,50)的整数
        System.out.println(y);
        System.out.println(n);
    }
}

Random

Random用来创建伪随机数,伪随机数是指只要种子一致,产生的随机数序列是完全一样的
生成随机数。默认使用系统当前时间戳作为种子

Random r = new Random();
r.nextInt();//15798153,每次都不一样
r.nextInt(10);//5,生成一个[0,10]之间的int
r.nextLong();
r.nextFloat();//生成一个[0,1]之间的float
r.nextDouble();//生成一个[0,1]之间的double

Math.random()实际上内部调用了Random类,只是我们无法指定种子

SecureRandom

真正的真随机数只能通过量子力学原理来获取
SecureRandom用来创建安全的不可预测的随机数
SecureRandom无法指定种子

SecureRandom的安全性是通过操作系统提供的安全的随机种子来生成随机数。这个种子是通过CPU的热噪声、读写磁盘的字节、网络流量等各种随机事件产生的“熵”。
在密码学中,安全的随机数非常重要。如果使用不安全的伪随机数,所有加密体系都将被攻破。因此,时刻牢记必须使用SecureRandom来产生安全的随机数。

SecureRandom sr = new SecureRandom();
System.out.println(sr.nextInt(100));

实际使用,有限获得高强度的安全随机数生成器,如果没有提供,再使用普通等级的安全随机数生成器:

import java.util.Arrays;
import java.security.SecureRandom;
import java.security.NoSuchAlgorithmException;

public class Main {
    public static void main(String[] args) {
        SecureRandom sr = null;
        try {
            sr = SecureRandom.getInstanceStrong(); // 获取高强度安全随机数生成器
        } catch (NoSuchAlgorithmException e) {
            sr = new SecureRandom(); // 获取普通的安全随机数生成器
        }
        byte[] buffer = new byte[16];
        sr.nextBytes(buffer); // 用安全随机数填充buffer
        System.out.println(Arrays.toString(buffer));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值