一. 对象和类型

1.基本类型

java里面基本上全是对象,但是有8种基本类型,这些基本类型不是对象,但是都有对应的对象类型,使用这些基本类型的效率比使用他们的对象的效率要高,如下代码
final int size = 10000;
		long start = System.currentTimeMillis();
		
		for(int i = 0;i < size;i++){
			int a = 0;
		}
		long mid = System.currentTimeMillis();
		for(int i = 0;i < size;i++){
			int b = new Integer(0);
		}
		long end = System.currentTimeMillis();
		System.out.println("创建基本类型所用的时间是" + (mid - start) + ",创建对象所用的时间是" + (end - mid));

创建基本类型所用的时间是0,创建对象所用的时间是2

并且他们存储空间是不变的,不管是32还是64的电脑,这是java代码易于移植的原因之一,列表如下:
boolean Boolean
char 16  bit Character
byte 8 bit Byte
short 16 bit Short
int 32 bit Integer
long 64 bit Long
float 32 bit Float
double 64 bit Double
基本类型和它对应的对象可以互相转化,基本类型转化成对象称作打包,对象转化成基本类型称作解包


int c = 100;
		System.out.println(c);
		Integer cobject = c;
		System.out.println(cobject);
		Integer dobject = new Integer(100);
		System.out.println(dobject);
		int d = dobject;
		System.out.println(d);


100
100
100
100


在这个转化这里还有一个很有意思的事情,java中判断二个对象是否“相等”有二种办法,==和equals方法,二者的区别是==是判断二个对象的地址是否相同,equals则是判断对象里面的内容是否相同,
Integer cobject = new Integer(100);
		Integer dobject = new Integer(100);
		System.out.println("cobject==dobject:" + (cobject == dobject));
		System.out.println("cobject.equals(dobject):" + (cobject.equals(dobject)));
		
		Integer cobject0 = 100;
		Integer dobject0 = 100;
		System.out.println("cobject0==dobject0:" + (cobject0 == dobject0));
		System.out.println("cobject0.equals(dobject0):" + (cobject0.equals(dobject0)));

cobject==dobject:false
cobject.equals(dobject):true
cobject0==dobject0:true
cobject0.equals(dobject0):true
可以看到相同值的基本类型的地址是相同的,下面一个程序输出供思考:
Integer cobject0 = 100;
		Integer dobject0 = 100;
		int eobject = 100;
		System.out.println("cobject0==dobject0:" + (cobject0 == dobject0));
		System.out.println("cobject0.equals(dobject0):" + (cobject0.equals(dobject0)));
		System.out.println("cobject0==eobject:" + (cobject0 == eobject));
		System.out.println("cobject0.equals(eobject):" + (cobject0.equals(eobject)));

2.其他常用类型String

另一个虽然不是基本类型,但是确是最常用的类型,也就是String,提到String就不得不提到StringBuilder和StringBuffer,这二种类型的主要是提高String的连接速度,代码如下:
String str = "aaaaa";
		String stra = "bbbbb";
		final int length = 10000;
		StringBuffer strBuffer = new StringBuffer(str);
		StringBuilder strBuilder = new StringBuilder(str);
		long start0 = System.currentTimeMillis();
		for(int i = 0;i < length;i++){
			str += stra;
		}
		long mid0 = System.currentTimeMillis();
		for(int i = 0;i < length;i++){
			strBuffer.append(stra);
		}
		long mid1 = System.currentTimeMillis();
		for(int i = 0;i < length;i++){
			strBuilder.append(stra);
		}
		long end0 = System.currentTimeMillis();
                                 System.out.println("String+所用的时间是" + (mid0 - start0));
		System.out.println("StringBuffer所用的时间是" + (mid1 - mid0));
		System.out.println("StringBuilder所用的时间是" + (end0 - mid1));
                String str1 = "aaaaa";
		String stra1 = "bbbbb";
		//final int length = 10000;
		long start1 = System.currentTimeMillis();
		for(int i = 0;i < length;i++){
			str1.concat(stra1);
		}
		long end1 = System.currentTimeMillis();
		System.out.println("String.concat所用的时间是" + (end1 - start1));

String+所用的时间是301
StringBuffer所用的时间是1
StringBuilder所用的时间是0
String.concat所用的时间是0


可以看到效率相差的比较大,因为String的+操作是新建一个String对象,然后传值过去,StringBuilder和StringBuffer都是直接在当前String后面添加字符串,不会创建新字符串,那么问题来了,StringBuffer和StringBuilder的区别是什么呢?具体如下图:
//01.png,02.png
StringBuffer的效率差一点,但是线程安全的


3.其他常用类型BigInteger和BigDecimal

这二种类型其实也不是很常见,但是我最近在公司做项目总是用到,因为公司数据仓库的主键很多都是BigInteger类型的,涉及金钱的类型都是Decimal类型的,也就是对应的java类型BigDecimal,这二种类型的出现是因为Integer类型的大小受限,某些情况加使用Integer会出现越界的情况,Float和Double也有同样的限制,所以出现了BigDecimal


4.基本类型作为局部变量和类成员的区别


如果你编写一个int a;这样的代码,那么它的值是多少,其实这取决于这行代码的位置,如果是类的成员,会被设置成默认值0,如果是函数内的变量,a现在还没有值,下面的代码说明这个问题:
//03.png


5.对象的equals方法

在知道了equals方法和==的区别之后,可以预测一下下面代码的输出:
public class Dog {

	private String name;
	private String say;
	
	public Dog(String name,String say){
		this.name = name;
		this.say = say;
	}
	
	public static void main(String[] args) {
		Dog spot = new Dog("spot", "Ruff");
		Dog scruffy = new Dog("spot","Ruff");
		System.out.println("spot==scruffy?" + (spot == scruffy));
		System.out.println("spot.equals(scruffy)?" + spot.equals(scruffy));
	}
}

输出如下:
spot==scruffy?false
spot.equals(scruffy)?false
你这不是在逗我么,二个变量地址不同==不同,这可以理解,但是内容明明是相同的,但是java默认的equals方法其实也是对比地址是否相同,想要改变这个,需要自己重写equals方法才可以,如下:


public class Dog {

	private String name;
	
	private String say;
	
	public Dog(String name,String say){
		this.name = name;
		this.say = say;
	}
	
	@Override
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		if(!(obj  instanceof Dog)){
			return false;
		}
		
		return this.name.equals( ((Dog)(obj)).getName() ) &&&& this.say.equals( ((Dog)(obj)).getSay() );
	}
	public static void main(String[] args) {
		Dog spot = new Dog("spot", "Ruff");
		Dog scruffy = new Dog("spot","Ruff");
		System.out.println("spot==scruffy?" + (spot == scruffy));
		System.out.println("spot.equals(scruffy)?" + spot.equals(scruffy));
	}
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getSay() {
		return say;
	}

	public void setSay(String say) {
		this.say = say;
	}
}


相关内容:
前言
对象和类型
操作符和引用
流程控制语句
初始化和清理
访问控制
组合和继承
接口和多态
接口与抽象类
容器
异常
类型信息
泛型
数组
IO系统
枚举类型
注解
多线程
总结