java入门基础六(面向对象)

10. 面向对象

10.10 Object类

含义:所有类的基类/超类,一个类没有明确继承的类,默认继承Object

Object作为所有类的父类,定义了几个方法,方便子类去重写

10.10.1 equals()方法

equals:比较两个对象在内存地址是否相同。

Object类中的equals方法:

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

示例:

Object obj1 = new Object();//0x001
Object obj2 = new Object();//0x002		

System.out.println(obj1.equals(obj2));//false

System.out.println(obj1 == obj2);//false

当Object中的equals方法中的比较方式不在适用于子类时,由子类重写(例如String类)

拓展:

​ 1.==两边是基本数据类型时,比较的是具体内容,为引用数据类型时,比较的是地址。

public static void main(String[] args) {
	String str1=new String("aaa");
	String str2=new String("aaa");
	String str3="ccc";
	String str4="ccc";
	System.out.println(str1==str2);			//false
	System.out.println(str1.equals(str2));	//true
	System.out.println(str3==str4);			//true
	System.out.println(str3.equals(str4));	//true
}

​ 注意:在常量池中只有一个"ccc",即str3和str4指向的地址相同。而str1和str2的地址是不相同的(每次new会在堆中开辟新空间)在String中存在equals方法的重写,如下:

public boolean equals(Object anObject) {
	if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
       String anotherString = (String)anObject;
       int n = value.length;
       if (n == anotherString.value.length) {
           char v1[] = value;
           char v2[] = anotherString.value;
           int i = 0;
           while (n-- != 0) {
               if (v1[i] != v2[i])
                   return false;
               i++;
           }
       return true;
       }
    }
    return false;
}

10.10.2 hashCode()方法

含义:获取对象的hash值:

hash值-系统利用对象的内存地址+散列算法获取的一个值
注:hash值不等于内存地址

示例:

Object obj1 = new Object();
Object obj2 = new Object();
				
System.out.println(obj1.hashCode());
System.out.println(obj2.hashCode());

10.10.3 getClass()方法

含义:获取类的字节码文件对象

public class A {
	String str1;
	String str2;
	int num;
	
	private void method01(){
		System.out.println("method01方法");
	}
	public void method02(){
		method01();
		System.out.println("method02方法");
	}

}
public static void main(String[] args) {
	A a = new A();
		
	//获取A类的字节码文件对象
	Class<? extends A> c = a.getClass();
		
	//获取A类中所有属性
	Field[] declaredFields = c.getDeclaredFields();
	for (Field field : declaredFields) {
		System.out.println(field);
	}
	System.out.println("");
	//获取A类中所有的方法
	Method[] declaredMethods = c.getDeclaredMethods();
	for (Method method : declaredMethods) {
		System.out.println(method);
	}	
}
/*
java.lang.String com.dream.day6.A.str1
java.lang.String com.dream.day6.A.str2
int com.dream.day6.A.num

public void com.dream.day6.A.method02()
private void com.dream.day6.A.method01()
*/

10.10.4 toString()方法

含义:获取对象的字符串表示

Object中的toString方法:

public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
Object obj1 = new Object();				

//java.lang.Object@15db9742
System.out.println(obj1.toString());

每个子类都有不同的属性,重写toString直接打印该对象中所有的属性,方便观察数据

重写示例:String类

public String toString() {
	return this;
}
System.out.println("abcdefg".toString()); //abcdefg

10.11 final --最终的

含义:最终

作用:

  1. 修饰类:该类不能被继承

  2. 修饰方法:该方法不能被重写

  3. 修饰变量:变成常量,不能重新赋值

​ 常量的命名规则:全大写,单词之间用下划线隔开

​ 常量的声明周期:存在常量池中,直到项目结束才会被销毁

10.12 abstract --抽象类及抽象方法

//抽象类
public abstract class 类名{
    //抽象方法
    public abstract void method();
}

抽象方法交给非抽象的子类去实现(重写)

应用场景:当一个方法必须在父类中出现,但是这个方法又不好实现,就把该方法变成抽象方法,交给非抽象的子类去实现

示例:

1.抽象父类Person —定义有抽象方法eat()

public abstract class Person {
	private String name;
	private char sex;
	private int age;
	
	public Person() {
		
	}
	public Person(String name, char sex, int age) {
		this.name = name;
		this.sex = sex;
		this.age = age;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public char getSex() {
		return sex;
	}
	public void setSex(char sex) {
		this.sex = sex;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", sex=" + sex + ", age=" + age + "]";
	}	
	public abstract void eat();
}

2.抽象子类Chinese —定义有抽象方法hoppy()

(子类Chinese虽然继承抽象类Person但是他本身也是抽象类,所以可以不实现父类中的抽象方法eat()。)

public abstract class Chinese extends Person{
	String id;

	
	public Chinese(String name, char sex, int age, String id) {
		super(name, sex, age);
		this.id = id;
	}

