Java知识点总结
1、==与equals
java的数据类型分为基本数据类型和复合数据类型;
基本数据类型(四类八种):整形:byte,short,int,long;浮点型:float,double;字符型:char;逻辑型:boolean;
在内存中直接存放于栈中,基本数据类型之间的比较用==比较,比较的是他们的值
复合数据类型:常指的是类,在内存中对象存在于堆中,对象引用则存在于栈中
==进行比较的时候,比较的是引用,即对象在内存中的地址;所以,同一个对象比较时,因内存地址相同,故返回true,不同对象比较时,因地址不同,故返回false;
equals进行比较的时候,需了解equals有没有被覆写,在java中,所有的类都继承于基类Object,在Object类中,equals方法是用==比较的,源码如下所示:
1 public boolean equals(Object obj) {
2 return (this == obj);
3 }
所以,在默认情况下,equals同==一样,比较的对象的内存地址;
但是,一些类覆写了equals方法,比如String,Integer等,它们有自己的实现,如下String类中equals方法的实现所示:第一个同==一样,判断内存地址是否一样,即判断是否为同一个对象,如果是同一个对象则返回true,否则继续往下走,执行第二个if,第二个if的条件为参数是否为String的实例,如果是的的话,判断两个对象的字符序列是否相等;相等返回true,不相等返回false;
1 public boolean equals(Object anObject) { 2 if (this == anObject) { 3 return true; 4 } 5 if (anObject instanceof String) { 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 class A{ 2 3 } 4 public class Test { 5 6 7 public static void main(String[] args) { 8 //比较普通类,没有复写了equals方法; 9 A a = new A(); 10 A b = new A(); 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个特征:封装,抽象,继承,多态