学习JavaEE的日子 day15 访问修饰符,Object,equals底层,final

发布时间:2024年01月19日

Day15

1.访问修饰符

理解:给类、方法、属性定义访问权限的关键字

注意:

1.修饰类只能使用public和默认的访问权限

2.修饰方法和属性可以使用所有的访问权限

经验:

1.属性一般使用private修饰,因为封装
2.属性或者方法如果需要被子类使用,一般使用protected修饰
3.方法如果不需要被外界使用,一般使用private修饰
4.方法一般使用public修饰

访问修饰符本类本包其他包子类其他包
privateOK
默认的OKOK
protectedOKOKOK
publicOKOKOKOK
public class A {
	
	public String str = "A类的属性";
	
	public void method(){
		System.out.println(str);
	}
}
public class Test01 {
	public static void main(String[] args) {
		
		A a = new A();
		System.out.println(a.str);
		
		
	}
}

2.Object类

概念:所有类的基类或者超类

理解:如果一个类没有明确继承的类,默认继承Object,所以说Object是所有类的祖先类

equals():

? 比较两个对象的内存地址是否相同

底层代码:

public boolean equals(Object obj){
	return this == obj;
}
getClass():

? getClass方法就是获取该类的class对象

? 前言:
使用到类,会把该类的class文件加载到方法区,并且在堆中创建该类的class对象
该类的class对象作为class文件的访问入口
class文件只加载1次,所以该类的class对象在内存中也只有一个

hashCode():

? 获取对象的hash值

注意:hash值不等于内存地址,hash值是对象的内存地址+散列算法,算出来的一个数值

toString():

? 获取对象的字符串表示(将对象转换为字符串,可以看做是对象的内存地址值)

      public String toString(){

 					     //java.lang.Object          @         15db9742

 			return getClass().getName() + "@" + Integer.toHexString(hashCode());

 			//getClass().getName() - class对象的全路径(报名+类名)

 			//Integer.toHexString(hashCode()) - 获取对象的十六进制hash值

            }
==:

基本数据类型:==比较的是值是否相同

引用数据类型:==比较的是内存地址

public class Test01 {
	public static void main(String[] args) {
		
		//基本数据类型:==比较的是值是否相同
//		int a = 10;
//		int b = 20;
//		System.out.println(a == b);//false

		//引用数据类型:==比较的是内存地址
		Object obj1 = new Object();//0x001
		Object obj2 = new Object();//0x002
		System.out.println(obj1 == obj2);//false
		System.out.println(obj1.equals(obj2));//false
		
	}
}

getClass():

public class Test02 {
    public static void main(String[] args) {
		

		Object obj1 = new Object();//0x001
		Object obj2 = new Object();//0x002
		
		Class<? extends Object> class1 = obj1.getClass();//获取的是Object类的class对象
		Class<? extends Object> class2 = obj2.getClass();//获取的是Object类的class对象
		System.out.println(class1 == class2);//true
		
	}

hashcode():

public class Test03 {
   public static void main(String[] args) {
		

		Object obj1 = new Object();//0x001
		Object obj2 = new Object();//0x002
		
		System.out.println(obj1.hashCode());//366712642
		System.out.println(obj2.hashCode());//1829164700
		
	}

toString():

public class Test04 {
   public static void main(String[] args) {

		Object obj1 = new Object();//0x001
		Object obj2 = new Object();//0x002
		
		System.out.println(obj1.toString());//java.lang.Object@15db9742
		System.out.println(obj2.toString());//java.lang.Object@6d06d69c
	}     

3.Object方法的使用

getClass():在反射的知识点中使用

hashCode():在集合的知识点中使用

equals():
比较两个对象的内存地址是否相同(有==就可以)
但是他的标杆作用是比较两个对象是否相同
不同子类比较两个对象的规则不一样
所以不同子类重写equals即可

toString():
获取对象的字符串表示
他的标杆作用不同的子类有不同的属性,重写toString方便外界打印

需求:编写用户类,比较两个对象是否相同,并打印

public class User {
	
	private String username;//账号
	private String password;//密码
	private String nickName;//昵称
	private String name;//姓名
	
	public User() {
	}

