初识常用类
Posted Al_tair
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初识常用类相关的知识,希望对你有一定的参考价值。
初识常用类
大家好呀!我是小笙!我学习了韩顺平老师的类和对象的知识,收获颇丰!现在来和大家分享笔记!
常用类
包装类(Wrapper)
包装类的分类
包装类 | 基本数据类型 | 直接父类 |
---|---|---|
boolean | Boolean | Object |
char | Character | Object |
byte | Byte | Number |
short | Short | Number |
int | Int | Number |
long | Long | Number |
float | Float | Number |
double | Double | Number |
Boolean
Character
Number父类下的直接子类
装箱 & 拆箱
- 自动拆装箱
- 手动拆装箱
public class Wrapper01
public static void main(String[] args)
// jdk5以前手动装箱&手动拆箱;jdk5之后可以自动拆装箱
// 以Character为例
char name = 'n';
// 手动装箱
Character ch1 = new Character(name); // 不推荐
Character ch2 = Character.valueOf(name);
// 手动拆箱
char name2 = Character.valueOf(ch2); // 本质就是使用charValue方法
char name3 = ch1.charValue();
// 自动装箱
Character ch3 = name; // 本质使用的就是valueOf方法
// 自动拆箱
char CH4 = ch3; // 本质就是使用charValue方法
接下来我对于自动拆装箱的底层进行追踪结果
首先打四个断点,分别探索这四个断点的跳转
以下是依次跳转的函数
总结
- 手动拆装箱和自动拆装箱底层没有本质区别
- 包装类转 <=>基本数据类型
- 基本数据类型 --> 包装类 装箱 本质:valueOf函数
- 包装类 --> 基本数据类型 拆箱 本质:charValue函数
习题
// 如下输出结果是什么
习题1
Object obj = true? new Integer(1):new Double(2.0); // 三元运算符是一个整体
System.out.println(obj); // 1.0
习题2
Object obj1;
if(true)
obj1 = new Integer(1);
else
obj1 = new Double(2.0);
System.out.println(obj); // 1
包装类 <=> String类
Wrapper Vs String
public class WrapperVsString
public static void main(String[]args)
// String类 转换成 包装类
String age = "120";
Integer age2 = Integer.valueOf(age); // 方式一:valueOf函数 本质上就是parseInt()方法
Integer a2 = Integer.parseInt(age); // 方式二:parseInt函数
Integer age3 = new Integer(age); //不推荐,本质就是parseInt()方法
// 包装类 转换成 String类
Integer height = 180; // 自动装箱
String h = String.valueOf(height); // 方式一:valueOf函数 本质就是调用toString()方法
String h2 = height + ""; // 方式二: 类型转换 Integer + ""
String h3 = height.toString(); // 方式三: toString()函数
/*
* String.valueOf()源码
* public static String valueOf(Object obj)
* return (obj == null) ? "null" : obj.toString();
*
*
* Integer.valueOf()源码
* public static Integer valueOf(String s) throws NumberFormatException
* return Integer.valueOf(parseInt(s, 10)); // 10指的是传入的数字是十进制数
*
*
* new Integer()源码
* @Deprecated(since="9")
* public Integer(String s) throws NumberFormatException
* this.value = parseInt(s, 10);
*
*/
Wrapper类的常用方法
以Integer包装类为例
包装类的相关面试题
public class Wrapper02
public static void main(String[] args)
/*
* 源码:IntegerCache.low -128 IntegerCache.high 127
* public static Integer valueOf(int i)
* if (i >= IntegerCache.low && i <= IntegerCache.high)
* return IntegerCache.cache[i + (-IntegerCache.low)];
* return new Integer(i);
*
* 如果valueOf(value) value > -128 && value < 127 则 返回 IntegerCache.cache[i + (-IntegerCache.low)]
* 否则 返回新对象Integer
*/
System.out.println(new Integer(1) == new Integer(1)); // false
Integer a = 1;
Integer b = 1;
System.out.println(a==b); // true
Integer m = 128;
Integer n = 128;
System.out.println(m==n); // false
Integer x = 128;
int y = 128;
System.out.println(x==y); // true
String类
String类的概述
public static void main(String[] args)
/**
* String
* 概念:是一组字符序列 本质上是char[] value 字符数组实现
* "Al_tair"被称为字符常量 用双引号括起来的字符序列
* 一个字符占用两个字节(每个字符不区分字母和汉字)
* public final class String 说明String的final类,不能被其它类继承
* private final byte[] value 用于存放字符串 value是用final修饰的类型,该数组不能指向新地址,但是能修改它的值
*/
String name = "Al_tair";
接口和构造器
String内存图
// 运行代码,内存图如下
class code
public static void main(String[] args)
String a = "Al_tair";
String b = new String("Al_tair");
内存图: 字符串 VS 字符数组
结合代码和内存图分析
class Text
String str = new String("lns");
// final指的是char类型数据存储的地址不能改变,但是值是可以改变的
final char[] ch = 'j','a','v','a';
public void change(String str,char[] ch)
str = "zlr";
ch[1] = 'c';
public static void main(String[] args)
Text text = new Text();
text.change(text.str,text.ch);
System.out.println(text.str.toString()+" and "+text.ch[1]); // lnsandc
String类的常用方法
- equals 区别大小写,判断字符串的内容是否相同
- equalsIgnoreCase 忽略大小写 来判断字符串的内容是否相同
- length 获取字符串的个数,或者称为字符串长度
- indexOf 获取字符在字符串中第一次出现的索引,索引从0开始,如果没有找到则返回-1
- lastindexOf 获取字符在字符串中最后一次出现的索引,索引从0开始,如果没有找到则返回-1
- substring 截取指定范围的字串
- trim 去掉字符串前后的空格
- charAt 获取某索引处的字符
- compareTo 比较两个字符串的大小,如果前者大于等于后者,则返回自然数;反之后者大,则返回负数
- intern 如果常量池中已经包含值相同的字符串,则返回常量池中的字符串引用地址,否则将String对象添加到常量池中,并返回String对象的引用
// equals()方法源码
public boolean equals(Object anObject)
if (this == anObject) // 地址是否相同
return true;
if (anObject instanceof String) // 是否为String类或者String父类
String aString = (String)anObject;
if (!COMPACT_STRINGS || this.coder == aString.coder)
return StringLatin1.equals(value, aString.value);
return false;
@HotSpotIntrinsicCandidate
public static boolean equals(byte[] value, byte[] other)
if (value.length == other.length)
for (int i = 0; i < value.length; i++)
if (value[i] != other[i])
return false;
return true;
return false;
// 占位符的讲解 涉及方法format <=> c语言输出
// %s,%d,%.3f,%c
String name = "lns";
int age = 18;
double height = 185.35;
char gender = '男';
String Info = "姓名:%s\\t年龄:%d\\t身高:%.3f\\t性别:%c";
String show = String.format(Info,name,age,height,gender);
System.out.println(show); // 姓名:lns 年龄:18 身高:185.350 性别:男
相关习题
// 习题1
String a = "l";
String b = new String("l");
System.out.println(a.equals(b)); // true
System.out.println(a == b); // false
System.out.println(a == b.intern()); // true
System.out.println(b == b.intern()); // false
// 习题2
// 2.1创建了几个对象 答:2
String s = "hello";
s = "haha";
// 2.2 创建了几个对象 答:1 结论:编译器会做优化,判断常量池对象是否有引用指向
String str = "hello" + "haha"; // 等价于 String str = "hellohaha";
// 2.3 创建了几个对象 答:3 结论:字符串常量相加地址存放在常量池,字符串变量相加地址存放在String对象中
// sum 指向的是value[](String对象),再指向常量池中"HelloString"字符串
public static void main(String[]args)
String m = "Hello";
String n = "String";
/*
* 解读:
* 1. 创建新对象 new StringBuilder();
* 2. 通过append函数添加字符串 “Hello”
* 3. 通过append函数添加字符串 “String”
* 4. 返回new String("HelloString");
*/
String sum = m + n;
// 分析sum 的指向和底层源码
// debug test
// first insert
public StringBuilder()
super(16);
//secong insert str = "Hello"
public StringBuilder append(String str)
super.append(str);
return this;
// third insert str = "String"
public StringBuilder append(String str)
super.append(str);
return this;
// last one
public String toString()
// Create a copy, don't share the array
return isLatin1() ? StringLatin1.newString(value, 0, count): StringUTF16.newString(value, 0, count);
StringBuffer类
概念:代表可变的字符序列,可以对字符串内容进行增删,是一个容器
构造方法
Constructor and Description |
---|
StringBuffer() 构造一个没有字符的字符串缓冲区,初始容量为16个字符。 |
StringBuffer(CharSequence seq) 构造一个包含与指定的相同字符的字符串缓冲区 CharSequence 。 |
StringBuffer(int capacity) 构造一个没有字符的字符串缓冲区和指定的初始容量。 |
StringBuffer(String str) 构造一个初始化为指定字符串内容的字符串缓冲区。 |
/*
* Constructs a string buffer with no characters in it and an
* initial capacity of 16 characters.
* StringBuffer()构造器
*/
@HotSpotIntrinsicCandidate
public StringBuffer()
super(16); // 初始容量为16个字符 存储在父类的value数组中
String类 <=> StringBuffer类
String类和StringBuffer类的区别
- String保存的是字符串常量,里面的值不能更改,每次值的更新实际上就是更改地址,效率低
- Stringbuffer保存的是字符串变量,里面的值是可以改变的,不需要每次都更改地址,效率高
String类和StringBuffer类的相互转换
public static void main(String[] args)
// String和StringBuffer的相互转换
// String => StringBuffer
String str = "lns";
StringBuffer stringBuffer = new StringBuffer(str); // 方式一: 使用StringBuffer构造器
StringBuffer append = new StringBuffer().append(str); // 方式二: 使用的是append方法
// StringBuffer => String
StringBuffer sbr = new StringBuffer("zlr");
String s = sbr.toString(); // 方式一: 使用toString方法
String s1 = new String(sbr); // 使用String构造器
常用方法
public static void main(String[] args)
// 常用方法
// append 增
StringBuffer stringBuffer = new StringBuffer("");
stringBuffer.append("lns"); // lns
/*
* append源码
* 不管传入什么数据类型,返回StringBuffer类型
* public synchronized StringBuffer append(String str)
* toStringCache = null;
* super.append(str);
* return this;
*
*/
// delete 删除
// 删除索引范围 [start,end)
stringBuffer.delete(0,1); // 删除第一个字符 ns
// replace 替换
// 替换范围[start,end)
stringBuffer.replace(0, 1,"ln"); // lns
// indexOf 查找
// 查找第一次在字符串中出现的索引,如果查找到会返回你查找的字符串首个字母索引,如果找不到返回-1
stringBuffer.indexOf("ns"); // 1
// length 长度
System.out.println(stringBuffer.length()); // 3
相关习题
// 习题1
String str = null;
StringBuffer sb = new StringBuffer();
sb.append(str);
System.out.println(sb); // null
System.out.println(sb.length()); // 4
/*
* // 底层分析
* // StingBuffer类
* public synchronized StringBuffer append(String str)
* toStringCache = null;
* super.append(str); // 跳转到父类
* return this;
*
* // AbstractStringBuilder抽象类
* public AbstractStringBuilder append(String str)
* if (str == null)
* return appendNull(); // 跳转到该方法
*
* int len = str.length();
* ensureCapacityInternal(count + len);
* putStringAt(count, str);
* count += len;
* return this;
*
* // appendNull方法
* private AbstractStringBuilder appendNull()
* ensureCapacityInternal(count + 4);
* int count = this.count;
* byte[] val = this.value;
* if (isLatin1())
* val[count++] = 'n';
* val[count++] = 'u';
* val[count++] = 'l';
* val[count++] = 'l';
* else
* count = StringUTF16.putCharsAt(val, count, 'n', 'u', 'l', 'l');
*
* this.count = count;
* return this;
*
*/
StringBuffer sb = new StringBuffer(str); // 抛出空指针异常 NullPointerException
/*
* AbstractStringBuilder(String str)
* int length = str.length(); // str为null
* int capacity = (length < Integer.MAX_VALUE - 16)
* ? length + 16 : Integer.MAX_VALUE;
* final byte initCoder = str.coder();
* coder = initCoder;
* value = (initCoder == LATIN1)
* ? new byte[capacity] : StringUTF16.newBytesFor(capacity);
* append(str);
*
*/
StringBuilder类
概念:一个可变的字符序列。 线程不安全。 此类设计用作简易替换为StringBuffer
在正在使用由单个线程字符串缓冲区的地方。 在可以的情况下,建议使用这个类别优先于StringBuffer
,因为它在大多数实现中将更快。
大部分与 StringBuffer类似
特殊点:没有做互斥处理,因此在单线程下使用
// 源码剖析 区别在于关键字 synchronized 保证线程安全
// StringBuffer 的append方法
@Override
@HotSpotIntrinsicCandidate
public synchronized StringBuffer append(String str)
toStringCache = null;
super.append(str);
return this;
// StringBuilder 的append方法
@Override
@HotSpotIntrinsicCandidate
public StringBuilder append(String str)
super.append(str);
return this;
String,StringBuffer,StringBuilder的区别
- String:不可变字符序列,效率低,但是因为存在常量池所以复用率高
- StringBuffer:可变字符序列,效率较高(增删),线程安全 、
- StringBuilder:可变字符序列,效率最高,线程不安全
使用原则
- 如果字符串存在大量的修改操作,一般使用StringBuffer或者StringBuider
- 如果字符串存在大量的修改操作,并在单线程的情况,使用StringBuilder
- 如果字符串存在大量的修改操作,并在多线程的情况,使用StringBuffer
- 如果字符串很少修改,被多个对象引用,使用String 比如:配置信息等
Math类
概念:Math类包含执行基本数学运算的方法
常用方法
public static void main(String[] args)
// Math类中大部分是静态方法,可以直接通过类名.方法名访问
// abs 绝对值
int abs = Math.abs(-10);
System.out.println(abs); // 10
// pow 求幂
double pow = Math.pow(2,4);
System.out.println(pow); // 16.0
// ceil 向上取整,返回>=该参数的最小整数(整数会转换成double型)
double ceil = Math.ceil(-3.002);
System.out.println(ceil); // -3.0
// floor 向下取整,返回<=该参数的最大整数(整数会转换成double型)
double floor = Math.flo以上是关于初识常用类的主要内容,如果未能解决你的问题,请参考以下文章