一、==和equals的区别
- 首先==是一个比较运算符,是可以直接使用的;而equals是一种非静态的方法,需要对象来引用。
- ==既可以比较基本数据类型(包括boolean,byte,short,int,long,char,float,daouble),也可以比较引用数据类型。比较基本数据类型时比较的是值,比较引用数据类型时比较的是地址值。
- 而equals只能比较引用数据类型,所有的对象都会继承Object类中的方法,在查看Object类中的源码可知,equals默认比较的是地址值,这就跟==比较引用数据类型无区别。所以一般我们会重写equals方法,使它比较两个对象中的属性
'=='的代码演示
package com.etime.work;
public class Test {
public static void main(String[] args) {
System.out.println("使用==比较基本数据类型");
System.out.println(2 == 2);
System.out.println('w' == 'w');
System.out.println(1.00 == 1); //true
double num1 = 1.00;
float num2 = 1.00f;
System.out.println(num1 == num2); //true
System.out.println("------------------");
System.out.println("使用==比较引用数据类型");
Person p1 = new Person("zx","女");
Person p2 = new Person("zx","女");
System.out.println(p1);
System.out.println(p2);
System.out.println(p1 == p2); //两个new出来的对象的地址在内存中是不同的
String str1 = new String("123");
String str2 = new String("123");
System.out.println(str1 == str2); //false
System.out.println("------------------------------");
}
}
接下来是equals比较,重写equals方法之前
package com.etime.work;
public class Test {
public static void main(String[] args) {
//这里String已经重写Object的equals方法,所以结果为true
String str1 = new String("123");
String str2 = new String("123");
System.out.println("使用equals比较引用数据类型");
System.out.println(str1.equals(str2)); //true
String str3 = new String("123456");
String str4 = new String("12345");
System.out.println(str3.equals(str4)); //false
System.out.println("------------------------------");
Person person = new Person("花木兰", "女");
Person person1 = new Person("花木兰", "女");
// 因为这里还没有重写equals方法,默认比较的还是地址值
System.out.println(person.equals(person1)); //false
}
}
在Person类中重写equals方法以后
重写equals时注意,Java规定,如果两个对象使用equals方法比较后返回true,那么这两个对象的hashCode必须返回值必须一致。所以,我们重写equals方法后,都需要重写hashCode方法来满足这个规定。
package com.etime.work;
public class Test {
public static void main(String[] args) {
Person person = new Person("花木兰", "女");
Person person1 = new Person("花木兰", "女");
// 重写equals以后
System.out.println(person.equals(person1)); //true
}
}
//在Person中重写equals()以后,
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return Objects.equals(name, person.name) && Objects.equals(gender, person.gender);
}
@Override
public int hashCode() {
return Objects.hash(name, gender);
}
二、重载和重写的区别
- 重载(Overload)
在一个类中,可以有一个的方法使用相同得方法名称,但是这些方法的参数必须不同。即参数个数不同,或者是参数类型不同。例如:
以下不是重载
public class Overload {
// 原方法
public String func(int i,int j,String name){
return name;
}
// 虽然两个参数相同,但是返回值类型不同
public void func(int i,int j,String name){}
// 虽然两个参数相同,有抛异常
public void func(int i,int j,String name) throws Exception{}
// 两个参数名字不相同
public void func(int j,int i,String name){}
}
正确的重载
public class Overload {
// 原方法
public String func(int i,int j,String name){
return name;
}
// 参数类型不同相同
public String func(int i,double j,String name){
return name;
}
// 参数个数不同相同
public String func(int i,String name){
return name;
}
}
- 重写(Override)
首先子类继承了父类原有的方法,但是子类并不想原封不动的继承父类中的某个方法,所以在方法名,参数列表,返回类型都相同的情况下, 对方法体进行修改或重写,这就是重写。但要注意子类函数的访问修饰权限不能少于父类的。
//父类
public class Override {
public String test(String str){
return str;
}
}
//继承了父类
public class Test extends Override{
public String test(String str){
String s = str + "子类重写了";
return s;
}
}
//不是重写
public class Test extends Override{
public void test(String str){
String s = str + "子类重写了";
return s;
}
}
方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。
三、String、Stringbuffer、StringBuilder的区别
1.String是引用数据类型,String对象被创建以后,它是不可改变的,包含在这个对象中的字符序列是不可改变的,直至这个对象被销毁。如果大量使用String对象就会导致String 对象泛滥,会占用大量的CPU的内存和资源。
2. StringBuffer对象则代表一个字符序列可变的字符串,当一个StringBuffer被创建以后,通过StringBuffer提供了很多方法可以改变这个字符串对象的字符序列。得到最终想要的字符串后,就可以调用它的toString()方法将其转换为一个String对象。StringBuffer对象是一个字符序列可变的字符串,它没有重新生成一个对象,而是在原来的对象中可以连接新的字符串。
3. StringBuilder也代表可变字符串对象。它和StringBuffer基本相似,两个类的构造器和方法也基本相同。不同的是:StringBuffer是同步的,多个线程不能同时调用它;而StringBuilder是异步的,即多个线程可以同时调用它。StringBuffer是线程安全的,而StringBuilder则没有实现线程安全功能。
package com.etime.stringBuffer;
public class Test01 {
public static void main(String[] args) {
// StringBuffer,StringBuilder:可变的字符串缓冲区类
/**
* 为什么要使用StringBuffer:因为字符串String的内容是不可变的,不断创建和销毁String
* 对象会大量的内存和CPU时间,而StringBUffer是可以通过append方法可以不断的往缓冲区
* 里面追加数据。缓冲区的默认容量为16字节
* 可以提高性能
* */
// 将三个字符串拼接起来
String a = "回家";
String b = "激活";
String c = "电弧";
// 原始方式:会有一个临时变量d
String d = a+b;
String f = d+c;
System.out.println(f);
// 使用StringBuffer
StringBuffer s = new StringBuffer(1024); //1024指的是缓冲区的初始大小
s.append(a).append(b).append(c); //可以不断的追加
System.out.println(s);
}
}