JAVA开发学习-day05

JAVA开发学习-day05

1. 字符串 String

java中除了8大基本数据类型,其他的类型都是引入类型

使用String来声明字符串,String是引用类型,所有的引用类型的默认值都为null。

//声明字符串
String str = "abc";
str = new String("你好");
char[] arr = new char[10];
char[] arr1 = {'a','b','c',97};
str = new String(); //构造方法参数可以为空
System.out.println(arr1);//输出为abca
//String.valueOf(),将传输的参数转化为字符串
str = String.valueOf(439028);
System.out.println(str);//439028

1.1 字符串的拼接

字符串使用+来拼接

字符串和所有类型相加(+),结果都为字符串

str = 123 + "abc"; // "123abc"
str = "123" + 123; //"123123"
//加对象,就是字符串加上对象的toString结果
str = "abc" + 123 + new Object();
System.out.println(str);
//输出为 abc123java.lang.Object@1b6d3586
//数组是一个特殊的类
str = "123" + new int[]{1,2,3};
//输出为 123[I@4554617c
System.out.println(str);

加号在做字符串拼接和数学运算时,优先级是一样的

System.out.println("123" + 123 + 123); 
// 结果为123123123
System.out.println(123 + 123 + "123"); 
// 结果为246123

1.2 字符串的比较

使用equals方法来比较字符串

boolean bool = "123".equals("123"); //返回值为布尔值
System.out.println(bool); // true
//比较的是字符串是否相同,而不是对象
bool = new String("123").equals(new String("123"));
System.out.println(bool); // true

