Object类

一、匿名内部类

匿名内部类在设计上和局部内部类相似;但是本质为多态,也就是能用多态的案例,肯定能用匿名内部类

回顾多态案例(接口或抽象类都可以),有直接引用,传参多态,返回值多态

直接引用

//案例:喷火娃具有喷火的能力
//应用场景:
//当实例化一次对象,倾向于用匿名内部类;写法上简单,节约资源
//当实例化多次对象,倾向于用多态;结果清晰,无需创建多个class资源
interface Fireable{
	void fire();
}
class WaWa implements Fireable{
	@Override
	public void fire() {
		System.out.println("喷火娃正在喷火...");
	}
}
public class Test1 {
	public static void main(String[] args) {
		//1.接口直接引用的多态
		Fireable able = new WaWa();
		able.fire();
		//2.匿名内部类的方式
		Fireable able2 = new Fireable() {
			@Override
			public void fire() {
				System.out.println("匿名内部类的喷火..");
			}
		};
		able2.fire();
	}
}

传参多态

//案例:直接调方法,多态传参;接口为USB标准;实现类为Disk
interface USB{
	void run();
}
class Disk implements USB{
	@Override
	public void run() {
		System.out.println("硬盘正在运转");
	}
}
public class Test2 {
	public static void main(String[] args) {
		//传参多态:将Test2看成第三方类来使用
		Test2.connect(new Disk());
		
		//匿名内部类实现
		Test2.connect(new USB() {
			@Override
			public void run() {
				System.out.println("匿名设备正在运转");
			}
		});
	}
	private static void connect(USB u) {
		u.run();  //接口回调
	}
}

结论:多态有什么应用场景,那么匿名内部类就有什么场景

二、Object类概述

概述

Object类是所有类的祖宗类,所有的类直接或间接继承Object类

直接继承:当一个类没有直接父类,则继承Object类

间接继承:当一个类有父类,则父类继承Object类

Object类天生就是多态的应用

Object创建

创建对象的方式有三种:1.直接new对象 2.传参new 3.返回值new

//创建Object对象
class Person{ //直接继承Object
}
public class Test1 {
	public static void main(String[] args) {
		//Object o = new Object();  //面向对象方式--不常用
		Object o = new Person();    //1.直接引用多态
		
		Test1.invoke(new Person()); //2.传参多态
		
		Object o1 = Test1.getPerson(); //3.返回值多态
	}
	private static Object getPerson() {
		return new Person();  //返回值多态
	}
	private static void invoke(Object o) { //传参多态
		System.out.println("传参多态");
	}
}

三、常用方法

getClass方法

获取类对象的方法,相同类的类对象只有一个

//Object的getClass方法:获取类对象
class Person{
}
public class Test1 {
	public static void main(String[] args) {
		Class c1 = new Person().getClass();
		Class c2 = new Person().getClass();
		//==:在引用类型中,用于比较地址;同一块地址则为true;不同则为false
		System.out.println(new Person()==new Person()); //false
		System.out.println(c1==c2); //true
		
		Class c3 = new Test1().getClass();
		System.out.println(c1==c3); //false
	}
}

场景:和instanceof场景类似,用于判断类型;另一个场景就是反射的应用(后面学)

hashCode方法

每个对象都可以调用hashCode后,返回hash值(整数值); 不同对象返回的hash值不同

//Object的hashCode方法:不同对象(对象就是地址)返回不同hash值(整数值)
//应用场景:我们直接使用Object的hashCode是没有意义的;往往需要重写
//重写后,认为属性值一致,则返回相同的hash值
class Man{	
}
class WoMan{
	String name;
	int  age;
	public WoMan(String name,int age) {
		this.name = name;
		this.age  = age;
	}
	@Override  //当前类重写的hashCode,里面获取的是属性的hash值
	public int hashCode() {
		//name.hashCode():String类型的hashCode:用于比较内容是否一致
		return name.hashCode()+age;
	}
}
public class Test2 {
	public static void main(String[] args) {
		System.out.println(new Man().hashCode()); //366712642
		System.out.println(new Man().hashCode()); //1829164700
		
		System.out.println("字符串的hashCode:"+"凤姐".hashCode());
		System.out.println("字符串的hashCode:"+"凤姐".hashCode());
		
		System.out.println(new WoMan("凤姐", 30).hashCode()); //
		System.out.println(new WoMan("凤姐", 30).hashCode());
	}
}

toString方法

Object的toString,就是将对象以字符串方式返回: 类名@hash值

//Object的toString:将对象以字符串方式返回; 结果:类名@hash值
//不同对象的类名@hash值不同;只能用于查看地址是否一致
//真正应用场景:重写--用于返回属性的字符串形式  
class Dog{
	String name;
	int    age;
	
	public  Dog(String name,int age) {
		this.name = name;
		this.age  = age;
	}
	@Override
	public String toString() {
		return name+":"+age; //调用重写的toString,可以查看到属性是否有赋值
	}
}
public class Test3 {
	public static void main(String[] args) {
		Dog wc = new Dog("旺财",3);
		Dog bj = new Dog("八戒",600);
		System.out.println(wc.toString());
		System.out.println(bj.toString());
		
		System.out.println("-----------");
		System.out.println(wc);  //打印对象-一样可以查看属性
		
		//分析打印对象流程:
		//1.System.out.println(wc)里面的println(Object),具体实现调用了String.valueOf(x)
		//2.查看String.valueOf(x)的实现里面调用了obj.toString() 
	}
}

equals方法

Object的equals方法:用于比较两个对象的地址是否相等;和==是一样的

