Java基础思维导图
2022-07-17 16:38:46 0 举报
AI智能生成
Java学习,从基础开始
作者其他创作
大纲/内容
Java8大基本类型
整数类型
byte:1字节 --默认值:0
对应包装类型:Byte --包装(引用)类型默认值:null,使用时需要判空
判空方式
普通:Byte !=null
jdk7: Objects.requireNonNull : Objects是final修饰的
jdk8:Optional.ofNullable : Optionnal是final修饰的
可是回头一看:Optional类是申明为final的!!没法继承啊!
因为像Optional类和LocalDateTime类都是值敏感的。jdk要求把值敏感的类设计成不可变类,否则对象就可以被变更。
题
题
申明为final
根据值来自定义equals()和hashCode()
绝对使用equals()方法而不是==进行比较
没有公开的构造器,而是提供工厂方法
根据值来自定义equals()和hashCode()
绝对使用equals()方法而不是==进行比较
没有公开的构造器,而是提供工厂方法
short: 2字节 --默认值:0
对应包装类型:Short --包装(引用)类型默认值:null,使用时需要判空
判空方式
java null 在前_java中判断对象为null时,null在前面还是后面
int:4字节 --默认值:0
对应包装类型:Integer --包装(引用)类型默认值:null,使用时需要判空
判空方式
1、数据结构判空(map、list、set)
分为apache.lang3或者spring框架下:
分为apache.lang3或者spring框架下:
CollectionUtils.isEmpty() 为空
CollectionUtils.isNotEmpty() 不为空
2、对象判空:jdk7
Objects.isNull() 为空
Objects.nonNull() 不为空
3、字符串判空
StringUtils.isNotEmpty() 不为空
4、isBlank()与isEmpty()的区别
String a = null;//没分配内存
String b = new String(); //分配了内存,内存指针无指向
String c = ""; //分配了内存,内存指针指向空字符串
String d= " "; //分配了内存,内存指针指向多个空格组成的字符串
String a = null;//没分配内存
String b = new String(); //分配了内存,内存指针无指向
String c = ""; //分配了内存,内存指针指向空字符串
String d= " "; //分配了内存,内存指针指向多个空格组成的字符串
(1),public static boolean isEmpty(String str)
判断某字符串是否为空,为空的标准是str==null或str.length()==0
下面是示例:
StringUtils.isEmpty(null) = true
StringUtils.isEmpty(“”) = true
StringUtils.isEmpty(" “) = false //注意在StringUtils中空格作非空处理
StringUtils.isEmpty(” “) = false
StringUtils.isEmpty(“bob”) = false
StringUtils.isEmpty(” bob ") = false
判断某字符串是否为空,为空的标准是str==null或str.length()==0
下面是示例:
StringUtils.isEmpty(null) = true
StringUtils.isEmpty(“”) = true
StringUtils.isEmpty(" “) = false //注意在StringUtils中空格作非空处理
StringUtils.isEmpty(” “) = false
StringUtils.isEmpty(“bob”) = false
StringUtils.isEmpty(” bob ") = false
(2). public static boolean isBlank(String str)
判断某字符串是否为空或长度为0或由空白符(whitespace)构成
下面是示例:
StringUtils.isBlank(null) = true
StringUtils.isBlank(“”) = true
StringUtils.isBlank(" “) = true
StringUtils.isBlank(” “) = true
StringUtils.isBlank(”\t \n \f \r") = true //对于制表符、换行符、换页符和回车符StringUtils.isBlank()均识为空白符
StringUtils.isBlank(“\b”) = false //“\b"为单词边界符
StringUtils.isBlank(“bob”) = false
StringUtils.isBlank(” bob ") = false
判断某字符串是否为空或长度为0或由空白符(whitespace)构成
下面是示例:
StringUtils.isBlank(null) = true
StringUtils.isBlank(“”) = true
StringUtils.isBlank(" “) = true
StringUtils.isBlank(” “) = true
StringUtils.isBlank(”\t \n \f \r") = true //对于制表符、换行符、换页符和回车符StringUtils.isBlank()均识为空白符
StringUtils.isBlank(“\b”) = false //“\b"为单词边界符
StringUtils.isBlank(“bob”) = false
StringUtils.isBlank(” bob ") = false
StringUtils.isEmpty() 为空
StringUtils.isNotBlank() 不为空
StringUtils.isBlank() 为空
生成Integer对是有常量池的:在-128~127之间常量,就从缓存的IntegerCache类中获取
long:8字节 --默认值:0L
对应包装类型:Long --包装(引用)类型默认值:null,使用时需要判空
判空方式
浮点类型
float:4字节 --默认值:0f
对应包装类型:Float --包装(引用)类型默认值:null,使用时需要判空
判空方式
double:8字节 --默认值:0d
对应包装类型:Double --包装(引用)类型默认值:null,使用时需要判空
判空方式
引申知识
BigDecimal判空
很多人都知道,在进行金额表示、金额计算等场景,不能使用double、float等类型,而是要使用对精度支持的更好的BigDecimal。
子主题
为什么阿里巴巴禁止使用BigDecimal的equals方法做等值比较?
equals()方法会比较值和精度(1.0与1.00返回结果为false),而compareTo()则会忽略精度,精度就是小数有几位
错误案例
if ( bigdecimal = bigdecimal )
因为BigDecimal是对象,所以不能用==来判断两个数字的值是否相等。
if ( bigdecimal.equals( bigdecimal ) )
比较值和精度,不适合比较
实际例子
BigDecimal bigDecimal = new BigDecimal(1);
System.out.println("bigDecimal = " + bigDecimal);//bigDecimal = 1
BigDecimal bigDecimal1 = new BigDecimal(1);
System.out.println("bigDecimal1 = " + bigDecimal1);//bigDecimal1 = 1
System.out.println(bigDecimal.equals(bigDecimal1)); //true
// 整数类使用bigdecimal,精度一样
BigDecimal bigDecimal2 = new BigDecimal(1);
System.out.println("bigDecimal2 = " + bigDecimal2);//bigDecimal2 = 1
BigDecimal bigDecimal3 = new BigDecimal(1.0);//bigDecimal3 = 1
System.out.println("bigDecimal3 = " + bigDecimal3);
System.out.println(bigDecimal2.equals(bigDecimal3)); //true
// 浮点型在用bigdecimal 初始化是不精确的,但是返回一样
BigDecimal bigDecimal4 = new BigDecimal("1");
System.out.println("bigDecimal4 = " + bigDecimal4);//bigDecimal4 = 1
BigDecimal bigDecimal5 = new BigDecimal("1.0"); //bigDecimal5 = 1.0
System.out.println("bigDecimal5 = " + bigDecimal5);
System.out.println(bigDecimal4.equals(bigDecimal5));//flase
BigDecimal bigDecimal = new BigDecimal(1);
System.out.println("bigDecimal = " + bigDecimal);//bigDecimal = 1
BigDecimal bigDecimal1 = new BigDecimal(1);
System.out.println("bigDecimal1 = " + bigDecimal1);//bigDecimal1 = 1
System.out.println(bigDecimal.equals(bigDecimal1)); //true
// 整数类使用bigdecimal,精度一样
BigDecimal bigDecimal2 = new BigDecimal(1);
System.out.println("bigDecimal2 = " + bigDecimal2);//bigDecimal2 = 1
BigDecimal bigDecimal3 = new BigDecimal(1.0);//bigDecimal3 = 1
System.out.println("bigDecimal3 = " + bigDecimal3);
System.out.println(bigDecimal2.equals(bigDecimal3)); //true
// 浮点型在用bigdecimal 初始化是不精确的,但是返回一样
BigDecimal bigDecimal4 = new BigDecimal("1");
System.out.println("bigDecimal4 = " + bigDecimal4);//bigDecimal4 = 1
BigDecimal bigDecimal5 = new BigDecimal("1.0"); //bigDecimal5 = 1.0
System.out.println("bigDecimal5 = " + bigDecimal5);
System.out.println(bigDecimal4.equals(bigDecimal5));//flase
理解
BigDecimal(int)
BigDecimal(double)
BigDecimal(long)
BigDecimal(String)
BigDecimal(double)
BigDecimal(long)
BigDecimal(String)
最简单的就是BigDecimal(long) 和BigDecimal(int),因为是整数,所以标度就是0 :
public BigDecimal(int val) {
this.intCompact = val;
this.scale = 0;
this.intVal = null;
}
public BigDecimal(long val) {
this.intCompact = val;
this.intVal = (val == INFLATED) ? INFLATED_BIGINT : null;
this.scale = 0;
}
this.intCompact = val;
this.scale = 0;
this.intVal = null;
}
public BigDecimal(long val) {
this.intCompact = val;
this.intVal = (val == INFLATED) ? INFLATED_BIGINT : null;
this.scale = 0;
}
BigDecimal(double)
当我们使用new BigDecimal(0.1)创建一个BigDecimal 的时候,其实创建出来的值并不是正好等于0.1的,而是0.1000000000000000055511151231257827021181583404541015625 。这是因为doule自身表示的只是一个近似值。那么,无论我们使用new BigDecimal(0.1)还是new BigDecimal(0.10)定义,他的近似值都是0.1000000000000000055511151231257827021181583404541015625这个,那么他的标度就是这个数字的位数,即55。
其他的浮点数也同样的道理。对于new BigDecimal(1.0)这样的形式来说,因为他本质上也是个整数,所以他创建出来的数字的标度就是0。
所以,因为BigDecimal(1.0)和BigDecimal(1.00)的标度是一样的,所以在使用equals方法比较的时候,得到的结果就是true。
其他的浮点数也同样的道理。对于new BigDecimal(1.0)这样的形式来说,因为他本质上也是个整数,所以他创建出来的数字的标度就是0。
所以,因为BigDecimal(1.0)和BigDecimal(1.00)的标度是一样的,所以在使用equals方法比较的时候,得到的结果就是true。
BigDecimal(string)
当我们使用new BigDecimal("0.1")创建一个BigDecimal 的时候,其实创建出来的值正好就是等于0.1的。那么他的标度也就是1。
如果使用new BigDecimal("0.10000"),那么创建出来的数就是0.10000,标度也就是5。
所以,因为BigDecimal("1.0")和BigDecimal("1.00")的标度不一样,所以在使用equals方法比较的时候,得到的结果就是false。
如果使用new BigDecimal("0.10000"),那么创建出来的数就是0.10000,标度也就是5。
所以,因为BigDecimal("1.0")和BigDecimal("1.00")的标度不一样,所以在使用equals方法比较的时候,得到的结果就是false。
布尔类型
boolean --默认值:false
对应包装类型:Boolean --包装(引用)类型默认值:null,使用时需要判空
判空方式
字符类型
char:2字节 --默认值:\u0000(null)
对应包装类型:Charater --包装(引用)类型默认值:null,使用时需要判空
判空方式
一、空字符串与null区别
1、类型
null表示的是一个对象的值,而并不是一个字符串。例如声明一个对象的引用,String a = null ;
""表示的是一个空字符串,也就是说它的长度为0。例如声明一个字符串String str = "" ;
""表示的是一个空字符串,也就是说它的长度为0。例如声明一个字符串String str = "" ;
引申知识
在java中变量和引用变量是存在栈中(stack),而对象(new产生的)都是存放在堆中(heap):
字符串对象与null的值不相等,且内存地址也不相等;
public static void main(String[] args) {
String s1 = new String();
String s2 = null;
String s3 = "";
System.out.println("s1==s2 = " + s1==s2);//内存地址比较 false
System.out.println("s1 = " + s1.equals(s2));//值的比较 false
System.out.println("s2==s3 = " + s2==s3);//内存地址比较 false
System.out.println("s3.equals(s2) = " + s3.equals(s2));//值的比较 false
System.out.println("s1==s3" + s1==s3);//内存地址比较 false
System.out.println("s1.equals(s3) = " + s1.equals(s3));//值的比较 true
}
String s1 = new String();
String s2 = null;
String s3 = "";
System.out.println("s1==s2 = " + s1==s2);//内存地址比较 false
System.out.println("s1 = " + s1.equals(s2));//值的比较 false
System.out.println("s2==s3 = " + s2==s3);//内存地址比较 false
System.out.println("s3.equals(s2) = " + s3.equals(s2));//值的比较 false
System.out.println("s1==s3" + s1==s3);//内存地址比较 false
System.out.println("s1.equals(s3) = " + s1.equals(s3));//值的比较 true
}
空字符串对象与null的值不相等,且内存地址也不相等;
new String()创建一个字符串对象的默认值为"" (String类型成员变量的初始值为null)
2、内存分配
String str = null ; 表示声明一个字符串对象的引用,但指向为null,也就是说还没有指向任何的内存空间;
String str = ""; 表示声明一个字符串类型的引用,其值为""空字符串,这个str引用指向的是空字符串的内存空间;
String str = ""; 表示声明一个字符串类型的引用,其值为""空字符串,这个str引用指向的是空字符串的内存空间;
引申知识
“==”和equals 最大的区别是
“==”是运算符,如果是基本数据类型,则比较存储的值;如果是引用数据类型,则比较所指向对象的地址值。
equals是Object的方法,比较的是所指向的对象的地址值,一般情况下,重写之后比较的是对象的值。
8大引用类型
统一extends Number 数字实现类
INumber 接口
INumber 接口
int intValue();
long longValue();
float floatValue();
double doubleValue();
default byte byteValue() {
return (byte)this.intValue();
}
default short shortValue() {
return (short)this.intValue();
}
long longValue();
float floatValue();
double doubleValue();
default byte byteValue() {
return (byte)this.intValue();
}
default short shortValue() {
return (short)this.intValue();
}
INumber下的方法只能是实例化之后的对象使用
所有包装类都重写了Object方法
我们也很容易知道Object的方法有:
boolean equals(Object obj)
int hashcode()
String toString()
boolean equals(Object obj)
int hashcode()
String toString()
equals 基本上用于判断当前对象和参数传入的对象是否相同,Object类的默认实现是比较地址。对于两个变量,指向同一个对象地址时,equals才会返回true,与==运算符结果相同。一般这个默认实现是不符合我们需要的比较两个对象相等,需要子类重写这个实现。以Long为例,其equals方法代码实现如下:
public boolean equals(Object obj){
if(obj instanceof Long){
return value==((Long)obj).longValue();
}
return false;
}
public boolean equals(Object obj){
if(obj instanceof Long){
return value==((Long)obj).longValue();
}
return false;
}
对于Float,equals方法实现跟上面还有点区别,需要注意一下,其equals实现:
public boolean equals(Object obj){
return (obj instanceof Float) && (floatToIntBits((Float) obj).value) ==floatToIntBits(value));
}
上面代码出现了一个floatToIntBits()方法,这里将float的二进制表示看做int。为什么要使用这个方法呢?因为float类型要比较相等的时候,只有当他们表示的二进制完全一样的时候才相等。所以比较两个float相等转成成了二进制对应int值的比较。Double实现euqals方法也类似,有兴趣的可以自己找源码看看。
public boolean equals(Object obj) {
return (obj instanceof Double)
&& (doubleToLongBits(((Double)obj).value) ==
doubleToLongBits(value));
}
public boolean equals(Object obj){
return (obj instanceof Float) && (floatToIntBits((Float) obj).value) ==floatToIntBits(value));
}
上面代码出现了一个floatToIntBits()方法,这里将float的二进制表示看做int。为什么要使用这个方法呢?因为float类型要比较相等的时候,只有当他们表示的二进制完全一样的时候才相等。所以比较两个float相等转成成了二进制对应int值的比较。Double实现euqals方法也类似,有兴趣的可以自己找源码看看。
public boolean equals(Object obj) {
return (obj instanceof Double)
&& (doubleToLongBits(((Double)obj).value) ==
doubleToLongBits(value));
}
hashCode 返回一个对象的哈希值。哈希值是一个int类型的数,一般有对象中不变的属性值映射得来。一般在容器类会对对象进行区分。一个对象的哈希值不能改变,相同对象的哈希值相同,不同对象的可以相同,也可以不同,一般是不同。对于hashcode与equals的关系,我这里推荐一个博主的文章,写的比我详细,我这里就在这里引用他的文
阿里规范:只要重写equals就必须重写hashCode.
为什么呢?
因为set对象对比的是equals和hashCode,如果hashCode没有,
两个对象字面量一样,但是hashCode不一样,会将两个添加到set集合中
因为set对象对比的是equals和hashCode,如果hashCode没有,
两个对象字面量一样,但是hashCode不一样,会将两个添加到set集合中
案例
在Set中为何要同时重写hashCode()和equals()呢?
不重写也可以,但是会丢失数据,比你认为的不重复数据,但是没有重写就添加不进去set集合
不重写也可以,但是会丢失数据,比你认为的不重复数据,但是没有重写就添加不进去set集合
//以下为Object类
public boolean equals(Object obj) {
return (this == obj);
}
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
public native int hashCode();
也就是说,hashCode()和equals()都是Object类中的方法。
在Object中,equals方法的本质就是 == ,即比较地址。
在没有重写的equals的类,equals比较的是地址。
而String、Date、File等类重写了equals方法,所以比较的是内容(字面量)。
在Object中,equals方法的本质就是 == ,即比较地址。
在没有重写的equals的类,equals比较的是地址。
而String、Date、File等类重写了equals方法,所以比较的是内容(字面量)。
2.2如何定义相等?
Object类中equals方法认为的相等是,地址相等。
@Test
public void testString() {
String s1 = new String("123");
String s2 ="123";
System.out.println(s1 == s2);//false
System.out.println(s1.equals(s2));//true
}
关于s1和s2,他们并不指向同一个实例对象,也就是说他们的地址并不相等。然而,在使用过程中,我们往往只关注String的内容,即字面量,故String类中重写了equals方法,也就是对equals来说,字面量相等,就认为他们相等。其实只是给何为相等重新下了个定义。何为相等,要根据业务场景去随时定义。默认的相等定义就是Object类中的equals方法,即比较地址。
当然,关于String类其实还要提到字符串常量池,常量池的对象地址是一样的 如果在 -128 -127之间取常量池,对象的地址一样
https://blog.csdn.net/weixin_43615816/article/details/123311738
public void testString() {
String s1 = new String("123");
String s2 ="123";
System.out.println(s1 == s2);//false
System.out.println(s1.equals(s2));//true
}
关于s1和s2,他们并不指向同一个实例对象,也就是说他们的地址并不相等。然而,在使用过程中,我们往往只关注String的内容,即字面量,故String类中重写了equals方法,也就是对equals来说,字面量相等,就认为他们相等。其实只是给何为相等重新下了个定义。何为相等,要根据业务场景去随时定义。默认的相等定义就是Object类中的equals方法,即比较地址。
当然,关于String类其实还要提到字符串常量池,常量池的对象地址是一样的 如果在 -128 -127之间取常量池,对象的地址一样
https://blog.csdn.net/weixin_43615816/article/details/123311738
2.3Set中如何定义相等?
其实,在Set中,如字符串,仍只需要比较字面量是否相等即可,对于其它对象,可由用户自定义相等规矩(重写equals方法)。
那为何还要同时重写hashCode()和equals(),即相等(equals)的对象必须具有相等的哈希码?
那为何还要同时重写hashCode()和equals(),即相等(equals)的对象必须具有相等的哈希码?
@Test
public void testPerson() {
//Person 重写了equals方法,即比较id和name,没有重写hashcode
Person person1 = new Person(1001, "jack");
Person person2 = new Person(1001, "jack");
System.out.println(person1.hashCode());//1805013491
System.out.println(person2.hashCode());//951880373
System.out.println(person1.equals(person2));//true
}
public void testPerson() {
//Person 重写了equals方法,即比较id和name,没有重写hashcode
Person person1 = new Person(1001, "jack");
Person person2 = new Person(1001, "jack");
System.out.println(person1.hashCode());//1805013491
System.out.println(person2.hashCode());//951880373
System.out.println(person1.equals(person2));//true
}
原因:当person1和person2这两个对象(equals)相等,即他们equals的结果为true,但他们各自的哈希码(很大概率)不相同(没有重写hashCode),当他们要存入同一个HashSet时,有可能就会因为哈希码不同导致计算得出的HashSet内部数组位置索引不一样,那么person1、person2很可能同时存入同一个HashSet中。
引申知识
如果自定义对象做为 Map 的键,那么必须重写 hashCode 和 equals;
HashMap中的重写
所有的key构成的集合是Set:无序的、不可重复的。
所以,key所在的类要重写:equals()和hashCode()。
所有的value构成的集合是Collection:无序的、可以重复的。
所以,value所在的类要重写:equals()。
所以,key所在的类要重写:equals()和hashCode()。
所有的value构成的集合是Collection:无序的、可以重复的。
所以,value所在的类要重写:equals()。
很多时候我们常用的key是String类型,那么如果使用一般对象作为key值这个对象需要满足或者具备什么条件呢?
1.首先String底层重写了hashcode 和equals 方法,所以可以使用String对象作为key来使用。
2.如果自定义对象作为 map 的键,那么也必须重写 hashcode和equals。
3.只要重写equals,就必须重写hashcode。
1.首先String底层重写了hashcode 和equals 方法,所以可以使用String对象作为key来使用。
2.如果自定义对象作为 map 的键,那么也必须重写 hashcode和equals。
3.只要重写equals,就必须重写hashcode。
引申知识:阿里规范
Object对象的colne尽量不使用,
因为是浅复制
因为是浅复制
Java API 的Comparable 接口如下:
public interface Comparable<T> {
public int compareTo(T o)
}
public int compareTo(T o)
}
Byte
静态方法直接调用:属于本身自己定义的方法
public static int compare(byte x, byte y) {
return x - y;
}
public static int compare(byte x, byte y) {
return x - y;
}
Integer、Long
静态方法直接使用 : 属于本身自己定义的方法
public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
public static int compare(long x, long y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
public static int compare(long x, long y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
该方法是实现Comparable接口的方法。实例对象才能使用,里边是使用的静态方法
public int compareTo(Long anotherLong) {
return compare(this.value, anotherLong.value);
}
public int compareTo(Long anotherLong) {
return compare(this.value, anotherLong.value);
}
public int compareTo(Long anotherLong) {
return compare(this.value, anotherLong.value);
}
public int compareTo(Long anotherLong) {
return compare(this.value, anotherLong.value);
}
Folat
静态方法直接使用:
public static int compare(float f1, float f2) {
if (f1 < f2)
return -1; // Neither val is NaN, thisVal is smaller
if (f1 > f2)
return 1; // Neither val is NaN, thisVal is larger
// Cannot use floatToRawIntBits because of possibility of NaNs.
int thisBits = Float.floatToIntBits(f1);
int anotherBits = Float.floatToIntBits(f2);
return (thisBits == anotherBits ? 0 : // Values are equal
(thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
1)); // (0.0, -0.0) or (NaN, !NaN)
}
public static int compare(float f1, float f2) {
if (f1 < f2)
return -1; // Neither val is NaN, thisVal is smaller
if (f1 > f2)
return 1; // Neither val is NaN, thisVal is larger
// Cannot use floatToRawIntBits because of possibility of NaNs.
int thisBits = Float.floatToIntBits(f1);
int anotherBits = Float.floatToIntBits(f2);
return (thisBits == anotherBits ? 0 : // Values are equal
(thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
1)); // (0.0, -0.0) or (NaN, !NaN)
}
Double
静态方法直接使用:
如果double使用的值大小不一样,直接判断,如果一样,则需要转换成二进制
进行判断大小,因为double(双精度)和float(单精度)都是近似值,只有二进制
一样才一样呢。要使用精确不丢失精度,得使用bigdecimal
使用<和>对浮点数进行比较时,不够严谨,有这两个问题:0.0、-0.0的比较问题(0.0 > -0.0),以及NaN的问题(NaN永远比!NaN大),建议使用Double.compare()或Float.compare()进行比较。
源码中将浮点数转化为long类型的位序列,并根据IEEE754标准进行大小比较,可以解决这两个问题。
public static int compare(double d1, double d2) {
if (d1 < d2)
return -1; // Neither val is NaN, thisVal is smaller
if (d1 > d2)
return 1; // Neither val is NaN, thisVal is larger
// Cannot use doubleToRawLongBits because of possibility of NaNs.
long thisBits = Double.doubleToLongBits(d1);
long anotherBits = Double.doubleToLongBits(d2);
return (thisBits == anotherBits ? 0 : // Values are equal
(thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
1)); // (0.0, -0.0) or (NaN, !NaN)
}
如果double使用的值大小不一样,直接判断,如果一样,则需要转换成二进制
进行判断大小,因为double(双精度)和float(单精度)都是近似值,只有二进制
一样才一样呢。要使用精确不丢失精度,得使用bigdecimal
使用<和>对浮点数进行比较时,不够严谨,有这两个问题:0.0、-0.0的比较问题(0.0 > -0.0),以及NaN的问题(NaN永远比!NaN大),建议使用Double.compare()或Float.compare()进行比较。
源码中将浮点数转化为long类型的位序列,并根据IEEE754标准进行大小比较,可以解决这两个问题。
public static int compare(double d1, double d2) {
if (d1 < d2)
return -1; // Neither val is NaN, thisVal is smaller
if (d1 > d2)
return 1; // Neither val is NaN, thisVal is larger
// Cannot use doubleToRawLongBits because of possibility of NaNs.
long thisBits = Double.doubleToLongBits(d1);
long anotherBits = Double.doubleToLongBits(d2);
return (thisBits == anotherBits ? 0 : // Values are equal
(thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
1)); // (0.0, -0.0) or (NaN, !NaN)
}
该方法是实现Comparable接口的方法。实例对象才可以使用
public int compareTo(Double anotherDouble) {
return Double.compare(value, anotherDouble.value);
}
public int compareTo(Double anotherDouble) {
return Double.compare(value, anotherDouble.value);
}
引申知识
Java中double类型大小比较的五种方法
在Java中 int类型数据的大小比较可以使用双等号, double类型则不能使用双等号来比较大小,如果使用的话得到的结果将永远是不相等,即使两者的精度是相同的也不可以。下面介绍几种比较double数据是否相等的方法,前三种可以比较正负数,后两种方法只能用于比较两数是否想等以及正数的大小。
1.使用BigDecimal
extends Number implements Comparable<BigDecimal>
extends Number implements Comparable<BigDecimal>
Bigdecimal通过字符串构造出来的不会丢失精度,
但是使用double,float的浮点型数据构造出来的bigdecimal会丢失精度。
因为浮点型数据本来就不像整数型数据精确。
但是使用double,float的浮点型数据构造出来的bigdecimal会丢失精度。
因为浮点型数据本来就不像整数型数据精确。
BigDecimal可以使用字符串和 double 类型创建对象,并且建议使用字符串创建,
因为在看起来数字相等的情况下,使用字符串的精度更高。
因为在看起来数字相等的情况下,使用字符串的精度更高。
阿里规范:Decimal(小数的意思)
BigDecimal的等值比较应使用CompareTo方法,而不是equals方法
说明:equals方法会比较值和精度(1.0与1.00返回结果为false).而compareTo则会忽略精度
说明:equals方法会比较值和精度(1.0与1.00返回结果为false).而compareTo则会忽略精度
源码:
equals:
将此BigDecimal与指定的Object进行比较是否相等。与compareTo不同,此方法仅当两个BigDecimal对象的值和比例相等时才认为它们相等(因此,通过此方法进行比较时,2.0 不等于 2.00)。
compareTp:
将此BigDecimal与指定的BigDecimal进行比较。此方法认为两个值相等但比例不同(如 2.0 和 2.00)的BigDecimal对象是相等的。此方法优先于六个布尔比较运算符(<、==、>、>=、!=、<=)中的每一个的单独方法提供。执行这些比较的建议习惯用法是: (x.compareTo(y) < op > 0) ,其中 < op > 是六个比较运算符之一。
equals:
将此BigDecimal与指定的Object进行比较是否相等。与compareTo不同,此方法仅当两个BigDecimal对象的值和比例相等时才认为它们相等(因此,通过此方法进行比较时,2.0 不等于 2.00)。
compareTp:
将此BigDecimal与指定的BigDecimal进行比较。此方法认为两个值相等但比例不同(如 2.0 和 2.00)的BigDecimal对象是相等的。此方法优先于六个布尔比较运算符(<、==、>、>=、!=、<=)中的每一个的单独方法提供。执行这些比较的建议习惯用法是: (x.compareTo(y) < op > 0) ,其中 < op > 是六个比较运算符之一。
禁止使用构造方法BigDecimal(double)的方式把double值转化为BigDecimal对象
说明:Bigdecimal(double)存在精度损失风险,在精确计算或值比较的场景中可能会导致业务逻辑异常如:BigDecimal g = new BigDecimal(0.1F);实际的存储值为:0.10000000149正例:优先推荐入参为String的构造方法,或使用BigDecimal的valueOf方法,此方法内部其实执行了Double的toString,而Double的toString按double的实际能表达的精度对尾数进行截断。BigDecimal d1 = new BigDecimal("0.1");BigDecimal d2 = BigDecimal.valueOf(0.1)
2.使用包装类Double
compareTo是实现了compareble接口,
我觉的实现接口的普遍都是类要实例化
因为实现类的方法被@Override注解修饰
使用static修饰会报错
“Method does not override method from its superclass”
方法不会重写其超类中的方法
//2.使用包装类Double
Double dL = num1;
Double dR = num2;
if (dL.compareTo(dR) < 0)
System.out.println("num1 < num2");
else if (dL.compareTo(dR) == 0)
System.out.println("num1 == num2");
else
System.out.println("num1 > num2");
我觉的实现接口的普遍都是类要实例化
因为实现类的方法被@Override注解修饰
使用static修饰会报错
“Method does not override method from its superclass”
方法不会重写其超类中的方法
//2.使用包装类Double
Double dL = num1;
Double dR = num2;
if (dL.compareTo(dR) < 0)
System.out.println("num1 < num2");
else if (dL.compareTo(dR) == 0)
System.out.println("num1 == num2");
else
System.out.println("num1 > num2");
3.在误差范围内运行相等
4.转换成字符串
可以将double数据转换成string然后借助string的compareTo方法来间接实现比较两个double数据是否相等。注意这种方法只适用于比较精度相同的数据,并且是只能用于比较正数的大小,负数比较结果异常,不过可以用于比较两数是否相等,此时正负数对结果没有影响。
5.使用doubleToLongBits()方法
使用sun提供的Double.doubleToLongBits()方法,该方法可以将double转换成long型数据,从而可以使double按照long的方法(<, >, ==)判断是否大小和是否相等,但是,这种办法还是只能用于比较正数,负数结果异常,比较两数相等与否是没有问题的。
Java中“==”、“compareTo()”和“equals()”的区别
在比较两个对象或者数据大小的时候,经常会用到==、compareTo()和equals(),
尤其是在接入了Comparable接口后重写compareTo方法等场景,所以我们来理一下这三个的区别。
尤其是在接入了Comparable接口后重写compareTo方法等场景,所以我们来理一下这三个的区别。
1.等号——"==":
等号是最简单也最容易理解的,如果等号的两边是基本数据类型,比如int,double,那么等号就用来单纯的比较他们的数值大小
如果等号两边放的是两个对象,那么就会比较他们在内存当中的地址。
如果等号两边放的是两个对象,那么就会比较他们在内存当中的地址。
String a="abc";
String b="abc";
System.out.println(a==b);
答案是:true
因为相同的字符串内容,在地址上是一样。在Java中,String是有一个String pool的,里面存放了可以共享的字符串对象,在声明一个String对象后,会首先去找是否存在相同的String内容,如果有的话是不会创建新的对象的。在这里b实际上是引用了a的对象的值,他自己并没有创建对象,所以这里的答案是true。
但是如果我们接着
String c=new String(“abc”);
再
System.out.println(a==c);
那答案就是false,因为这二者的地址并不是一致的。
为什么呢?
因为这里是 new String 新创建对象。之前 “abc” 是编译器自动处理优化,因此可以去查找字符串池
String b="abc";
System.out.println(a==b);
答案是:true
因为相同的字符串内容,在地址上是一样。在Java中,String是有一个String pool的,里面存放了可以共享的字符串对象,在声明一个String对象后,会首先去找是否存在相同的String内容,如果有的话是不会创建新的对象的。在这里b实际上是引用了a的对象的值,他自己并没有创建对象,所以这里的答案是true。
但是如果我们接着
String c=new String(“abc”);
再
System.out.println(a==c);
那答案就是false,因为这二者的地址并不是一致的。
为什么呢?
因为这里是 new String 新创建对象。之前 “abc” 是编译器自动处理优化,因此可以去查找字符串池
引申知识
String a="abc"与String b=new String("abc")的区别
第1种:
String a="abc";
String b="abc";
System.out.print(a==b);
结果:true
原因:编译时,String a="abc" 会把"abc"放到常量池中,再定义b时,因为常量池中已存在“abc”,所有不会再创建,运行时JVM(JAVA虚拟机)则认为这两个变量赋的是同一个对象,所以返回true。
第5种
String a="abcdef";
String b="";
String c=a+b;
System.out.print(c=="abcdef");
结果:false
原因:编译时,先将"abcedf"放在常量池中,而c的值则是在运行时在堆里创建的。所以为false。
1、常量池
指的是在编译期确定,并被保存在已编译的字节码文件中的一些数据,它包括类、方法、接口等中的常量,存放字符串常量和基本类型常量(public static final)。
2、栈(stack)
主要保存基本数据类型(或者叫内置类型)(char、byte、short、int、long、float、double、boolean)和对象的引用,数据可以共享,速度仅次于寄存器(register),快于堆。
3、堆(heap):用于存储对象
3、== :引用是否指向同一个对象
4、equals():比较里面的数值是否相等时
指的是在编译期确定,并被保存在已编译的字节码文件中的一些数据,它包括类、方法、接口等中的常量,存放字符串常量和基本类型常量(public static final)。
2、栈(stack)
主要保存基本数据类型(或者叫内置类型)(char、byte、short、int、long、float、double、boolean)和对象的引用,数据可以共享,速度仅次于寄存器(register),快于堆。
3、堆(heap):用于存储对象
3、== :引用是否指向同一个对象
4、equals():比较里面的数值是否相等时
第1种:
String a="abc";
String b="abc";
System.out.print(a==b);
结果:true
原因:编译时,String a="abc" 会把"abc"放到常量池中,再定义b时,因为常量池中已存在“abc”,所有不会再创建,运行时JVM(JAVA虚拟机)则认为这两个变量赋的是同一个对象,所以返回true。
第2种:
String a=new String("abc");
String b=new String("abc");
System.out.print(a==b);
结果:false
第二种中用构造器创建的对象是不会被放入常量池中,这句话是不对的。事实上,只要有引号的引用它就会在常量池中创建字符串,所以常量池中是存在abc的,只不过new的过程在堆中又创建了字符串abc。
String a=new String("abc");
String b=new String("abc");
System.out.print(a==b);
结果:false
第二种中用构造器创建的对象是不会被放入常量池中,这句话是不对的。事实上,只要有引号的引用它就会在常量池中创建字符串,所以常量池中是存在abc的,只不过new的过程在堆中又创建了字符串abc。
第3种
String a="abc";
String b=new String("abc");
System.out.print(a==b);
结果:false
原因:同上
String a="abc";
String b=new String("abc");
System.out.print(a==b);
结果:false
原因:同上
第4种
String a="abcdef";
System.out.print(a=="abcdef");
结果:true
原因:运行出现的字符串常量,若是在常量池中出现过,则JVM会认为同一个对象,以节省内存开销,所以这两个字符串会被认为是同一个对象。
String a="abcdef";
System.out.print(a=="abcdef");
结果:true
原因:运行出现的字符串常量,若是在常量池中出现过,则JVM会认为同一个对象,以节省内存开销,所以这两个字符串会被认为是同一个对象。
第5种
String a="abcdef";
String b="";
String c=a+b;
System.out.print(c=="abcdef");
结果:false
原因:编译时,先将"abcedf"放在常量池中,而c的值则是在运行时在堆里创建的。所以为false。
2.compareTo()
注意这里是String类型,其他同理
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;
}
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;
}
可以观察出,这里实际上是获取的字符串(也可以是其他对象)的长度,然后作减法,这里的减法就是ASCII码的减法,所以compareTo()会返回数字,如果两个字符串内容相同,会返回0,字符串a大于字符串b,会返回相差的ASCII码的正数,字符串a小于字符串b,会返回相差的ASCII码的负数。
所以 System.out.println(a.compareTo(b))的答案是:0
所以 System.out.println(a.compareTo(b))的答案是:0
3.equals()
注意这里是String类型,其他同理
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
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;
}
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
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;
}
可以观察出,equals是先用等号(==)直接来比较两个对象在内存当中的地址,如果相等会直接返回true,如果这两个对象的地址不一样,就会考虑这两个对象是不是String类型的,如果是String类型的,那先比较两个字符串长度是否一样,如果长度不一致,那100%不相等,直接返回false。长度一致则逐个比较
4.compareTo()和equals的区别
compareTo()会返回二者的差值,即返回的是一个数字;而equals就简单一些,只返回true或者false。
最后,compareTo()和equals()都可以判断其他基本数据类型,比如说Integer,Java的源码中对这两者方法都做了一些重载,可以根据参数的类型去自动匹配相应的方法,他们的原理也非常简单,只是一些简单的减法或者(?:)这类判断。
最后,compareTo()和equals()都可以判断其他基本数据类型,比如说Integer,Java的源码中对这两者方法都做了一些重载,可以根据参数的类型去自动匹配相应的方法,他们的原理也非常简单,只是一些简单的减法或者(?:)这类判断。
java.util.Date
public int compareTo(Date anotherDate) {
long thisTime = getMillisOf(this);
long anotherTime = getMillisOf(anotherDate);
return (thisTime<anotherTime ? -1 : (thisTime==anotherTime ? 0 : 1));
}
long thisTime = getMillisOf(this);
long anotherTime = getMillisOf(anotherDate);
return (thisTime<anotherTime ? -1 : (thisTime==anotherTime ? 0 : 1));
}
引申知识
new Date()返回的是系统的毫秒时间
public Date() {
this(System.currentTimeMillis());
}
this()调用的是本地的构造函数,
也就是下面这个函数,参数类型是 long
public Date() {
this(System.currentTimeMillis());
}
this()调用的是本地的构造函数,
也就是下面这个函数,参数类型是 long
public static native long currentTimeMillis();
返回类型是long类型
System.currentTimeMillis()
自然就可以使用下面的构造函数了
public Date(long date) {
fastTime = date;
}
返回类型是long类型
System.currentTimeMillis()
自然就可以使用下面的构造函数了
public Date(long date) {
fastTime = date;
}
分配一个Date对象并对其进行初始化,
以便它表示由字符串s指示的日期和时间,
这就像由parse方法解释一样。
已弃用
从 JDK 1.1 版开始,由DateFormat.parse(String s)取代。
参数:
s – 日期的字符串表示形式。
也可以看看:
DateFormat , parse(String)
@Deprecated
public Date(String s) {
this(parse(s));
}
以便它表示由字符串s指示的日期和时间,
这就像由parse方法解释一样。
已弃用
从 JDK 1.1 版开始,由DateFormat.parse(String s)取代。
参数:
s – 日期的字符串表示形式。
也可以看看:
DateFormat , parse(String)
@Deprecated
public Date(String s) {
this(parse(s));
}
引申知识
public abstract class DateFormat extends Format
SimpleDateFormat
public Date parse(String source) throws ParseException
{
ParsePosition pos = new ParsePosition(0);
Date result = parse(source, pos);
if (pos.index == 0)
throw new ParseException("Unparseable date: \"" + source + "\"" ,
pos.errorIndex);
return result;
}
{
ParsePosition pos = new ParsePosition(0);
Date result = parse(source, pos);
if (pos.index == 0)
throw new ParseException("Unparseable date: \"" + source + "\"" ,
pos.errorIndex);
return result;
}
编写 stringToDate
yyyy-MM-dd HH:mm:ss大小写区别
首先结论:yyyy-MM-dd HH:mm:ss是最标准的写法
下面展示不同出现的结果
月份如果小写的话 就是yyyy-mm-dd HH:mm:ss
这样子就会月份和分钟混了,两个都是小写mm,最后两个都显示分钟
MM是月份,mm是分钟
产生如下问题
2019-18-03 12:18:33 //18问题
小时如果小写的话 就是yyyy-MM-dd hh:mm:ss
这样子如果是下午两点半 大写的HH会表示为14:30 小写的hh会表示为2:30
2019-18-03 2:30:33
HH为24小时制,hh为12小时制
2019-18-03 14:30:33
首先结论:yyyy-MM-dd HH:mm:ss是最标准的写法
下面展示不同出现的结果
月份如果小写的话 就是yyyy-mm-dd HH:mm:ss
这样子就会月份和分钟混了,两个都是小写mm,最后两个都显示分钟
MM是月份,mm是分钟
产生如下问题
2019-18-03 12:18:33 //18问题
小时如果小写的话 就是yyyy-MM-dd hh:mm:ss
这样子如果是下午两点半 大写的HH会表示为14:30 小写的hh会表示为2:30
2019-18-03 2:30:33
HH为24小时制,hh为12小时制
2019-18-03 14:30:33
Java中强大的 接口 :Format
Format的直接子类包括DateFormat、NumberFormat和MessageFormat。下面一一进行介绍
链接 :
https://www.jianshu.com/p/c8f16cab35e1
链接 :
https://www.jianshu.com/p/c8f16cab35e1
接口 : DateFormat
子类:
SimpleDateFormat
SimpleDateFormat
接口 :NumberFormat
子类:
DecimalFormat
DecimalFormat
Java DecimalFormat四舍五入的坑及正确用法
一、DecimalFormat四舍五入的坑
一、DecimalFormat四舍五入的坑
1.1 有时候我们在处理小数保留几位小数时,想到了DecimalFormat这个类的使用,百度搜一把可能用到以下方式。
复制代码
1 public static void main(String[] args) {
2 String str="3.145";
3 System.out.println(round1(str));
4 }
5
6 static String round1(String str){
7 double a=Double.parseDouble(str);
8 DecimalFormat df=new DecimalFormat("###.00");
9 return df.format(a);
10 }
复制代码
1.2 初看好像没什么问题,四舍五入保留两位小数,最后输出3.15。当然精度要求不高,也无需计较。当涉及到精确统计时,这里的坑来了将上面的字符串改为“5”前面为奇数,如“3.155”,就瓜了,输出3.15。显然这里没满足要求,不是我们学校里的四舍五入。再上一段代码。
1 static String round2(String str){
2 double a=Double.parseDouble(str);
3 DecimalFormat df=new DecimalFormat("###.00");
4 df.setRoundingMode(RoundingMode.HALF_UP);
5 return df.format(a);
6 }
这里可以看到这个setRoundingMode()方法可以设定四舍五入的模式,原来四舍五入不光有我们学校里学的那种,还有其他模式。DecimalFormat默认情况下,它使用 RoundingMode.HALF_EVEN,此舍入模式也称为“银行家舍入法”,主要在美国使用。RoundingMode.HALF_UP这个模式才是我们学校里学的标准四舍五入模式。以上代码虽然舍了学校型模式仍然不准确,应该将double类型改为BigDecimal类型。
复制代码
1 public static void main(String[] args) {
2 String str="3.145";
3 System.out.println(round1(str));
4 }
5
6 static String round1(String str){
7 double a=Double.parseDouble(str);
8 DecimalFormat df=new DecimalFormat("###.00");
9 return df.format(a);
10 }
复制代码
1.2 初看好像没什么问题,四舍五入保留两位小数,最后输出3.15。当然精度要求不高,也无需计较。当涉及到精确统计时,这里的坑来了将上面的字符串改为“5”前面为奇数,如“3.155”,就瓜了,输出3.15。显然这里没满足要求,不是我们学校里的四舍五入。再上一段代码。
1 static String round2(String str){
2 double a=Double.parseDouble(str);
3 DecimalFormat df=new DecimalFormat("###.00");
4 df.setRoundingMode(RoundingMode.HALF_UP);
5 return df.format(a);
6 }
这里可以看到这个setRoundingMode()方法可以设定四舍五入的模式,原来四舍五入不光有我们学校里学的那种,还有其他模式。DecimalFormat默认情况下,它使用 RoundingMode.HALF_EVEN,此舍入模式也称为“银行家舍入法”,主要在美国使用。RoundingMode.HALF_UP这个模式才是我们学校里学的标准四舍五入模式。以上代码虽然舍了学校型模式仍然不准确,应该将double类型改为BigDecimal类型。
二、学校型四舍五入几种正确使用
2.1 String直接格式化
1 static String round3(String str){
2 double d=Double.parseDouble(str);
3 return String.format("%.2f",d);
4 }
2.2 BigDecimal结合DecimalFormat,BigDecimal比较好性能,数据处理量大不建议使用。
1 static String round4(String str){
2 BigDecimal bigDecimal=new BigDecimal(str);
3 DecimalFormat df=new DecimalFormat("###.00");
4 df.setRoundingMode(RoundingMode.HALF_UP);
5 return df.format(bigDecimal);
6 }
2.3 BigDecimal单独使用,这个类也自带舍入模式设定方法。
1 static String round5(String str){
2 BigDecimal bigDecimal=new BigDecimal(str);
3 return String.valueOf(bigDecimal.setScale(2,RoundingMode.HALF_UP));
4 }
1 static String round3(String str){
2 double d=Double.parseDouble(str);
3 return String.format("%.2f",d);
4 }
2.2 BigDecimal结合DecimalFormat,BigDecimal比较好性能,数据处理量大不建议使用。
1 static String round4(String str){
2 BigDecimal bigDecimal=new BigDecimal(str);
3 DecimalFormat df=new DecimalFormat("###.00");
4 df.setRoundingMode(RoundingMode.HALF_UP);
5 return df.format(bigDecimal);
6 }
2.3 BigDecimal单独使用,这个类也自带舍入模式设定方法。
1 static String round5(String str){
2 BigDecimal bigDecimal=new BigDecimal(str);
3 return String.valueOf(bigDecimal.setScale(2,RoundingMode.HALF_UP));
4 }
接口 :MessageFormat
MessageFormat form = new MessageFormat("The disk \"{1}\" contains {0}.");
String类中的format方法
String result1 = String.format("小明今年%d岁,他住在%s,他的月工资有%.2f", 25,"北京市",6633.435);
System.out.println(result1);//输出:小明今年25岁,他住在北京市,他的月工资有6633.44
/*****************************************************/
double num = 123.4567899;
String result2 = String.format("%e", num);
System.out.println(result2);//输出:1.234568e+02
System.out.println(result1);//输出:小明今年25岁,他住在北京市,他的月工资有6633.44
/*****************************************************/
double num = 123.4567899;
String result2 = String.format("%e", num);
System.out.println(result2);//输出:1.234568e+02
总结
1.Format中的子类都是不同步,所以需要注意线程安全问题
2.可能在某些地方我解释的还是不太清楚。学习最重要的是多去尝试,多编写代码测试,如果仅仅靠看就能学会的话,那你就看吧、
1.Format中的子类都是不同步,所以需要注意线程安全问题
2.可能在某些地方我解释的还是不太清楚。学习最重要的是多去尝试,多编写代码测试,如果仅仅靠看就能学会的话,那你就看吧、
时间比较的时候,先获取毫毛值
在进行比较
在进行比较
8大引用类型转换
valueOf()方法进行转换成相应包装类型
引申知识
String.valueOf()
BigDecimal.valueOf()
应用场景:
1、BigInteger适合保存比较大的整型
2、BigDecimal适合保存精度更高的浮点型(小数)
1、BigInteger适合保存比较大的整型
2、BigDecimal适合保存精度更高的浮点型(小数)
Decimal英文意思是小数
BigDecimal意思是大的小数
BigDecimal意思是大的小数
BigInteger
//当我们编程中,需要处理很大的整数,long不够用
//可以使用BigInteger的类来搞定
long l = 234459897895499999999999999999999l;//编译器报 “Long number too large”
System.out.println("l=" + l);
BigInteger bigInteger = new BigInteger("234459897895499999999999999999999");
System.out.println(bigInteger);
//1.在对BigInteger进行加减乘除的时候,需要使用对应的方法,不能直接进行 + - * /
BigInteger bigInteger2 = new BigInteger("100");
BigInteger add = bigInteger.add(bigInteger2);
System.out.println(add);//+
BigInteger subtract = bigInteger.subtract(bigInteger2);
System.out.println(subtract); //减
BigInteger divide = bigInteger.divide(bigInteger2);
System.out.println(divide);//除
//可以使用BigInteger的类来搞定
long l = 234459897895499999999999999999999l;//编译器报 “Long number too large”
System.out.println("l=" + l);
BigInteger bigInteger = new BigInteger("234459897895499999999999999999999");
System.out.println(bigInteger);
//1.在对BigInteger进行加减乘除的时候,需要使用对应的方法,不能直接进行 + - * /
BigInteger bigInteger2 = new BigInteger("100");
BigInteger add = bigInteger.add(bigInteger2);
System.out.println(add);//+
BigInteger subtract = bigInteger.subtract(bigInteger2);
System.out.println(subtract); //减
BigInteger divide = bigInteger.divide(bigInteger2);
System.out.println(divide);//除
BigDecimal
//当我们需要保存一个精度很高的数时,double不够用
//可以用BigDecimal
//double d=19999.2323223423493423423432423;
//System.out.println(d);//输出 19999.2323223423 精度缺失
BigDecimal bigDecimal = new BigDecimal("19999.2323223423493423423432423");
BigDecimal bigDecimal2 = new BigDecimal("1.1");
System.out.println(bigDecimal);
//1.如果对BigDecimal进行运算,比如加减乘除,需要使用对应的方法
//2.创建一个需要操作的BigDecimal然后调用相应的方法即可
System.out.println(bigDecimal.add(bigDecimal2));//+
System.out.println(bigDecimal.subtract(bigDecimal2));//-
System.out.println(bigDecimal.multiply(bigDecimal2));//*
//在调用divide 方法时,指定精度即可.BigDecimal.ROUND_CEILING
//如果有无限循环小数,就会保留分子的精度 就是定义的bigDecimal 数对应的分子的精度,小数点后的位数
//不指定精度,可能就会抛出异常
System.out.println(bigDecimal.divide(bigDecimal2, BigDecimal.ROUND_CEILING));// / 可能抛出异常ArithmeticException
//可以用BigDecimal
//double d=19999.2323223423493423423432423;
//System.out.println(d);//输出 19999.2323223423 精度缺失
BigDecimal bigDecimal = new BigDecimal("19999.2323223423493423423432423");
BigDecimal bigDecimal2 = new BigDecimal("1.1");
System.out.println(bigDecimal);
//1.如果对BigDecimal进行运算,比如加减乘除,需要使用对应的方法
//2.创建一个需要操作的BigDecimal然后调用相应的方法即可
System.out.println(bigDecimal.add(bigDecimal2));//+
System.out.println(bigDecimal.subtract(bigDecimal2));//-
System.out.println(bigDecimal.multiply(bigDecimal2));//*
//在调用divide 方法时,指定精度即可.BigDecimal.ROUND_CEILING
//如果有无限循环小数,就会保留分子的精度 就是定义的bigDecimal 数对应的分子的精度,小数点后的位数
//不指定精度,可能就会抛出异常
System.out.println(bigDecimal.divide(bigDecimal2, BigDecimal.ROUND_CEILING));// / 可能抛出异常ArithmeticException
parse+引用类型
parseByte
parseInt
parseLong
parseFloat
parseDouble
final可以修饰类、属性、方法和局部变量。
使用场景
当不希望类被继承时;
当不希望父类的某个方法被子类覆盖、重写时;
当不希望类的某个属性值被修改时;
当不希望某个局部变量被修改时。
注意事项和细节:
子主题
1.final修饰的属性又叫常量,一般用大写字母和下划线命名;
2.final修饰的属性必须赋初始值,且一旦赋值不能被修改;(在定义时、构造器、代码块中都可以进行赋值)
3.如果final修饰的属性是静态的,则初始化的位置只能是定义时和静态代码块中,不能在构造器中赋值;
4.final类不能继承,但是可以实例化对象;
5.如果类不是final类,但是含有final方法,则该方法虽然不能重写,但是可以被继承。
6.一般来说,如果一个类已经是final类了,就没有必要再将方法修饰成final方法了。
7.final和static搭配使用,效率更高,底层编译器做了优化处理。
class Demo{
public static final int i = 16;
static{
system.out.println("我想hj了");
}
}
8.包装类(Integer,Double,Float,Boolean等都是final),String也是final类。
具体工作任务与完成情况
按时间
按项目
亮点与不足
工作亮点
工作不足
改进措施
个人方面
团队协作方面
下一阶段工作计划

收藏
0 条评论
下一页
为你推荐
查看更多