1、==与equals
java的数据类型分为基本数据类型和复合数据类型;
基本数据类型(四类八种):整形:byte,short,int,long;浮点型:float,double;字符型:char;逻辑型:boolean;
在内存中直接存放于栈中,基本数据类型之间的比较用==比较,比较的是他们的值
复合数据类型:常指的是类,在内存中对象存在于堆中,对象引用则存在于栈中
==进行比较的时候,比较的是引用,即对象在内存中的地址;所以,同一个对象比较时,因内存地址相同,故返回true,不同对象比较时,因地址不同,故返回false;
equals进行比较的时候,需了解equals有没有被覆写,在java中,所有的类都继承于基类Object,在Object类中,equals方法是用==比较的,源码如下所示:
1 public booleanequals(Object obj) {
2 return (this ==obj);
3 }
所以,在默认情况下,equals同==一样,比较的对象的内存地址;
但是,一些类覆写了equals方法,比如String,Integer等,它们有自己的实现,如下String类中equals方法的实现所示:第一个同==一样,判断内存地址是否一样,即判断是否为同一个对象,如果是同一个对象则返回true,否则继续往下走,执行第二个if,第二个if的条件为参数是否为String的实例,如果是的的话,判断两个对象的字符序列是否相等;相等返回true,不相等返回false;
1 public booleanequals(Object anObject) {2 if (this ==anObject) {3 return true;4 }5 if (anObject instanceofString) {6 String anotherString =(String) anObject;7 int n =value.length;8 if (n ==anotherString.value.length) {9 char v1[] =value;10 char v2[] =anotherString.value;11 int i = 0;12 while (n-- != 0) {13 if (v1[i] !=v2[i])14 return false;15 i++;16 }17 return true;18 }19 }20 return false;21 }
举例说明:
1 classA{2
3 }4 public classTest {5
6
7 public static voidmain(String[] args) {8 //比较普通类,没有复写了equals方法;
9 A a = newA();10 A b = newA();11 System.out.println("use ==");12 System.out.println( a == b); //==比较
13 System.out.println("use equals ");14 System.out.println(a.equals(b));//equals比较
15 System.out.println();16 //String类,复写了equals方法;
17 String s1 = "abc";18 String s2 = "abc";19 String s3 =s1;20 String s4 = new String("abc");21 String s5 = new String("abc");22 //s1 and s2 use ==
23 System.out.println("s1 and s2 use ==");24 System.out.println(s1==s2);25 System.out.println();26 //s1 and s2 use equals
27 System.out.println("s1 and s2 use equals ");28 System.out.println(s1.equals(s2));29 System.out.println();30 //s1 and s3 use ==
31 System.out.println("s1 and s3 use ==");32 System.out.println(s3 ==s1);33 System.out.println();34 //s1 and s3 use equals
35 System.out.println("s1 and s3 use equals ");36 System.out.println(s1.equals(s3));37 System.out.println();38 //s4 and s5 use ==
39 System.out.println("s4 and s5 use ==");40 System.out.println(s4 ==s5);41 System.out.println();42 //s4 and s5 use equals
43 System.out.println("s4 and s5 use equals ");44 System.out.println(s4.equals(s5));45 System.out.println();46 //s1 and s4 use ==
47 System.out.println("s1 and s4 use ==");48 System.out.println(s1 ==s4);49 System.out.println();50 //s1 and s4 use equals
51 System.out.println("s1 and s4 use equals ");52 System.out.println(s1.equals(s4));53 }54 }
运行结果:
use ==
false
use equals
false
----普通类A继承了Object类,但没有复写equals方法,故==和equals都是比较的内存地址,a和引用了两个对象,所有返回的都是false
s1 and s2 use ==
true
s1 and s2 use equals
true
----s1和s2指向同一个对象“abc”;故都返回true;
s1 and s3 use ==
true
s1 and s3 use equals
true
----s3=s1,意味着将s1的值复制了一份,赋给了s3,s1指向的是对象“abc",所以s3也指向对象”abc“,故都返回true;
s4 and s5 use ==
false
s4 and s5 use equals
true
----s4和s5指向的是由new创建的两个String对象,故==返回的是false;由上面的源码可知,String复写了equals方法,两个对象的字符序列是相同的,故equals返回的是true;
s1 and s4 use ==
false
s1 and s4 use equals
true
----与s4和s5一样,不再赘述;
2、静态变量与实例变量的区别
java的成员变量有两种,一种是被关键字static修饰的变量,称之为静态变量或者类变量,另外一种是没有被static修饰的变量,称为实例变量
实例变量属于对象级别,只有创建了实例对象,变量才会在内存中分配空间,才能使用这个实例变量;
静态变量属于类级别,只要程序加载了类,静态变量就会在内存中分配空间,就可以使用静态变量,静态变量存储在java方法区中
3、java程序在内存中的存储分配情况
java程序在内存中的存储分配情况:
堆区:
1.存储的全部是对象,每个对象都包含一个与之对应的class的信息。(class的目的是得到操作指令)
2.jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身
栈区:
1.每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中
2.每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。
3.栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。
方法区:
1.又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。
2.方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。
4、final关键字
使用final关键修饰一个引用类型的变量时,引用变量时不能改变的,但是引用变量所指向的对象的内容是可以改变的,举例说明:
final StringBuffer ss = new StringBuffer("sssss");
ss = new StringBuffer("aaa"); //该语句编译错误
ss.append("aaaa");
System.out.println(ss); //这两句编译正确,且最终显示sssssaaaa
5、String ,StringBuffer,StringBuilder
都是属于java.lang包;
都使用字符数组保存字符串,
不同的是:String是不可变的,StringBuffer和StringBuilder是可变的;
查看源码可知:
String类中保存字符串的数组有final修饰付修饰,故是不可变的且String类中没有append()方法;
private final char value[];
而StringBuffer,StringBuilder 均继承自抽象类AbstractStringBuilder,该抽象类中保存字符串的数组没有被final修饰符修饰,故是可变的,且这两个类都有append方法;
char[] value;
StringBuffer,StringBuilder的不同之处在于:StringBuffer是线程安全的,StringBuffer类中的方法加了同步锁,故是线程安全的;StringBuilder类中的方法没有,故是非线程安全的;
6、面向对象的特征
面向对象的变成语言有4个特征:封装,抽象,继承,多态