做个小笔记,激励自己学习,方便查阅,欢迎小伙伴们提意见,彼此提高~
一、 一切皆对象
Java是非常纯粹的面向对象的语言。对象的生成是通过new 来创建,但是所谓的对象变量,如String s=new String("abc"); s 不是一个对象,而是对象的引用,它存储着可以调用到该对象的信息,类似于一个入口。 String s1=s; 赋值时赋得自然是引用,因此只要s1改变,s 也会跟着改变。
存储位置:
栈中存储的是确定生命周期、大小的项,如对象的引用(4 bytes)、基本类型。位于RAM中,向下移动分配新内存。存取速度快;
堆中存储真正的对象,大小和生命周期灵活分配,空的Object是8bytes。位于RAM中,向上移动分配内存,存取速度稍慢。
特例:8个基本类型和void
类型 | 字节数 | 包装类 |
char | 2 | Character |
boolean | 1 | Boolean |
byte | 1 | Byte |
short | 2 | Short |
int | 4 | Integer |
long | 8 | Long |
float | 4 | Float |
double | 8 | Double |
void | - | Void |
ps: 这9个特例是由JVM预先创建的Class 对象;JVM采用unicode编码, 一个字符2个字节;这些基本类型存储的是字面值,而不是引用,他们构造的数组是一个对象,而不是基本类型,包括它在内的素有类都继承自根类Object ;
可以使用如下代码验证一下基本类型的数组和对象数组的区别
import java.util.*;
public class ObjectArray{
public static void main(String[] args){
int [] intArray1 = new int[]{1,2,3};
int [] intArray2 = new int[4];
int[][] intArray2D = new int[2][3];
String [] stringArray = new String[]{"a","b","c"};
System.out.println(intArray1.getClass().equals(intArray2.getClass()));//true, int[] 是一个类 extends Object
System.out.println(intArray1.getClass().equals(stringArray.getClass())); //false
System.out.println(intArray1.getClass().equals(intArray2D.getClass())); //false,int[][] 是Object[]
System.out.println(intArray1.getClass().getName()); // [I ,应该代表着int []的意思
System.out.println(intArray1.getClass().getSuperclass().getName()); //超类java.lang.Object
System.out.println(stringArray.getClass().getName()); //[L java.lang.String
System.out.println(stringArray.getClass().getSuperclass().getName()); //java.lang.Object
//Object[] extends Object
Object aObj1 = intArray1;
Object aObj2 = stringArray;
//Object[] aObj3 = intArray1;//编译不通过,required Object[],found int[]
Object[] aObj4 = intArray2D;
Object[] aObj5 = stringArray;
System.out.println(intArray1); //打印出对象的HashCode [I@9789f68
System.out.println(stringArray); //打印出对象的HashCode [L java.lang.String;@16adf9
System.out.println(Arrays.asList(intArray1)); //打印出HashCode [[I @9673f13
System.out.println(Arrays.asList(stringArray)); //打印出[a,b,c]
}
}
二、 操作符
1、 == 和 equals
==和!= 用于基本类型时,比较的是字面值是否相等;用于对象时,判断的是两个比较对象的引用是否相同,i.e. 二者在内存中的位置(hashCode)是否一致;如果要只单纯比较两个对象的字面值,可以重写equals方法
常量池(Constant Pool)用于存储编译期就已经确定的数据,如字符串常量、基本类型常量,如果有就不会在创建只是将引用指向该位置。
String s=new String("hello");如果常量池中没有该字符串,那这句话实际上创建了两个对象,一个把内容保存在常量区,一个把对象保存在堆中。
可以通过以下代码比较二者的不同
public class StringEquals{
public static void main(String[] args){
String s1="thinking ";
String s2="in java";
String s3="thinking in java";
String s4="thinking "+"in java";
String s5=s1+s2;
String s6=new String("thinking in java");
System.out.println(s3=s4); //thinking in java ;普通的赋值返回s3
System.out.println(s3==s4);//true ;常量池中已经存在
System.out.println(s5==s4);//false ;s5需要等到运行时才知道他的值,不在常量池中
System.out.println(s6==s5);//false ;两个对象引用不一致
System.out.println(s6.equals(s5));//true ;String改写了equals方法,内容一致返回true
System.out.println(s6.equals(s4));//true ;String改写了equals方法,内容一致
}
}
2、位操作
<< 向左移位,低位补0;>>向右移位,负数高位补1,正数高位补0;>>>逻辑右移位,无论正负,高位补0
可以用位操作来测算基本类型所占的位数
public class TypeRange{
public static void main(String[] args){
char c=1;
byte b=1;
short s=1;
int i=1;
long L=1L;
int cnt;
for(cnt=1;(b<<=1)!=0;cnt++);//向左移位,即每次乘2,直到越界,变成0
System.out.println("byte bits: "+cnt);//8
for(cnt=1;(c<<=1)!=0;cnt++);
System.out.println("char bits: "+cnt);//16
for(cnt=1;(s<<=1)!=0;cnt++);
System.out.println("short bits: "+cnt);//16
for(cnt=1;(i<<=1)!=0;cnt++);
System.out.println("int bits: "+cnt);//32
for(cnt=1;(L<<=1)!=0;cnt++);
System.out.println("long bits: "+cnt);//64
}
}
对char,short,byte 进行移位操作的时候,它们会先被转换成int,然后被截断返回原来的类型;boolean 值不能做算术运算,只有逻辑运算