String中的重写的equals方法

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true; //如果是同一对象,则直接返回true
    }
    //instanceof用于检查对象是否是指定类型
    if (anObject instanceof String) { //检查anObject是否是字符串类型
        String anotherString = (String)anObject; //将anObject转换为String,为了下面使用String的属性和方法
        int n = value.length;
        //this.value.length,对字符串的长度进行判断
        if (n == anotherString.value.length) {
            //value是String的 private final char[] value存储字符串的字符串数组
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            //对每个字符进行判断
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

1.3 String类型中的常用方法

1.3.1 valueOf()

valueOf 将传入的参数转成字符串

String.valueOf('1');
String.valueOf("");
String.valueOf(null);
String.valueOf(new Object());
//String.valueOf(); ❌ 不能没有参数

重载的方法一个参数为String,一个参数为Object的情况下,参数的输入值为null,则优先调使用String的方法

public class EasyString {
    public static void main(String[] args) {
        //String和Object重载的情况下,优先调使用String的方法
        test(null); //输出结果为 String
    }
    public static void test(String str){
        System.out.println("String");
    };
    public static void test(Object obj){};
}
1.3.2 indexOf() lastIndexOf() charAt()

indexOf()和lastIndexOf()是用来查找字符串的子串出现的下标的方法

int index = "123456".indexOf("456");
System.out.println(index); //返回子串的下标
int index1 = "123456".indexOf("46");
System.out.println(index1); //没有子串,返回-1
index = "123123123".indexOf("1"); // index值为0
index = "123123123".lastIndexOf("1");// 查找最后一个子串所在第一个字符的下标,index值为6

charAt()用来获取指定位置的字符

//获取指定位置的字符
char item = "123456".charAt(4); //获取下标为4的字符 item为"5"
//char item1 = "123456".charAt(100); String index out of range 字符串下标超出范围
1.3.3 subString()

subString()用于截取字符串的一段

str = "123456".substring(1); //从开始下标截取到最后
System.out.println(str); // 23456
//包含开始下标,不包含结束下标
str = "123456".substring(1, 3); //从开始下标截取到结束下标的前一个
System.out.println(str); // 23
1.3.4 replace() replaceAll()

replace()和replaceAll()用来将字符串中的子串替换为指定的字符串

str = "123456".replace("34","aaaa");
System.out.println(str); //12aaaa56
//replace替换所有子串
str = "12345634".replace("34","aaaa");
System.out.println(str); //12aaaa56aaaa
//正则表达式替换,使用正则表达式匹配子串并替换
str = "12.31.23".replaceAll(".","1");
System.out.println(str); //111111111
1.3.5 split()

使用split()来根据输入的分隔符来分割字符串

String[] strArr = "123123123".split("1");
//如果分隔符是第一个元素,则会分割一个空串
System.out.println(Arrays.toString(strArr)); // [, 23, 23, 23]
String[] strArr1 = "23123121".split("1");
//如果分隔符是最后一个元素,那就不会有空串
System.out.println(Arrays.toString(strArr1)); // [23, 23, 2]
String[] strArr2 = "12312312".split("2");
System.out.println(Arrays.toString(strArr2)); // [1, 31, 31]
1.3.6 其他

String的方法都可以见名知义,不需要特别记忆

//字符串长度 length()
int l = "123123".length();
for (int i = 0 ; i < l; i++){};

//trim 去除前后空白位    空格 \n \r \t \f
//只去除前后的空白位
str = "          123  456  \n\r\t\f   ".trim();
System.out.println(str); // 输出结果为123  456

// 大写 小写 (针对字母)
str = "123abc".toUpperCase(); //转成大写 123ABC
str = "123ABC".toLowerCase(); //转成小写 123abc

//判断是否是空串
bool = "123".isEmpty(); // false
bool = "".isEmpty(); // true

//结束开始判断
//判断是否以某字符串开始
bool = "123456".startsWith("123"); //true
//判断是否以某字符串结束
bool = "123456".endsWith("456"); //true

1.4 字符串常量池

池这个词在java里并不罕见,比如运行时常量池,字符串常量池,线程池,数据库连接池等,所谓“池”就是为了资源复用,减少空间的占用,提高性能。

JVM为了提高性能,减少内存开销,维护的一个存放字符串常量的内存区域,里面的字符串不允许重复,有长度限制,最大为65535字节

使用量方式声明的字符串,就会加入到常量池中

// 量的形式声明
// 直接赋予值,就是量的形式声明
int a = 12;
String str = "abc";

程序中第一次使用量的形式定义"123",会将这个字符串存入常量池中

之后再使用量的形式使用该对象,就执行使用常量池中的对象

String strA = "123";
String strB = "123";
//strA strB是同一对象
System.out.println(strA == strB); // true

new即创建新对象,创建新对象的时不会使用常量池的对象

String strA = "123";
String strC = new String("123");
String strD = new String("123");
//对象不同
System.out.println(strC == strD); //false
System.out.println(strC == strA); //false

是否使用了常量池中的对象判断

String strE = "12" + "3"; // "123"
String strF = "1" + "2" + "3"; // "123"
String item = "12";
String strG = item + "3";
String strGG = item + 3;
// itme不明确,在计算之前,先创建对象存储 item + ? 再计算值
// 所以strG和strGG不是同一对象
System.out.println(strG == strGG); //false
String strH = "12" + 3;

System.out.println(strA == strE); //true
System.out.println(strA == strF); //true
System.out.println(strA == strG); //false
System.out.println(strA == strH); //true

final String item1 = "12";
//item1是常量,下面item1 + "3"在解析之前就明确为"123"
String strI = item1 + "3";
System.out.println(strI == strA); //true
//新对象
final String strJ = new String("123");
System.out.println(strA == strJ); // false

也开始使用intern()方法来将字符串加入到常量池中

//intern
str.intern();

intern()将对象加入常量池的方式

//返回str对象在字符串常量池中的副本对象 没有副本对象就将str复制一份到常量池中再返回副本对象
//所以如果两个字符串 equals为true
//那么两个字符串的intern()方法是相等的(都是同一副本对象)
strA = new String("123123");
strB = new String("123123");
System.out.println(strA.equals(strB));//true
System.out.println(strA == strB); // false
System.out.println(strA.intern() == strB.intern()); // true

面试题

//new String("abc") 创建了几个对象
//一个或两个
//当字符串常量池中有abc的副本对象,就创建了一个对象
//如果没有abc副本对象,就创建abc副本对象,和此对象,即两个对象

1.5 StringBuilder() StringBuffer()

String 字符串定义后就不可改变 存在常量池中

在拼接字符串的过程中会产生中间量

public class EasyStringbuilder {
    public static void main(String[] args) {
        //String 字符串定义后就不可改变 存在常量池中
        String str = "";
        for (int i = 0; i < 10; i++) {
            str = str + i;
        }
        //在拼接字符串的过程中会产生中间量 0 01 012 0123 .... 0123456789
    }
}

在拼接字符串时想要不产生中间量就需要StringBuilder StringBuffer

使用StringBuilder的append方法进行拼接

StringBuilder strB = new StringBuilder();
strB.append("123");
strB.append("abc");
strB.append("456");

//调用append 往StringBuilder数组中追加字符
//其中没有再产生字符串对象
System.out.println(strB);
//输出为 123abc456

StringBuilder的append方法中直接调用了其父类AbstractStringBuilder的append方法

public AbstractStringBuilder append(String str) {
    if (str == null)
        return appendNull();
    int len = str.length();
    //ensureCapacityInternal对存放字符串的数组进行扩容
    //count为字符串数组的容量,len为要拼接的字符串的长度
    ensureCapacityInternal(count + len);
    //对字符串进行拼接
    str.getChars(0, len, value, count);
    count += len;
    return this;
}

ensureCapacityInternal()方法用来确认AbstractStringBuilder中存储字符串的数组是否需要扩容

private void ensureCapacityInternal(int minimumCapacity) {
    // overflow-conscious code
    if (minimumCapacity - value.length > 0) {
        //定义扩容大小
        value = Arrays.copyOf(value,
                              newCapacity(minimumCapacity));
    }
}

如果需要扩容则通过newCapacity()方法确认需要扩容至多大

private int newCapacity(int minCapacity) {
    // overflow-conscious code
    //将数组的容量左移一位再加2,即*2+2
    int newCapacity = (value.length << 1) + 2;
    //如果扩容后仍小于需要的大小,则将扩容大小变为需要的大小
    if (newCapacity - minCapacity < 0) {
        newCapacity = minCapacity;
    }
    //容量足够则返回新容量,不足则用hugeCapacity()方法继续扩容
    return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
        ? hugeCapacity(minCapacity)
        : newCapacity;
}

再回去看ensureCapacityInternal()方法中的Arrays.copyOf()方法,在确定需要扩容至多大后就用Arrays.copyOf()方法来扩容

public static char[] copyOf(char[] original, int newLength) {
    //声明更大的数组
    char[] copy = new char[newLength];
    //将小数组的数据拷贝到大数组
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
}

System.array()是原生方法,下面是System.array()的使用方法

import java.util.Arrays; 

int[] source = { 1, 2, 3, 4, 5, 6, 7 };
int[] destination = new int[5];

//System.arraycopy(源数组,源数组开始拷贝下标,目标数组,目标数组拷贝下标,拷贝的元素个数)
System.arraycopy(source, 3, destination, 2, 3); // 要复制的源数组中的元素为 4,5,6。 这些将从索引2开始复制到目标数组。
System.out.println(Arrays.toString(destination)); // [0, 0, 4, 5, 6]

再看append()调用的getChars()方法

public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
    if (srcBegin < 0) {
        throw new StringIndexOutOfBoundsException(srcBegin);
    }
    if (srcEnd > value.length) {
        throw new StringIndexOutOfBoundsException(srcEnd);
    }
    if (srcBegin > srcEnd) {
        throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
    }
    //使用System.arraycopy()对数组进行拼接
    System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}

由StringBuilder类的构造方法可知AbstractStringBuilder类中存储字符串的数组大小初始值设为16

public final class StringBuilder extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence{
    public StringBuilder() {
        super(16);
    }
}

abstract class AbstractStringBuilder implements Appendable, CharSequence {
    char[] value;
    int count;
    AbstractStringBuilder() {
    }
    AbstractStringBuilder(int capacity) {
        //数组初始大小设为16
        value = new char[capacity];
    }
}

总结

StringBuiLder 默认容量是16
StringBuilder 扩容
追加字符时容量不够,就需要扩容(value) 默认原容量*2+2

StringBuilder 是线程不安全的 异步
StringBuffer 是线程安全的 synchronized
StringBuilder使用arraycopy来拼接

2. 关于日期的方法

获取当前时间可以使用java.util.Date类

import java.util.Date;
public class EasyDate {
    public static void main(String[] args) {
        //时间类型 Date
        //获取当前时间 --执行时
        //Date date = new Date(100000);
        Date date = new Date();
        System.out.println(date);
    }
}

获取当前时间的时间戳,可以用Date类的getTime方法

import java.util.Date;
public class EasyDate {
    public static void main(String[] args) {
        //获取从1970-1-1 00:00:00.000过了多少毫秒
        //获取时间戳
        Date date = new Date();
        long time = date.getTime();
        System.out.println(time);
    }
}

在实例化对象时填入的数值,就是从1970-1-1 00:00:00.000过了多少毫秒的日期

import java.util.Date;
public class EasyDate {
    public static void main(String[] args) {
        Date date = new Date(100000); //过了100秒
        System.out.println(date);
        //输出为 Thu Jan 01 08:01:40 CST 1970
        //因为在东八区,所以显示8点
    }
}

天数计算

import java.util.Date;
public class EasyDate {
    public static void main(String[] args) {
        Date date = new Date();
        System.out.println(date);

        //获取从1970-1-1 00:00:00.000过了多少毫秒
        //获取时间戳
        long time = date.getTime();
        System.out.println(time);

        //输出两天后的时间
        time = time + 2*24*60*60*1000;
        date = new Date(time);
        System.out.println(date); //输出的日期为两天后
    }
}

时间格式化

使用SimpleDateFormat对象的format()方法来格式化Date对象的输出格式

import java.text.SimpleDateFormat;
public class EasyDate {
    public static void main(String[] args) {
        Date date = new Date();
        System.out.println(date);

        //时间格式化
        //将日期输出的形式重新定义
        //HH为24小时制 年-月-日 小时:分钟:秒 毫秒
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        //hh为12小时制度
        System.out.println(sdf.format(date));
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss SSS");
        System.out.println(sdf1.format(date));
    }
}

其他的时间类

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;

public class EasyDate {
    public static void main(String[] args) {
        LocalDate ld = LocalDate.now(); //本地日期
        System.out.println(ld); //2024-07-18
        LocalDateTime ldt = LocalDateTime.now(); //本地时间
        System.out.println(ldt);// 2024-07-18T17:29:52.532
        ZonedDateTime zdt = ZonedDateTime.now(); //本地时间 + 时区和地区
        System.out.println(zdt); 
        //2024-07-18T17:29:52.533+08:00[Asia/Shanghai]
        Object obj = zdt.getZone(); //哪个地区时间制度
        System.out.println(obj); //Asia/Shanghai
    }
}

3. 随机数

可以用Math.random方法来返回一个double类型的随机数

//随机数
double ran = Math.random(); //[0,1)
//如果想得到取值范围为[8,90)的随机数
//[8,90) -----> [0,82) + 8 -----> [0,1)*82 + 8
double ran = Math.random()*82 + 8;

Random类也可以实现随机数,不同于Math.random()的是Random类实现的随机数是假随机,而Math.random是真随机

Random randomObj = new Random(12); //参数是种子数
Random randomObjA = new Random(12);
//种子数相同,返回的随机数也相同 假随机
int a = randomObj.nextInt();
int b = randomObjA.nextInt();
System.out.println(a == b); //true
//种子数相同,取值范围相同,返回值也相同
a = randomObj.nextInt(200);
b = randomObjA.nextInt(200);
System.out.println(a == b); //true

虽然是假随机,但Random类使用方便,想要哪个类型的随机数直接调用方法返回即可

Random randomObj = new Random(12);

int numInt = randomObj.nextInt();
long numLong = randomObj.nextLong();
double numDouble = randomObj.nextDouble();
float numFloat = randomObj.nextFloat();
boolean numBoolean = randomObj.nextBoolean();

4. 取整

Math类中还有一些取整方法

//取整
//四舍五入
ran = 12.5;
//Math.round方法传入double返回long   传入float返回int
long roundNum = Math.round(ran); //13
float aa = 12.4f;
int roundNum1 = Math.round(aa); //12
System.out.println(roundNum);
//向上取整 有小数部分舍去进一 double
double ceilNum = Math.ceil(ran); //13
System.out.println(ceilNum);
//向下取整  double
double floorNum = Math.floor(ran);//12
System.out.println(floorNum);

负数的取整要注意

roundNum = Math.round(-0.5); // 0
roundNum = Math.round(-0.51); // -1
roundNum = Math.round(-0.49); // 1
roundNum = Math.round(0.5); // 1
  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值