	public Chinese() {
		
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	@Override
	public String toString() {
		return "Chinese [id=" + id + ", toString()=" + super.toString() + "]";
	}
	public abstract void hoppy();  //定义抽象方法。
}

3.子类SiChuan (四川) --继承父类Chinese,需要实现两个抽象方法 eat和hoppy

public class SiChuan extends Chinese{
    
	public SiChuan() {
		
	}
	public SiChuan(String name, char sex, int age, String id) {
		super(name, sex, age, id);
	}
    
	@Override
	public void hoppy() {
		System.out.println(super.getName()+"打麻将");
	}
	
	@Override
	public void eat() {
		System.out.println(super.getName()+"吃火锅");
		
	}

	@Override
	public String toString() {
		return "SiChuan [toString()=" + super.toString() + "]";
	}	
}
public static void main(String[] args) {
	SiChuan sc=new SiChuan("小明",'女',18,"123456789");
	sc.eat();
	sc.hoppy();
	System.out.println(sc);
}
/*
小明吃火锅
小明打麻将
SiChuan [toString()=Chinese [id=123456789, toString()=Person [name=小明, sex=女, age=18]]]
*/

注:

  1. 抽象类不能直接创建对象,但可以创建匿名内部类,需要重写抽象方法。
Chinese c = new Chinese() {
		@Override
		public void eat() {
		}
		@Override
		public void hobby(){
	}
};
//1.创建匿名类,继承Chinese,重写eat、hobby方法
//2.创建匿名类的对象
//3.赋值给父类的引用

在这里插入图片描述

  1. 抽象类可以有构造方法
  2. 抽象类中可以有非抽象方法(成员方法和静态方法)
  3. 抽象类中可以没有抽象方法,但是毫无意义,与普通类相同
  4. 如果父类是抽象类,则子类不是抽象类时,才必须实现父类的抽象方法

10.13 interface --接口

含义:特殊的抽象类

注意:

  1. JDK1.7时,接口中只能有静态常量(static final)和抽象方法(abstract)
  2. JDK1.8开始,接口中可以允许存在有静态方法(static)和默认方法(default)

应用场景:对实现类进行行为上的规范。

public interface I1 {

	//默认添加public static final
	int i = 100;	
	//默认添加abstract
	public void method01();
	public void method02();	
	//默认方法
	default void defaultMethod(){
		System.out.println("接口中的默认方法");
	}	
	//静态方法
	public static void staticMethod(){
		System.out.println("接口中的静态方法");
	}	
}

抽象类 vs 接口

抽象类:成员变量、静态变量、静态常量、成员方法、静态方法、抽象方法

接口:静态常量、抽象方法; 静态方法、默认方法(JDK1.8)

注:

  1. 一个类可以实现多个接口,但只能继承一个父类。
public class A implements I1,I2,I3 {

	@Override
	public void method_3() {		
	}
    
	@Override
	public void method_2() {		
	}
    
	@Override
	public void method_1() {		
	}
}
  1. 一个接口不可以实现其他接口,但可以继承,且可以继承多个接口。
public interface I1 extends I2,I3{   //I2和I3也是接口类
    public void method_1();
}
  1. 接口里面的方法不一定都是抽象的,JDK1.7时接口里只能有抽象方法,但JDK1.8及以后,接口可以有抽象方法和默认方法

  2. 接口解决了类的单继承问题。

  3. 类能够同时实现继承和多接口。

  4. 接口可以new对象与抽象类相同,只能创建匿名内部类。

类 - 接口的关系:
类 - 类:单继承
类 - 接口:多实现
接口 - 接口:多继承

10.14 多态

在面对需求升级或是迭代时,常常需要修改程序,此时应该满足OCP原则。

OCP - 开闭原则:
O - open :在需求升级时,对于创建类是欢迎的
C - close:在需求升级时,改变原有代码是拒绝的

注:需求升级时,尽量不要改变以前的类,否则容易出bug

10.14.1 类的多态

类的多态通过继承和向上转型实现,使子类对象指向父类引用(即,父类引用中储存的是子类对象在堆中的地址。)

示例:

//定义抽象父类  交通工具类
public abstract class Vehicle {
	public abstract void start();
	public abstract void stop();
}
//子类 自行车类
public class Bike extends Vehicle{
	
	public void start(){
		System.out.println("启动自行车");
	}
	public void stop(){
		System.out.println("关闭自行车");
	}
}
//子类  小汽车类
public class Car extends Vehicle{
	public void start(){
		System.out.println("启动小汽车");
		
	}
	public void stop(){
		System.out.println("关闭小汽车");
	}
}
//测试方法
public static void main(String[] args) {
		
	Teacher t = new Teacher();
	Vehicle v= new Car();
    Vehicle v1= new Bike();
	t.open(v);
	System.out.println("欣赏沿途风景");
	t.close(v);
    t.open(v1);
	System.out.println("欣赏沿途风景");
	t.close(v1);
}
/*
启动小汽车
欣赏沿途风景
关闭小汽车
启动自行车
欣赏沿途风景
关闭自行车
*/

10.14.2 接口的多态

接口的多态是通过实现类和向上转型完成,指实现类的对象指向接口的引用,在接口的引用中存放的是实现类对象在堆中开辟空间的地址。

示例:

//Usb接口
public interface IUsb {
	
