目录
可变字符串StringBuffer StringBuilder
包装类
就是基本类型的包装类
直接上代码吧。
package com.mark.java.common;
import javax.persistence.criteria.CriteriaBuilder;
public class IntegerDemo {
public static void main(String[] args) {
//正常情况
int a = 10;//基本类型定义
Integer a1 = new Integer(10);//包装类定义
//进行了自动装箱,相当于 Integer b = Integer.valueOf(10); 把int类型转为Integer类型
Integer b = 10;
//进行了自动拆箱,相当于 int b1 = new Integer(10).intValue(); 把Integer类型转为int类型
int b1 = new Integer(10);
//在这里不得不提到比较值 ==,看到等于我们应该想到是 对于引用变量来说是比较两个地址。对于基本类型来说就是比较值。
//情况1
int c = 10;
int c1 = 10;
c1 =20;
//当int c=10;时,会在栈中存储一个10,c指向10;如果c1=10;则c1直接指向10;所以c==c1 为true。
//虽然都指向10,但是如果此时 我们另 c1 = 20;,此时c的值并不会变化,还是指向10,只是在栈中在存储一个20,同时c1 指向 20,此时c ==c1为false
System.out.println(c==c1); //true ,基本类型,直接比较值
//情况2
Integer d = new Integer(10);
Integer d1 = new Integer(10);
System.out.println(d == d1); //false ,引用类型,比较地址。
//情况3
Integer e = new Integer(10);
int e1 = 10;
//true,包装类和基本类型比较是,包装类会自动拆箱,int e2 = new Integer(10).intValue(); 在转换就是int e2 = 10;所以 e2==e1 为true
System.out.println(e==e1);//true
//情况4
Integer f = 100;
Integer f1 = 100;
System.out.println(f==f1);//true;
//这里其实需要自动装箱,变为
Integer f2 = Integer.valueOf(100);
Integer f3 = Integer.valueOf(100);
//要判断f2 == f3 到底是什么,先不要急,我们需要先看一下valueOf()方法是怎么实现的
//我们可以看到,是由一个if判断的,当满足if条件的时候,是从一个Integer数组中取出来的Integer对象,对于下标是100,取的对象都是同一个,所以f2 ==f3为ture
System.out.println(f2==f3);//true
System.out.println("---------------------------");
//如果上述值变成 200;会怎么样呢
Integer g = 200;
Integer g1 = 200;
System.out.println(g==g1);
//这里其实需要自动装箱,变为
Integer g2 = Integer.valueOf(200);
Integer g3 = Integer.valueOf(200);
System.out.println(g2==g3);
//揭晓谜底,当值变为200的时候,就不满足if条件,而是new Integer()对象,所以
//相当于
Integer g4 = new Integer(200);
Integer g5 = new Integer(200);
System.out.println(g4==g5);
//这就明确了吧,g4 == g5 一定为false
}
}
分析valueOf()
这里我们可以稍微分析下valueOf()方法
1. 可以看到是有个if判断,当满足if条件,从IntegerCache类中的cache数组中取值并返回。
2. 此时我看一下IntegerCathe类,该类是Integer类的静态内部类,该静态内部类在启动的时候在staitc块中就已经创建一个Integer的数据组cache,里面已经创建好了256个Integer对象,是从-127到128的。
3.所以 Integer.valueOf(100)的值是从数组中取的对象,所以f==f1为true。但是当值为200的时候,就会不在这个区间内,而是每次都new Integer(),所以g==g1 为false。
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
String
趁热打铁,我们也可以研究一下String 类型的== 关系。
String有点特殊,所以String是一个引用变量,但是也有两个方法创建对象
- String str = "abc";
1. 先在常量池中查找是否有“abc"
2. 如果没有,则在常量池中创建”abc“对象,并让str引用该对象
3. 如果有,则直接str指向该对象。
- 2. String str1 = new String("abc");
这种方式一次可能创建两个对象或者一个对象,为什么这么说呢
首先 ”abc“就是一个对象,然后在new String()所以相当于创建了两个对象。
1. 在堆中new String()对象,并让栈中的引用变量str1指向该对象。
2. 在字符串常量池中查找”abc“,如果没有查询到,则在常量池中创建一个对象”abc“,并让堆中的new String()对象指向池中的”abc“
3 .如果查询到常量池中有”abc“对象,则不在创建对象,而是让new String() 对象直接指向池中的”abc“
这里不得不提一下
- 在JDK1.6及之前版本,字符串常量池在方法区中
- 在JDK1.7及以后版本,字符串常量池移到了堆中
4. 根据以上,现在可以理解为,栈中str1指向堆中的new String("abc"), 而new String("abc")指向常量池中的”abc“,但是让str1调用一个intern()方法,该方法会把指向常量池”abc“的地址返回。
例如
String c = "abc";
String c1 = new String("abc");
System.out.println(c==c1);//false
c1 = c1.intern();
System.out.println(c==c1);//true
5. ”abc“ 在类加载的时候,就已经创建了一个对象,并存储在字符串常量池中。此时,这个对象的属性已经初始化。"abc"在编译时就被写入字节码中,所以class被加载时,JVM就为"abc"在常量池中 分配内存,创建了对象
所以当 String str = new String("abc") 时,实际上“abc”就已经是一个对象了,可以调用任何String 类的方法。
根据以上的介绍,如果要比较两个字符串是否 ==,看下几种场景
package com.mark.java.common;
public class StringDemo {
public static void main(String[] args) {
//情况1
String a = "abc";
String a1 = "abc";
//a 和 a1都指向常量池中的"abc"
System.out.println(a==a1);//true
//情况2
String b = new String("abc");
String b1 = new String("abc");
//b 和 b1 分别指向堆中不同的对象
System.out.println(b==b1);//false
//情况3
String c = "abc";
String c1 = new String("abc");
//c 指向常量池中的"abc",而c1执行堆中的 对象
System.out.println(c==c1);//false
//调用intern方法,c1指向 将常量池中的"abc",c也指向池中的"abc",所以c1 ==c
c1 = c1.intern();
System.out.println(c==c1);//true
System.out.println("-----------------------------------------");
//情况4,Stirng 中出现 + 的情况
String d = "abc";
String d1 = "efg";
String d2 = "abcefg";
String d3 = "abc"+"efg";
String d4 = d+d1;
//对于d3,直接去池中找abcefg,所以d2和 d3 指向的时一致的,所以相等
System.out.println(d2==d3);//true
//对于d4,是 d+d1,是引用变量的相加,是地址的相加,不是值得相加
//其实在内部会创建一个StringBuilder的对象
System.out.println(d2==d4);//false
//相当于
StringBuilder stringBuilder = new StringBuilder().append(d).append(d1);
String s = stringBuilder.toString();
//而下面是StringBuilder的toString方法,就是new String()创建了一个新对象。所以为false
//public String toString() {
// // Create a copy, don't share the array
// return new String(value, 0, count);
// }
}
}
String 是一个不可变对象,值得属性不可变,但是String里面的属性是 char[] 数组,指的是数组的指向地址不可变,但数据中的内容是可变的。
String str = "abc";
相当于:
char data[] = {'a', 'b', 'c'};
String str = new String(data);
也就是说,其实String就是由char数据构成的。String中的属性private final char value[]; 就是这些char数据。
所以String 的 equals 比较的实际上是 两个char数组,比较数据中每一个值是否相等。
String 的常用方法:
1. 构造方法,
String()
String(byte[]) 以及 String(byte[] ....)
String(char[]) 以及 String(char[] ....)
String(int [] ......)
String(String)
String(StringBuilder)
String(StringBuffer)
2. 成员方法
- char charAt(int index) 返回 char指定索引处的值。
- int compareTo(String anotherString) 按字典顺序比较两个字符串。按照unicode值比较,如果该String对象在参数String之前,返回负整数,之后,返回正整数,相等返回0
- String concat(String str) 将指定的字符串连接到该字符串的末尾。
- boolean contains(CharSequence s) 是否包含
- boolean contentEquals(StringBuffer sb) ,具有指定相同的序列
- static String copyValueOf(char[] data) 相当于 valueOf(char[]) 。将char数组转成String
- boolean endsWith(String suffix) 测试此字符串是否以指定的后缀结尾。
- boolean equals(Object anObject)
- boolean equalsIgnoreCase(String anotherString) 忽略大小写的 equals
- static String format(String format, Object... args) 使用指定格式的字符串,用到占位符
- byte[] getBytes() String 转 byte数组
- void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) 将字符串中的字符复制到char数组中,
- int hashCode() 返回该字符串的哈希码
- int indexOf(int ch) 返回指定字符在该字符串中的索引
- String intern() ,返回该字符串的规范表示
- boolean isEmpty() 判断字符串lenth是否0
- static String join(CharSequence delimiter, CharSequence... elements)
String message = String.join("-", "Java", "is", "cool");
// message returned is: "Java-is-cool"
- static String join(CharSequence delimiter, Iterable<? extends CharSequence> elements)
List<String> list = new ArrayList<>();
list.add("我是");
list.add("一只");
list.add("可爱的");
list.add("小猫");
System.out.println(String.join("--",list));
//返回我是--一只--可爱的--小猫
- int lastIndexOf(int ch) 返回指定字符 最后一次出现在字符串中的 索引位置
- int length() ,返回字符串长度
- boolean matches(String regex) 匹配正则
- replace replaceAll replaceFirst 替换
- split 分割
- startWith 以 开始
- subString 截取子字符串
- char[] toCharArray() 转换成char数组
- String toLowerCase() 转成小写
- String toUpperCase() 转成大写
- String trim() ,删除前后空格
- String valueOf() 转成String类型
可变字符串StringBuffer StringBuilder
两者的api基本都相同,不同的是一个是线程安全的,一个是线程不安全的的。
StringBuffer 线程安全的,在成员方法中增加了synchronized,同步锁。由于是可变字符串,所以就存在同时操作一个字符串的问题,所以要加一个锁保证数据同步。
StringBuilder 线程不安全的
参考:https://www.cnblogs.com/xiohao/p/4296088.html
Date 日期
相关的类
Calendar 日历类,是一个抽象类,抽象类是不能new 对象的。提供一个getInstance方法类获取Calendar对象
Date sql.Date 是 util.Date的子类。
DateFormat 用来格式化时间
Math
-
基本数字运算的方法,加减乘除,平方,开平方 ,三角函数,
- 获取随机数Math.random()
package com.mark.java.common;
public class MathDemo {
public static void main(String[] args) {
System.out.println(Math.random());
//向上取整
System.out.println(Math.ceil(3.14));
//向下取整
System.out.println(Math.floor(3.14));
//四舍五入
System.out.println(Math.round(3.14));
}
}
枚举类eumn
1. 用enum修饰
2. 枚举类中的枚举值相当于枚举类的对象,且是用 public static final修饰,可以直接用类调用。
3. 枚举类有属性,构造方法,普通方法等
4. 枚举类可以当做常量类来使用。直接获取A的value值。作为常量。
String code = EnumDemo2.A.getValue();
无参构造
package com.mark.java.common;
import sun.security.util.ECUtil;
public enum EnumDemo {
//可以当成是EnumDemo类的两个实例化对象
//相当于acct(),client();,调用的时无参数的构造方法;
acct,client;
EnumDemo(){
}
}
有参数构造
package com.mark.java.common;
public enum EnumDemo2 {
//枚举,可以当成该枚举类的实例对象。
//相当于public static final 修饰,直接用类名进行调用
A("01","哈哈"),
B("02","呵呵");
//属性
private String code;
private String value;
//构造方法
private EnumDemo2(String code,String value){
this.code=code;
this.value=value;
}
//get set 方法
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
//普通方法
//提供了values方法,能将枚举类中的枚举值转成数组。
public static void show(){
EnumDemo2[] values = EnumDemo2.values();
for (EnumDemo2 enumDemo2 : values) {
System.out.println(enumDemo2.name());
}
}
//根据code获取value值
public static String getValueByCode(String code){
EnumDemo2[] values = EnumDemo2.values();
for (EnumDemo2 enumDemo2 : values) {
if(enumDemo2.getCode().equals(code)){
return enumDemo2.getValue();
}
}
return null;
}
}
class A{
public static void main(String[] args) {
EnumDemo2.show();
System.out.println(EnumDemo2.A.getCode()+":"+EnumDemo2.A.getValue());
String valueByCode = EnumDemo2.getValueByCode("01");
System.out.println(valueByCode);
}
}