//Object的equals方法:用于比较两个对象的地址是否相等;和==是一样的
//如果相等则返回true;不相等则返回false
//应用场景:比较属性是否相等---在实体类中重写equals方法,认为属性一致则返回true
class Pig{
}
class Cat{
	String name;
	int    age;
	public Cat(String name,int age) {
		this.name = name;
		this.age  = age;
	}
	@Override
	public boolean equals(Object obj) {//Object obj = "加菲猫";
		//if (obj instanceof Cat) { //方式1:使用instanceof匹配类型
		if(this.getClass()==obj.getClass()){
			Cat cat = (Cat) obj;  //将字符串转成Cat
			//String的equals重写方法用于比较内容,内容一致,则返回true
			return this.name.equals(cat.name)&&this.age==cat.age;
		}
		return false;
	}
}
public class Test4 {
	public static void main(String[] args) {
		//1.调用Object的equals方法
		Pig peiQi = new Pig();
		Pig qiaoZhi = new Pig();
		System.out.println(peiQi==qiaoZhi);  //false
		System.out.println(peiQi.equals(qiaoZhi));  //false
		
		//2.重写equals方法--比较属性
		Cat jf = new Cat("加菲猫", 5);
		Cat jf2 = new Cat("加菲猫", 5);
		System.out.println(jf.equals(jf2));  //true
		
		System.out.println(jf.equals("加菲猫"));  //
	}
}

finalize方法

如果一个对象变为了垃圾对象,JVM就会调用finalize方法,标记该方法需要进行回收了。可以通过垃圾回收器进行回收

一般不会立即进行回收(触发finalize方法),除非内存满了,则会立即回收

垃圾对象:没有引用变量去指向new出来的对象,这个new对象就是垃圾对象

自动回收机制:JVM内存耗尽,才会一次性回收。

手动回收机制:调用System.gc(),告诉JVM现在需要回收内存了

class Student{
	private String name;
	public Student(String name) {
		this.name=name;
	}
	@Override
	protected void finalize() throws Throwable {
		System.out.println(name+"已经准备回收");
	}
}
public class Test5 {
	public static void main(String[] args) {
		Student st = new Student("刘亦菲"); //不是垃圾对象,有引用变量使用
		
		new Student("凤姐");  //垃圾对象,没人使用
		System.gc();  //手动回收
	}
}

四、包装类

前面学习了8大基本类型,破坏了面向对象的纯粹性;为了承诺一切皆为对象,在java中提供了包装了,来包装这些基本类型。

好处:可以统一变量的初始值为null;且具有面向对象特点—调方法

基本类型对应包装类:

byte—Byte short—Short int—–Integer long—-Long

float—Float double—Double boolean—Boolean char—–Character

包装类型转换

class Person{
	//变为包装类后,同一个初始类型为null
	String name;  //null
	Integer    age;   //0---null  
	Character   sex;   //码值为0 空格---null
}
public class Test1 {
	public static void main(String[] args) {
		Person p = new Person();
		System.out.println(p.name);
		System.out.println(p.age);
		System.out.println(p.sex);
		
		//装箱:将基本类型转包装类
		Integer  a = new Integer(3); //方式1
		a = Integer.valueOf(5);   //方式2:类名调静态方法
		
		//拆箱:将包装类转基本类型
		int b = a.intValue();
		System.out.println(b);  //5
		
		//自动装箱:int-->Integer 本质还是手动装,系统自动做了(1.5版本后)--看反编译工具
		Integer aa = 3;
		//自动拆箱:
		int bb = aa;
		System.out.println(bb);  //3
		
		//字符串与其他类型的转换:
		//其他类型转字符串:拼接""
		String s = 3+"";
		//字符串转其他类型
		String ss = "33"; 
		//字符串转整数:
		int i = Integer.parseInt(ss);
		//字符串转double
		double d = Double.parseDouble(ss);
		
		//注意-字符串一定是数字字符串,否则报格式转换异常
		int ii = Integer.parseInt("aaa"); //NumberFormatException
	}
}

整数缓冲区

在Integer中提供了256个(-128~127)常用的整数缓冲区的地址; 也就是在这个范围了如果值相同返回的地址相同

要使用整数缓冲区,必须调用Integer.valueOf(..)

好处:节约内存

Integer i = new Integer(3);
Integer ii = new Integer(3);
System.out.println(i==ii);  //false new不同地址,肯定是false

//整数缓冲区测试:-128~127之间  ,如果参数相同,则返回地址一致
Integer a = Integer.valueOf(3);
Integer b = Integer.valueOf(3);
System.out.println(a==b);  //true

Integer aa = Integer.valueOf(300);
Integer bb = Integer.valueOf(300);
System.out.println(aa==bb);  //false

五、总结与作业

总结

1.匿名内部类(重点)
和多态一致,应用场景也一致
应用:直接引用,传参匿名内部类的使用
2.Object类的概述(重点)
概述,创建方式
3.Object常用方法
getClass:获取类对象,new的类型相同,则类对象一致
hashCode:不同对象有不同hash值返回--重写后返回属性hash值(重点)
toString:将对象以字符串返回--重写后返回属性的字符串拼接(重点)
equals: 比较地址是否相等---重写后比较属性是否相等(重点)
finalize:垃圾回收后的触发  
4.包装类
对基本类型的包装;包装类型转换;(重点) 字符串与其他类型的转换
整数缓冲区

作业

1.Object类实现多态的方式有哪些?并给出案例

2.公司招聘微服务架构标准人才,匿名内部类具备该标准,请使用匿名内部类完成

3.实例化两个String对象,调用两次hashCode,返回的值为什么一致?如何做到的。
例如: 
new String("zs").hashCode();
new String("zs").hashCode();

4.实例化两个String对象,调用equals方法进行比较,为什么会返回true?如何做到的。
String s1 =new String("zs");
String s2 =new String("zs");
s1.equals(s2)---true