	public User(String username, String password, String nickName, String name) {
		this.username = username;
		this.password = password;
		this.nickName = nickName;
		this.name = name;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getNickName() {
		return nickName;
	}

	public void setNickName(String nickName) {
		this.nickName = nickName;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
   
    // user1.equals(user2):user是子类(也就是User类),equals是object类,对象的向上转型
    //User类:默认父类是object类
    
    //user1.equals(user2)
	//this --> user1
	//obj是传进来的参数,也就是user2
    
	@Override
	public boolean equals(Object obj) { //第一步
		if(this == obj){  //比较两个内存地址是否相同
			return true;
		}
		
		User use = (User) obj;//第二步 向下转型   
		if(this.username.equals(use.username)){  //账号是一样的true,否则false
			return true;   //这个equals是String类的,比较两个字符串是否相等
		}
		return false;
	}
	
	@Override
	public String toString() {
		return this.username + " -- " + this.password + " -- " + this.nickName + " -- " + this.name;
	}
}
public class Test01 {
	public static void main(String[] args) {
		
		User user1 = new User("1445584980", "123123", "撕裂的忧伤", "彭于晏");//0x001
		User user2 = new User("1445584980", "123123", "撕裂的忧伤", "彭于晏");//0x002
		//user1,user2是否相等?从内存角度上看,new了两个对象,地址不同   从业务角度:账号一样,就一样
        
		System.out.println(user1.equals(user2));//false
		
		System.out.println(user1.toString());
		System.out.println(user2.toString());
	}
}

内存分析图:

在这里插入图片描述

扩展 - 注意:

? 1.java方法中的参数是值传递

? 2.如果方法中的参数是基本类型直接将实参的值传入该方法

? 3.如果方法中的参数是引用类型将对象的内存地址作为值传入该方法

4.深入字符串String的equals()

字符串一般不用 == 比较,因为这样比较的是内存地址,肯定是false

所以字符串比较用equals()方法

面试题:String是如何比较两个字符串是否相同的

1.比较两个字符串的地址是否相同(重写equals()方法,用 == 比较)
2.比较两个字符串的字符个数(先强转)
3.循环比较字符的Unicode码

public class MyString {

	private char[] value;
	
	public MyString(String original) {
		//"abc" 转换为 ['a','b','c']
		value = original.toCharArray();//将字符串转换为字符数组
	}
	
    //重写equals方法
	@Override
	public boolean equals(Object obj) {
		if(this == obj){//比较两个内存地址是否相同
			return true;
		}
		
		MyString my = (MyString) obj;//强转为MyString
		
		char[] v1 = this.value;//当前数组
		char[] v2 = my.value;//v2
		
		//比较字符长度
		if(v1.length != v2.length){
			return false;
		}
		
		for (int i = 0; i < v1.length; i++) {
			//长度一致,然后比较字符的Unicode码是否相同
			if(v1[i] != v2[i]){
				return false;
			}
		}
		return true;
	}
	
	@Override
	public String toString() {
		return String.valueOf(value);//将字符数组转为字符串
	}
}
public class Test01 {
	public static void main(String[] args) {
		
		String str1 = new String("abc");
		String str2 = new String("abc");
		
		System.out.println(str1 == str2);//false  一般不用
		System.out.println(str1.equals(str2));//true
		
		System.out.println(str1);//abc
		System.out.println(str2);//abc
		
		System.out.println("-------------------------------");
		
		MyString m1 = new MyString("abc");
		MyString m2 = new MyString("abc");
		
		System.out.println(m1 == m2);//false
		System.out.println(m1.equals(m2));//true
		
		//注意:打印对象,默认调用toString()
		System.out.println(m1);//不重写toString(),就打印地址值
		System.out.println(m2);//不重写toString(),就打印地址值
	}
}

小结:

? 1.默认情况下equals方法比较的是对象的地址值

? 2.比较对象的地址值是没有意义的,因此一般情况下我们都会重写Object类中的equals方法

5.final

作用:

1.final修饰类,该类不能被继承

2.final修饰方法,该方法不能被子类重写

3.final修饰变量,变量变为常量,不能重新赋值

注意:

1.常量在常量池中声明,项目结束时才会被销毁

2.常量的命名规范:全部单词大写,单词之间使用下划线隔开

经验:

如果不想让该类有子类(不想该类有扩展),就是用final修饰

final和static一般一起修饰属性,该属性变成静态常量

//final修饰类,该类不能被继承
//public final class A {
public class A {

	//final修饰方法,该方法不能被子类重写
	//public final void method(){
	public void method(){
		System.out.println("父类的方法");
	}
}
public class B extends A{

	@Override
	public void method() {
		System.out.println("子类重写父类的方法");
		
		//final修饰变量,变量变为常量,不能重新赋值
		final int i = 100;
		System.out.println(i);
	}
}

总结

1.访问修饰符 – 一定要去做实验

2.Object的概念
equals
getClass
hashCode
toString

3.Object的使用
子类重写equals和toString

4.MyString – 重要!!!

5.final - 最终的
修饰类,类不能被继承
修饰方法,方法不能被重写
修饰变量,变为常量

文章来源:https://blog.csdn.net/weixin_69595694/article/details/135693996
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。