目录
4、获取自1970年1月1日 00:00:00 000到当前系统时间的总毫秒数
基础类型对应的8个包装类
以下八种包装类型中,重点以java.lang.Integer为代表的,其他的包装类型类似。
1、8种基本数据类型对应的包装类(属于引用数据类型)型名是什么?
基本数据类型 包装类型
-----------------------------------
byte java.lang.Byte(父类Number)
short java.lang.Short(父类Number)
int java.lang.Integer(父类Number)
long java.lang.Long(父类Number)
float java.lang.Float(父类Number)
double java.lang.Double(父类Number)
boolean java.lang.Boolean(父类Object)
char java.lang.Character(父类Object)
2、八种包装类型中其中6个是数字对应的包装类,他们的父类都是Number,可以先研究一下Number中公共的方法,Number是一个抽象类,无法实例化对象。
byte byteValue() 返回指定号码作为值 byte ,这可能涉及舍入或截断。
abstract double doubleValue() 返回指定数字的值为 double ,可能涉及四舍五入。
abstract float floatValue() 返回指定数字的值为 float ,可能涉及四舍五入。
abstract int intValue() 返回指定号码作为值 int ,这可能涉及舍入或截断。
abstract long longValue() 返回指定数字的值为 long ,可能涉及四舍五入或截断。
short shortValue() 返回指定号码作为值 short ,这可能涉及舍入或截断。
这些方法其实所有数字包装类的子类都有,这些方法是负责拆箱的。
例子:123这个基本数据类型,进行构造方法的包装达到了:基本数据类型 --(转换为)--> 引用数据类型 (封箱)
Integer i = new Integer(123);
将引用数据类型 --(转换为)--> 基本数据类型(拆箱)
int retValue = i.intValue();
System.out.println(retValue); // 123
关于包装类型的构造方法
Integer(int) , Java9之后不建议使用这个构造方法了,已过时。
Integer x = new Integer(100);
System.out.println(x); // 100
Integer(String) 将String类型的数字,转换成Integer包装类型。
Integer y = new Integer("123");
System.out.println(y); //123
凡是将String类型转换成Integer类型的字符串是有要求的,必须是String类型的数字
Integer y = new Integer("12s3");
上面的代码编译没有问题,运行会报java.lang.NumberFormatException异常,数字格式化异常
包装类的最大、小值
分别通过访问包装类的常量MAX_VALUE和MIN_VALUE,来获取最大值和最小值
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);
自动装箱和自动封箱
在java5之后,引入了一种新特性,自动装箱和自动封箱
有了自动拆箱之后,Number类的方法就用不着了!编程更加方便。
在java5之前使用自动装箱和自动封箱特性,编译器肯定报错的。
自动装箱:基本数据类型 --(自动转换)--> 包装类型
Integer x = 900;
System.out.println(x);
解析:900是基本数据类型,x是包装类型
自动拆箱:包装类型 --(自动转换)--> 基本数据类型
int y = x;
System.out.println(y);
解析:x是包装类型,y是基本数据类型
运算符触发自动拆箱机制
Integer z = 100; // 等同于:Integer z = new Integer(100);
System.out.println(z + 1); // 101
"+"运算符 两边要求是基本数据类型的数字,z是包装类,不属于基本数据类型,这里会进行自动拆箱,将z转换成基本数据类型。( + - * / 等运算的会触发。)
== 这个运算符不会触发自动拆箱机制。
Integer a = 1000;
Integer b = 1000;
System.out.println(a == b); // false
Integer a = 1000;等同于Integer a = new Integer(1000); a是一个引用,保存内存地址指向对象,b类似。而 == 比较的是对象的内存地址。
Integer类常用的方法
static int parseInt(String s) 静态的:String -(转换)-> int
int retValue = Integer.parseInt("1234"); //String -(转换)-> int
System.out.println(retValue + 1000); // 2234
static Integer valueOf(int i) 静态的: int --> Integer
Integer i1 = Integer.valueOf(100);
System.out.println(i1); //100
static Integer valueOf(String s) 静态的:String --> Integer
Integer i2 = Integer.valueOf("123");
System.out.println(i2); //123
String int Integer三种类型的互相转换
附加
Integer非常重要的面试题
Integer a = 128;
Integer b = 128;
System.out.println(a == b); // false
Integer x = 127;
Integer y = 127;
System.out.println(x == y); // true
解析:
java中为了提高程序的执行效率,用[-128 127]之间所有的包装对象提前创建好,放到了一个方法区的“整数型常量池“当中了,目的是只要用这个区间的数据不需要再new了,直接从整数型常量池当中取出来。
原理:x变量中保存的对象的内存地址和y变量中保存的对象的内存地址是一样的。
String类
JDK中内置的一个类:java.lang.String
1、String表示字符串类型,属于引用数据类型,不属于基本数据类型。
int i = 100;
String s = "abc";
解析:i变量中保存的是100这个值。s变量中保存的是字符串对象的内存地址。s引用中保存的不是"abc", 是0x1111,而0x1111是"abc"字符串对象在“字符串常量池”当中的内存地址。
2、使用双引号括起来的都是String对象,例如:"abc", "efg", "hello world", 这是3个String对象。
String s1 = "abcdef";
String s2 = "abcdef" + "xy";
解析:这两行代码表示底层创建了3个字符串对象,都在字符串常量池当中。
3、java中规定,双引号括起来的字符串,是不可变的,也就是说"abc"自出生到最终死亡,不可变,不能变成"abcd",也不能变成"ab"。
4、【重点】在JDK当中双引号括起来的字符串,例如:"abc" "def"都是直接存储在“方法区”的“字符串常量池”当中的。字符串在实际的开发中使用太频繁,为了执行效率,所以把字符串放到了方法区的字符串常量池当中。
String s3 = new String("xy");
解析:凡是双引号括起来的都在字符串常量池中有一份。而new对象的时候一定在堆内存当中开辟空间。
String类中的构造方法
第一个:String s = ""; 【常用】
String类已经重写了toString()方法。
String s1 = "hello world!";
System.out.println(s1); // hello world!
第二个:String s = new String("");
String s6 = new String("helloworld!");
System.out.println(s6); // helloworld!
第三个:String s = new String(char数组);
char[] chars = {'我', '是', '中', '国', '人'};
String s4 = new String(chars);
System.out.println(s4); //我是中国人
第四个:String s = new String(char数组, 起始下标, 长度);
String s5 = new String(chars, 2, 3);
System.out.println(s5); //中国人
第五个:String s = new String(byte数组);
byte[] bytes = {97, 98, 99}; //97是a.98是b,99是c
String s2 = new String(bytes);
System.out.println(s2); // abc
第六个:String s = new String(byte数组, 起始下标, 长度);
String s3 = new String(bytes, 1, 2);
System.out.println(s3); // bc
String类当中常用的方法
1.char charAt(int index)
char c = "中国人".charAt(1);
System.out.println(c); // 国
2.int compareTo(String anotherString) 字符串之间比较大小
int result = "abc".compareTo("abc");
System.out.println(result); // 0
返回0 相等;-1 小于; 1 大于
3.boolean contains(CharSequence s) 判断前面的字符串是否包含后面的子字符串
System.out.println("HelloWorld.java".contains(".java")); // true
4.boolean endsWith(String suffix) 判断当前字符串是否以某个子字符串结尾
System.out.println("test.txt".endsWith(".txt")); // true
5.boolean equals(Object anObject) 比较两个字符串必须使用equals方法,不能使用“==”
System.out.println("abc".equals("abc")); // true
6.boolean equalsIgnoreCase(String anotherString) 判断两个字符串是否相等,并且同时忽略大小写。
System.out.println("ABc".equalsIgnoreCase("aBC")); // true
7.byte[] getBytes() 将字符串对象转化为字节数组
byte[] bytes = "abcdef".getBytes();
for (int i = 0; i < bytes.length; i++) {
System.out.println(bytes[i]);
}
8.int indexOf(int ch) 判断某个字符串在当之前字符串中第一次出现的索引(下标)
System.out.println("oraclejavatpythonjavaclass".indexOf("java")); // 6
9.boolean isEmpty()
判断某个字符串是否为“空字符串”。底层源代码调用的是字符串的length()方法。
String s = "a";
System.out.println(s.isEmpty()); // false
10.int length() 判断字符串长度
System.out.println("abc".length()); // 3
11.int lastIndexOf(String str) 判断某个子字符串在当前字符串中最后一次出现的索引(下标)
System.out.println("oraclejavasec++,netpythonjava".lastIndexOf("java")); // 25
12.String replace(CharSequence target, CharSequence replacement) 替换
String newString = "http://www.baidu.com".replace("http://", "https://");
System.out.println(newString); // https://www.baidu.com
【注意】:String的父类接口就是:CharSequence
13.String[] split(String regex) 拆分字符串
String[] ymd = "1998-10-11".split("-"); // “1998-10-11”以“-”分隔符进行拆分。
for (int i = 0; i < ymd.length; i++) {
System.out.println(ymd[i]);
}
14.boolean startsWith(String prefix) 判断某个字符串是否以某个子字符串开始
System.out.println("http://www.baidu.com".startsWith("http")); // true
15.String substring(int beginIndex) 截取字符串
System.out.println("http://www.baidu.com".substring(7)); // www.baidu.com
String substring(int beginIndex, int endIndex)
beginIndex起始位置(包括)
endIndex结束位置(不包括
System.out.println("http://www.baidu.com".substring(7, 10)); // www
16.char[] toCharArray() 将字符串转换为char数组
char[] chars = "我是中国人".toCharArray();
for (int i = 0; i < chars.length; i++) {
System.out.println(chars[i]);
}
17.String toLowerCase() 转换为小写
System.out.println("AFASasd".toLowerCase());
18.String toUpperCase() 转换为大写
System.out.println("AFASasd".toUpperCase());
19.String trim() 去除字符串前后空白
System.out.println(" hello world ".trim());
21.String中只有一个方法是静态的,不需要new对象,这个方法叫做valueOf
作用:将“非字符串”转换成“字符串”
String s1 = String.valueOf(3.14);
这个静态的valueOf()方法,参数是一个对象的时候,会自动调用对象的toString()方法
String s2 = String.valueOf(new Date());
System.out.println("------->"+s2);
附加
String相关面试题
String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2); // true
s1变量的"hello"是存储在方法区的字符串常量池当中,所以s2变量存储的"hello"不会新建。(因为这个对象已经存在了!)
== 双等号比较的是变量中保存的内存地址
String x = new String("xyz");
String y = new String("xyz");
System.out.println(x == y); // false
使用equals比较
System.out.println(x.equals(y)); // true
分析以下代码,一共创建了几个对象?
String s3 = new String("Hello");
String s4 = new String("Hello");
解析:一共3个对象:方法区字符串常量池中有1个:"Hello",堆内存当中有2个String对象
内存分配图
StringBuffer和StringBuilder类
java中的字符串是不可变的,每一次拼接都会产生新字符串。这样会占用大量的方法区内存,造成内存空间的浪费。
如果以后需要进行大量字符串的拼接操作,建议使用JDK中自带的:
java.lang.StringBuffer、java.lang.StringBuilder
如何优化StringBu的性能?
在创建StringBuffer的时候尽可能给定一个初始化容量,最好减少底层数组的扩容次数。预估一下,尽量给一个合适一些的初始化容量。
关键点:给一个合适的初始化容量,可以提高程序的额执行效率。
StringBuffer
使用无参数构造,创建StringBuffer对象(字符串缓冲区对象)
StringBuffer stringBuffer = new StringBuffer();
【注意】:无参构造创建一个初始化容量为16个char[] 数组。
指定初始化容量的StringBuffer对象
StringBuffer sb = new StringBuffer(100);
append()方法,拼接字符串
【注意】:append方法底层在进行追加的时候,如果char数组满了,会自动扩容。
stringBuffer.append("a");
stringBuffer.append(3.14);
stringBuffer.append(true);
stringBuffer.append(100L);
System.out.println(stringBuffer.toString()); //a3.14true100
StringBuilder
StringBuilder和StringBuffer语法类似,主要说一些不同点
StringBuilder是线程安全的。
其中方法都有synchronized关键字修饰。表示StringBuffer在多线程环境下进行是安全的。
StringBuilder是非线程安全的。
附加
1、面试题:String为什么是不可变的?
答:我看过源代码,String类中有一个char[]数组,这个char[]数组采用了final修饰,因为数组一旦创建长度不可变的,并且被final修饰的引用一旦指向某个对象之后,不可再指向其他对象,所以String是不可变的!
"abc"无法变成"abcd"
2、StringBuilder/StringBuffer为什么是可变的呢?
答:我看过源代码,StringBuffer/StringBuilder内部实际上是一个byte[]数组,这个char[]数组没有被final修饰. StringBuffer/StringBuilder的初始化容量我记得应该是16,当存满之后会进行扩容,低层调用了数组拷贝的方法System.arraycopy()...是这样扩容的,所以StringBuilder/StringBuffer适含于使用宇符串的频繁拼接操作。
枚举
1、枚举是一种引用数据类型
2、枚举类型语法
enum 枚举类型名{
枚举值1,枚举值2
}
3、结果只有两种情况的,建议使用布尔类型。
结果超过两种并且还是一枚一枚列举出来的,建议使用枚举类型。
【注意】:枚举编译之后也是生成class文件。枚举中的每一个值可以看做是常量
public enum Result{
SUCCESS, FAIL
}
public class EnumTest {
public static void main(String[] args) {
Result r = divide(10, 0);
System.out.println(r == Result.SUCCESS ? "计算成功" : "计算失败");
}
public static Result divide(int a, int b) {
try {
int c = a / b;
return Result.SUCCESS; //成功
} catch (Exception e) {
return Result.FAIL; // 失败
}
}
}
switch语句支持枚举类型,switch也支持String,int
【注意】低版本的JDK,只支持int;高版本的JDK,支持int,String,枚举。byte short char 也可以,因为存在自动类型转换。
public enum Season {
SPRING, SUMMER, AUTUMN, WINTER
}
public class SwitchTest {
public static void main(String[] args) {
switch (Season.SPRING){
// 必须省略Season
case SPRING:
System.out.println("春天");
break;
case SUMMER:
System.out.println("夏天");
break;
case AUTUMN:
System.out.println("秋天");
break;
case WINTER:
System.out.println("冬天");
break;
}
}
}
日期类
1、获取系统当前时间
获取当前系统日期(精确到毫秒的系统当前时间),直接调用无参构造方法就可以。
Date nowTime = new Date();
System.out.println(nowTime);
java.util.Date类的toString()方法已经重写了,输出的不是一个对象的内存地址,是一个日期字符串
2、Date ---> String
日期格式化:Date --(转换成具有一定格式的日期字符串)--> String
yyyy 年(年是4位)
MM 月(月是2位)
dd 日
HH 时
mm 分
ss 秒
SSS 毫秒(毫秒3位,最高999。1000毫秒代表1秒。)
【注意】:在日期格式中,除了 y M d H m s S 这些数字不能随便写之外,剩下的符号格式自己随意组织。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
String newTimeStr = sdf.format(nowTime);
System.out.println(newTimeStr);
3、String --> Date
将一个日期字符串String类型转换成Date类型
String time = "2008-8-8 08:08:08 888";
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
Date dateTime = sdf2.parse(time);
System.out.println(dateTime); //Fri Aug 08 08:08:08 CST 2008
【注意】:字符串的日期格式和SimpleDateFormat对象指定的日期格式要一制,不然会出现异常:java.text.ParseException
4、获取自1970年1月1日 00:00:00 000到当前系统时间的总毫秒数
long nowTimeMills = System.currentTimeMillis();
System.out.println(nowTimeMills);
可以利用这个方法,统计一个方法耗时
5、Date的有参数构造方法
注意:参数是一个毫秒
Date time = new Date(1);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
String strTime = sdf.format(time);
System.out.println(strTime); // 1970-01-01 08:00:00 001
因为北京是东8区,所以会差8个小时。
数字类
BigDecimal类
1、BigDecimal 属于大数据,精度极高,不属于基本数据类型,属于java对象(引用数据类型),这是SUN提供的一个类,专门用在财务软件当中。
2、注意:财务软件中double是不够的。处理财务数据用java.math.BigDecimal类型。
BigDecimal v1 = new BigDecimal(100);
BigDecimal v2 = new BigDecimal(200);
上面这个100不是普通的100,是精度极高的100
v1 + v2;
求和不能使用"+"运算符,因为v1和v2都是引用,不能直接使用+求和。,需要调用方法求和
BigDecimal v3 = v1.add(v2);
System.out.println(v3);// 300
其他运算也需要调用方法。
数字的格式化
java.text.DecimalFormat专门负责数字格式化的
数字格式有哪些?
# 代表任意数字
, 代表千分位
. 代表小数点
0 代表不够时补0
###,###.##
表示:加入千分位,保留2位小数
DecimalFormat df = new DecimalFormat("###,###.##");
String s = df.format(1234.56);
System.out.println(s); //"1,234.56"
随机数
java.util.Random类
随机产生一个int类型取值范围内的数字
Random random = new Random();
int num1 = random.nextInt();
System.out.println(num1);
随机产生一个int类型指定取值范围内的数字
int num2 = random.nextInt(101); // 不包括101
System.out.println(num2);
解析:产生[0~100]之间的随机数,不产生101。