	public void usb();

}
//实现类   鼠标类
public class Mouse implements IUsb {
	@Override
	public void usb() {
		System.out.println("鼠标点点点");
	}
}
//电脑类
public class Computer {
	public void useusb(IUsb u){
		u.usb();
	}
}
//测试方法
public static void main(String[] args) {
	Computer c =new Computer();
	IUsb u =new Mouse();
	c.useusb(u);
}
/*
鼠标点点点
*/

10.15 对象转型

10.15.1 向上转型

含义:子类类型 转 父类类型
1. 可以调用父类非私有化属性
2. 可以调用父类非私有化方法
3. 可以调用子类重写父类的方法
4. 不可以调用子类属性和方法

注:向上转型就是多态。(详细示例可以参照10.14 --多态)

缺点:

不可以调用子类自己的属性和方法。

10.15.2 向下转型

含义:父类类型 转 子类类型

注:向下转型为强制转换,转换前需要使用instanceof进行判断,否则容易出现类型转换异常–ClassCastException 。

(使用向下转型时,此对象应经过一次向上转型)

示例:

//父类 动物类
public class Animal {
	
	public void method(){
		System.out.println("Animal的方法");
	}
}
//子类 狗类
public class Dog extends Animal{

	@Override
	public void method() {
		System.out.println("Dog~~旺旺旺");
	}
}
//子类 猫类
public class Cat extends Animal{

	@Override
	public void method() {
		System.out.println("Cat~~喵喵喵");
	}
}
//测试方法
public static void main(String[] args) {
	Animal animal = new Dog();  //向上转型
		
	if(animal instanceof Dog){   //先判断
		Dog dog = (Dog) animal;
		dog.method();
	}
	if(animal instanceof Cat){
		Cat cat = (Cat) animal;
		cat.method();
	}
}
/*
Dog~~旺旺旺
*/

10.16 内部类

知识点:内部类
含义:一个类里面声明一个类

10.16.1 成员内部类

特点:可以调用外部类中所有的属性

示例:

public class A {
	public String str1="aaa";
	private String str2="bbb";
	protected String str3="ccc";
	static String str4="ddd";
	final String STR5="eee";
	
	public class A1{
		public void method(){
			System.out.println("成员内部类的方法");
			System.out.println(str1);
			System.out.println(str2);
			System.out.println(str3);
			System.out.println(str4);
			System.out.println(STR5);
		}
	}
}

10.16.2 静态内部类

特点:只能到调用外部类的静态属性

示例:

public class B {
	static String str="111";
    
	static class B1{
		public void method(){
			System.out.println("静态内部类的方法");
			System.out.println(str);
		}
	}
}

10.16.3 接口内部类

注意:接口内部类底层就是静态内部类

示例:

public interface IC {
    
	String str="111";
    
	class C1{
		public void method(){
			System.out.println("接口内部类的方法");
			System.out.println(str);
		}
	}
}

10.16.4 局部内部类

含义:放在成员方法中的类

普通示例:

public class D {
	public String str="aaa";
	public void functians(){
		 class D1{
			public void method(){
				System.out.println("局部内部类的方法");
				System.out.println(str);
			}			
		}
		 D1 d1=new D1();
		 d1.method();
	}
}

深入示例:

public class Outter {
	
	public Object function(){
		//如果局部内部类中使用到该变量,JDK1.8开始该变量自动变成常量(JDK1.8之前需要手动添加final)		
        //因为防止i在该方法结束后才使用
		int i = 100;		
		//局部内部类
		class Inner{
			@Override
			public String toString() {
				return i+"";
			}
		}		
		//创建局部内部类的对象
		Inner inner = new Inner();		
		return inner;
	}	
}

对以上四类进行综合测试示例:

public static void main(String[] args) {
	//调用成员内部类的方法。
	A1 a1 = new A().new A1();
	a1.method();
		
	//调用静态内部类的方法。
	B1 b1 = new B.B1();
	b1.method();
		
	//调用接口内部类的方法。
	C1 c1 = new IC.C1();
	c1.method();
		
	//调用局部内部类的方法
	D d = new D();
	d.functians();
    
    //创建外部类的对象
	Outter outter = new Outter();
				
	//调用方法
	Object obj = outter.function();
	System.out.println(obj);
}

/*
成员内部类的方法
aaa
bbb
ccc
ddd
eee
静态内部类的方法
111
接口内部类的方法
111
局部内部类的方法
aaa
100
*/

10.16.5 匿名内部类

匿名内部类分 有匿名子类(父类或者抽象父类)和 匿名实现类(接口)。

//1.创建匿名实现类,实现I1中的method
//2.创建匿名实现类的对象,指向接口的引用
I1 i1 = new I1() {
	@Override
	public void method() {
	}
};

//1.创建匿名子类,继承A,重写method
//2.创建匿名子类对象,赋值给父类的引用
A a = new A() {
	@Override
	public void method() {
	}
};

详细示例和图解可以见 : 10.12 --抽象类 —> 注 —> 1.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值