| int(4字节) | Integer |
| short(2字节) | Short |
| long(8字节) | Long |
| float(4字节) | Float |
| double(8字节) | Double |
| byte(1字节) | Byte |
| char(2字节) | Character |
| boolean(未定) | Boolean |
类,接口,数组
● 从概念方法来说:
● 从内存方法
● 数据类型在 栈和堆中的区别
自动根据数值创建对应的 Integer对象,这就是装箱。
拆箱,就是自动将包装器类型转换为基本数据类型。
从反编译得到的字节码内容可以看出,在装箱的时候自动调用的是Integer的valueOf(int)方法,创建对应的对象。
而在拆箱的时候自动调用的是Integer的intValue方法。
public class Tinterger {
public static void main(String[] args) {
Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 321;
Integer f = 321;
Long g = 3L;
Long h = 2L;
Integer k = 2;
Double M = 2.0;
System.out.println(c==d); //true判断对象地址相同,因为在-128~127
System.out.println(e==f); //false判断对象地址相同,equal和==是一样的
System.out.println(e.equals(f)); //true 基本类型的对象重写了equal方法
System.out.println(c==(a+b)); //true 进行运算自动拆箱比较值
System.out.println(d.equals(c)); // //true equal比较值是否相同
System.out.println(c.equals(a+b)); // true equal比较值是否相同
System.out.println(g==(a+b));// true equal比较值是否相同
System.out.println(g.equals(a+b));// false equal比较值是否相同
System.out.println(g.equals(a+h));// true equal比较值是否相同
System.out.println(k.equals(M));// true equal比较值是否相同
System.out.println(1==1.0);// true 比较值是否相同
}
}
从这2段代码可以看出,在通过valueOf方法创建Integer对象的时候,如果数值在[-128,127]之间,便返回指向IntegerCache.cache中已经存在的对象的引用;否则创建一个新的Integer对象。
Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
复制代码
private static class IntegerCache {
static final int high;
static final Integer cache[];
static {
final int low = -128;
// high value may be configured by property
int h = 127;
if (integerCacheHighPropValue != null) {
// Use Long.decode here to avoid invoking methods that
// require Integer's autoboxing cache to be initialized
int i = Long.decode(integerCacheHighPropValue).intValue();
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - -low);
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
private IntegerCache() {}
}
Double类的valueOf方法会采用与Integer类的valueOf方法不同的实现。很简单:在某个范围内的整型数值的个数是有限的,而浮点数却不是。
double类型的对象创建不使用缓存,每次都新建一个对象
Double、Float的valueOf方法的实现是类似的。
Boolean对象内置了两个静态属性对象True和False,每次创建的对象在获得值的都是这两个静态对象的一个,因此不同对象的true和false也都是这一个
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
public static final Boolean TRUE = new Boolean(true);
/**
* The Boolean object corresponding to the primitive
* value false.
*/
public static final Boolean FALSE = new Boolean(false);
string是一个类,但是可以和基本数据类型一样做符合赋值。
用来做金钱计算的类,不出现精度损失。金额计算必须用BigDecimalBigDecimal在进行入库时,数据库选择decimal类型, 长度可以自定义, 如18; 小数点我们项目中用的是2, 保留2位小数.此外还要注意的就是默认值, 一定写成0.00, 不要用默认的NULL, 否则在进行加减排序等操作时, 会带来转换的麻烦!
优先使用String构造方法,当double必须用作BigDecimal的源时,请使用Double.toString(double)转成String,然后使用String构造方法,或使用BigDecimal的静态方法valueOf,如下
功能介绍
BigDecimal(int) 创建一个具有参数所指定整数值的对象。
BigDecimal(double) 创建一个具有参数所指定双精度值的对象。
BigDecimal(long) 创建一个具有参数所指定长整数值的对象。
BigDecimal(String) 创建一个具有参数所指定以字符串表示的数值的对象。
===========================================================
add(BigDecimal) BigDecimal对象中的值相加,然后返回这个对象。
subtract(BigDecimal) BigDecimal对象中的值相减,然后返回这个对象。
multiply(BigDecimal) BigDecimal对象中的值相乘,然后返回这个对象。
divide(BigDecimal) BigDecimal对象中的值相除,然后返回这个对象。
toString() 将BigDecimal对象的数值转换成字符串。
doubleValue() 将BigDecimal对象中的值以双精度数返回。
floatValue() 将BigDecimal对象中的值以单精度数返回。
longValue() 将BigDecimal对象中的值以长整数返回。
intValue() 将BigDecimal对象中的值以整数返回。
public class TBigDecimal {
public static void main(String[] args) {
System.out.println(0.05 + 0.01);
BigDecimal a = new BigDecimal(1.01);
BigDecimal b = new BigDecimal(1.02);
BigDecimal c = new BigDecimal("1.01");
BigDecimal d = new BigDecimal("1.02");
System.out.println(a.add(b));
System.out.println(c.add(d));
}
public static BigDecimal add(double v1, double v2) {// v1 + v2
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2);
}
public static BigDecimal sub(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2);
}
public static BigDecimal mul(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2);
}
public static BigDecimal div(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
// 2 = 保留小数点后两位 ROUND_HALF_UP = 四舍五入
return b1.divide(b2, 2, BigDecimal.ROUND_HALF_UP);// 应对除不尽的情况
}
}
public class P{
static{
System.out.println("hell");
}
}
继承父类使用extend
- 抽象类也是类
- 满足类的基本继承规则
- 但是只能通过继承的子类来实例化
继承接口使用implent
- 接口可以被继承多个
- 接口的方法只能抽象,通过字类实现
- 子类必须实现所有接口方法
- 接口之间也可以相互继承
只定义一个函数的接口,这个函数可以用来解析表示lambda表达,到时候调用接口的函数就相当只需lambda式里的函数
另外java内置了一些函数式接口
interface Tti{
void printl();
}
public class TestL {
public static void main(String[] args) {
Tti t = ()-> {System.out.println("hello");};
t.printl();
}
}
不定义任何方法,仅仅用来被继承作为标识
当某个类除了他的外部类,不会被其他类使用时,使用成员内部类。这种情况下,内部类依附于外部类而存在,原因可能有: 1. 不可能有其他类使用该内部类。 2. 该内部类不能被其他类使用,可能会导致错误。这是内部类使用比较多的一个场景。
- 外部类可以直接访问内部类的成员和方法,但是必须先创建一个内部类的对象,再通过该对象使用其成员和方法。
- 内部类可以访问外部类的成员和方法,但是要注意,当内部类拥有和外部类相同的成员或方法时,会发生隐藏现象,默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式访问:外部类.this.成员变量/方法
- 内部类只是一个编译时的概念,一旦编译成功,就会成为完全不同的两个类。对于一个名为Outer的外部类和其内部定义的名为Inner的内部类,编译完后会生成Outer.class和Outer$Inner.class两个类
- 成员内部类与普通的成员没什么区别,可以与普通成员一样进行修饰和限制
public class Outer {
private int num = 1;
private int num1 = 10;
public class Inner {
private int num = 2;
public void func () {
System.out.println(Outer.this.num);
System.out.println(num1);
}
}
public static void main(String[] args) {
Outer outer = new Outer();
Inner inner = outer.new Inner();
inner.func();
}
}
静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。静态内部类是不需要依赖于外部类的,它不持有指向外部类对象的引用this,并且它不能使用外部类的非static成员或方法,这点很好理解,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体对象。它唯一的作用就是随着类的加载(而不是随着对象的产生)而产生。
public class Outer {
static class Inner {
public Inner () {
}
}
public static void main(String[] args) {
Outer.Inner innner = new Outer.Inner();
}
}
局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。局部内部类就像方法里面的局部变量一样,是不能有public、protected、private及static修饰符的。
public class Outer {
private int num = 1;
private int num1 = 10;
public void func () {
class Inner {
private int num = 2;
}
Inner inner = new Inner();
System.out.println(inner.num);
}
public static void main(String[] args) {
Outer outer = new Outer();
outer.func();
}
}
匿名内部类应该是平时我们编写代码时用的最多的,在编写事件监听的代码时匿名内部类不但方便,而且使代码更加容易维护。匿名内部类是唯一一种没有构造器的类。正因为其没有构造器,所以匿名内部类的使用范围非常有限,大部分匿名内部类用于接口回调。匿名内部类在编译的时候由系统自动起名为Outer$1.class。一般来说,匿名内部类用于集成其他类或者实现接口,并不需要增加额外的方法,只是对集成方法的实现或是重写。
public class Outer {
public void func () {
System.out.println("1");
}
public static void main(String[] args) {
Outer inner = new Outer() {
public void func () {
System.out.println("2");
}
};
inner.func();
}
}