外贸网站建设szjijie,企业品牌推广策划,网站开发设计大赛,html5 手机网站 模版目录1.String 为什么是不可变的#xff1f;2.字符串拼接用“” 和 StringBuilder 有什么区别?3.String、StringBuffer 和 StringBuilder 的区别是什么?4.String 中的 equals() 和 Object 中的 equals() 有何区别#xff1f;5.Object 类有哪些常用的方法#xff1f;6.如何获…
目录1.String 为什么是不可变的2.字符串拼接用“” 和 StringBuilder 有什么区别?3.String、StringBuffer 和 StringBuilder 的区别是什么?4.String 中的 equals() 和 Object 中的 equals() 有何区别5.Object 类有哪些常用的方法6.如何获取当前系统的剩余内存、总内存及最大堆内存7.LocalDateTime Calendar7.1.如何取当前的年、月、日、时、分、秒、毫秒7.2.如何获取从 1970 年 1 月 1 日 0 时 0 分 0 秒到现在的毫秒数7.3.如何获取某年某月的最后一天7.4.如何打印昨天的当前时刻7.5.如何格式化日期1.String 为什么是不可变的
1String 类中使用 final 关键字修饰的字符数组来保存字符串如下面的代码所示
public final class String implements java.io.Serializable, ComparableString, CharSequence {/** The value is used for character storage. */private final char value[];...
}2我们知道被 final 关键字修饰的类不能被继承修饰的方法不能被重写修饰的变量是基本数据类型则值不能改变修饰的变量是引用类型则不能再指向其他对象。因此final 关键字修饰的数组保存字符串并不是 String 不可变的根本原因因为这个数组保存的字符串是可变的final 修饰引用类型变量的情况。
3String 真正不可变的原因如下 ① 保存字符串的数组被 final 修饰且为私有的并且String 类没有提供/暴露修改这个字符串的方法。 ② String 类被 final 修饰导致其不能被继承进而避免了子类破坏 String 的不可变性。
2.字符串拼接用“” 和 StringBuilder 有什么区别?
1Java 语言本身并不支持运算符重载“”和“”是专门为 String 类重载过的运算符也是 Java 中仅有的两个重载过的运算符。
public static void main(String[] args) {String str1 he;String str2 llo;String str3 world;String str4 str1 str2 str3;
}上述代码对应的字节码如下 可以看出字符串对象通过 “” 的字符串拼接方式实际上是通过 StringBuilder 调用 append() 方法实现的拼接完成之后调用 toString() 得到一个 String 对象。不过在循环内使用“”进行字符串的拼接的话存在比较明显的缺陷编译器不会创建单个 StringBuilder 以复用会导致创建过多的 StringBuilder 对象从而比较占用内存空间并且效率较低。
public static void main(String[] args) {String[] arr {he, llo, world};String s ;for (int i 0; i arr.length; i) {s arr[i];}System.out.println(s);
}上述代码对应的字节码如下所示 2如果直接使用 StringBuilder 对象进行字符串拼接的话就不会存在这个问题了。
public static void main(String[] args) {String[] arr {he, llo, world};StringBuilder s new StringBuilder();for (String value : arr) {s.append(value);}System.out.println(s);
}上述代码对应的字节码如下所示 如果在 IDEA 中使用 “” 来拼接字符串的话会出现建议使用 StringBuilder 的提示如下图所示 查看字节码的方式之一 在控制台使用命令 javap -v xxx.class 即可不过在此之前需要先将 xxx.java 进行编译得到 xxx.class 文件才行。 3.String、StringBuffer 和 StringBuilder 的区别是什么?
1底层数据结构
String 是只读字符串它并不是基本数据类型而是一个对象。从底层源码来看是一个 final 类型的字符数组所引用的字符串不能被改变一经定义无法再增删改。每次对 String 的操作都会生成新的 String 对象。例如每次拼接操作即两个字符串相加 隐式地在堆上 new 了一个跟原字符串相同的 StringBuilder 对象再调用 append() 拼接后面的字符。
private final char value[];StringBuffer 和 StringBuilder 都继承了 AbstractStringBuilder 抽象类在 AbstractStringBuilder 中也是使用字符数组保存字符串不过没有使用 final 和 private 关键字修饰如下面的代码所示最关键的是这个 AbstractStringBuilder 类还提供了很多修改字符串的方法例如 append 方法。所以在进行频繁的字符串操作时建议使用 StringBuffer 和 StringBuilder 来进行操作。
/**
* The value is used for character storage.
*/
char[] value;2线程安全性
String 中的对象是不可变的也就可以理解为常量所以是线程安全的、StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁所以是线程安全的。StringBuilder 并没有对方法进行加同步锁所以是非线程安全的。
3性能
每次对 String 类型进行改变的时候都会生成一个新的 String 对象然后将指针指向新的 String 对象。StringBuffer 每次都会对 StringBuffer 对象本身进行操作而不是生成新的对象并改变对象引用。相同情况下使用 StringBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升但却要冒多线程不安全的风险。性能StringBuilder StringBuffer String
4使用场景
操作少量的数据建议使用 String单线程操作字符串缓冲区下操作大量数据: 建议使用 StringBuilder多线程操作字符串缓冲区下操作大量数据: 建议使用 StringBuffer;
4.String 中的 equals() 和 Object 中的 equals() 有何区别
String 中的 equals 方法是被重写过的比较的是 String 字符串的值是否相等。Object 的 equals 方法是比较的对象的内存地址。
5.Object 类有哪些常用的方法
1Object 是所有类的根是所有类的父类所有对象包括数组都实现了 Object 的方法。Object 类结构如下图所示 2各种方法介绍如下 ① clone() 保护方法实现对象的浅复制只有实现了 Cloneable 接口才可以调用该方法否则抛出 CloneNotSupportedException 异常深拷贝也需要实现 Cloneable同时其成员变量为引用类型的也需要实现 Cloneable然后重写 clone()。
② finalize() 该方法和垃圾收集器有关系判断一个对象是否可以被回收的最后一步就是判断是否重写了此方法。
③ equals() 该方法使用频率非常高。equals 和 的区别见上面的4.1题但是在 Object 中两者是一样的。子类一般都要重写这个方法。
④ hashCode() 该方法用于哈希查找重写了 equals() 一般都要重写 hashCode()这个方法在一些具有哈希功能的 Collection 中用到。
⑤ notify() 配合 synchronized 使用该方法唤醒在该对象上等待队列中的某个线程同步队列中的线程是给抢占 CPU 的线程等待队列中的线程指的是等待唤醒的线程。
⑥ notifyAll() 配合 synchronized 使用该方法唤醒在该对象上等待队列中的所有线程。
⑦ wait() 配合 synchronized 使用wait() 就是使当前线程等待该对象的锁当前线程必须是该对象的拥有者也就是具有该对象的锁。wait() 一直等待直到获得锁或者被中断。wait(long timeout) 设定一个超时间隔如果在规定时间内没有获得锁就返回。 调用该方法后当前线程进入睡眠状态直到以下事件发生
其他线程调用了该对象的 notify 方法其他线程调用了该对象的 notifyAll 方法其他线程调用了 interrupt 中断该线程时间间隔到了。此时该线程就可以被调度了如果是被中断的话就抛出一个 InterruptedException 异常。
6.如何获取当前系统的剩余内存、总内存及最大堆内存
1可以通过 java.lang.Runtime 类中与内存相关方法来获取剩余的内存、总内存及最大堆内存。通过下面方法可以获取到堆使用的百分比及堆内存的剩余空间。
freeMemory() 方法返回剩余空间的字节数
totalMemory() 方法总内存的字节数
maxMemory() 返回最大内存的字节数2示例如下
class Solution {public static void main(String[] args) {System.out.println(JVM 从操纵系统那里挖到的最大的内存 maxMemory : Runtime.getRuntime().maxMemory() / 1024 / 1024 M);System.out.println(JVM 已经从操作系统那里挖过来的内存 totalMemory : Runtime.getRuntime().totalMemory() / 1024 / 1024 M);System.out.println(JVM 从操纵系统挖过来还没用上的内存 freeMemory : Runtime.getRuntime().freeMemory() / 1024 / 1024 M);System.out.println(~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~);byte[] b1 new byte[3 * 1024 * 1024];System.out.println(JVM 从操纵系统那里挖到的最大的内存 maxMemory Runtime.getRuntime().maxMemory() / 1024 / 1024 M);System.out.println(JVM 已经从操作系统那里挖过来的内存 totalMemory : Runtime.getRuntime().totalMemory() / 1024 / 1024 M);System.out.println(JVM 从操纵系统挖过来还没用上的内存 freeMemory : Runtime.getRuntime().freeMemory() / 1024 / 1024 M);}
}输出结果如下
JVM 从操纵系统那里挖到的最大的内存 maxMemory : 3154M
JVM 已经从操作系统那里挖过来的内存 totalMemory : 213M
JVM 从操纵系统挖过来还没用上的内存 freeMemory : 208M
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
JVM 从操纵系统那里挖到的最大的内存 maxMemory 3154M
JVM 已经从操作系统那里挖过来的内存 totalMemory : 213M
JVM 从操纵系统挖过来还没用上的内存 freeMemory : 205M7.LocalDateTime Calendar
7.1.如何取当前的年、月、日、时、分、秒、毫秒
创建 java.util.Calendar 实例调用其 get() 传入不同的参数即可获得参数所对应的值。
import java.util.Calendar;public class TestDateAndTime {public static void main(String[] args) {//获取当前的年、月、日、时、分、秒、毫秒Calendar calendar Calendar.getInstance();//年System.out.println(calendar.get(Calendar.YEAR));//月需要注意的是 Calendar.MONTH 是从 0 开始的System.out.println(calendar.get(Calendar.MONTH) 1);//天System.out.println(calendar.get(Calendar.DATE));//时System.out.println(calendar.get(Calendar.HOUR));//分System.out.println(calendar.get(Calendar.MINUTE));//秒System.out.println(calendar.get(Calendar.SECOND));//毫秒System.out.println(calendar.get(Calendar.MILLISECOND));}
}7.2.如何获取从 1970 年 1 月 1 日 0 时 0 分 0 秒到现在的毫秒数
import java.util.Calendar;public class TestDateAndTime {public static void main(String[] args) {Calendar calendar Calendar.getInstance();//以下 2 种方法均可以获取从 1970 年 1 月 1 日 0 时 0 分 0 秒到现在的毫秒数System.out.println(System.currentTimeMillis());System.out.println(Calendar.getInstance().getTimeInMillis());}
}7.3.如何获取某年某月的最后一天
import java.time.LocalDate;
import java.util.Calendar;public class TestDateAndTime {public static void main(String[] args) {Calendar calendar Calendar.getInstance();//某月最后一天//2018-05月最后一天6月1号往前一天calendar.set(Calendar.YEAR, 2018);calendar.set(Calendar.MONTH, 5);calendar.set(Calendar.DAY_OF_MONTH, 1);calendar.add(Calendar.DAY_OF_MONTH, -1);System.out.println(calendar.get(Calendar.YEAR) - (calendar.get(Calendar.MONTH) 1) - calendar.get(Calendar.DAY_OF_MONTH));//JDK 1.8 java.time 包LocalDate date LocalDate.of(2019, 6, 1).minusDays(1);System.out.println(date.getYear() - date.getMonthValue() - date.getDayOfMonth());}
}7.4.如何打印昨天的当前时刻
import java.time.LocalDateTime;public class YesterdayCurrent {public static void main(String[] args) {LocalDateTime today LocalDateTime.now();LocalDateTime yesterday today.minusDays(1);System.out.println(yesterday);}
}或者使用以下方式
import java.util.Calendar;public class YesterdayCurrent {public static void main(String[] args) {Calendar cal Calendar.getInstance();cal.add(Calendar.DATE, -1);System.out.println(cal.getTime());}
}7.5.如何格式化日期
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;public class TestDateAndTime {public static void main(String[] args) {Date date new Date();SimpleDateFormat simpleDateFormat new SimpleDateFormat(yyyy-MM-dd HH:mm:ss);//格式化日期System.out.println(simpleDateFormat.format(date));//JDK 1.8 java.time 包System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss)));}
}