JavaSE 之 面向对象梳理

概念

类是模板,规划了对象应该拥有怎样的属性和方法

结构
public class A{
    //-------------属性------------------
    //成员属性/实例属性
    String str1;
    int i1;
    
    //静态属性/类属性
    static String str2;
    static String i2;
    
     //-------------方法------------------
    /**
    *成员方法/实例方法:
    *	访问修饰符 返回值类型 方法名(参数列表){
    *		...代码块...
	*	}
	*/
    public void method01(){}
    public void method02(){}
    
    /**
    *静态方法/类方法:
    *	访问修饰符 static 返回值类型 方法名(参数列表){
    *		...代码块...
	*	}
	*/
    public static void method03(){}
    public static void method04(){}
}

对象

概念

对象是类的具体表现形式,可以操作对象中的各种信息

比如:操作属性、方法

具体使用
public class Test {

	public static void main(String[] args) {

		//创建Perosn类的对象
		Person p = new Person();
		
		//设置属性
		p.name = "吴彦祖";
		p.age = 18;
		
		//获取属性
		String n = p.name;
		System.out.println(n);
		System.out.println(p.age);
		
		//调用方法
		p.eat();
		p.sleep();
	}
}
//人类
class Person{
    String name;
    int age;
    
    public void eat(){
    	System.out.println("吃饭饭");
    }
    
    public void sleep(){
    	System.out.println("吃饭饭");
    }
}

方法的重载

概念

依据具体参数类型匹配到对应方法

规则
  1. 在同一个类中
  2. 方法名相同
  3. 形参列表的个数或者类型不同
  4. 与返回值无关
具体使用
public class Test {

	public static void main(String[] args) {

		Operation operation = new Operation();
		//根究参数类型自动匹配对应add方法
		int result = operation.add(10, 20);
		System.out.println(result);
	}
}
//运算类
class Operation{
	//2个int类型做加法
	public int add(int num1,int num2){
		return num1 + num2;
	}
	//3个int类型做加法
	public int add(int num1,int num2,int num3){
		return num1 + num2 + num3;
	}
}
好处

在一个类中,多个方法功能一样,所以方法名应该相同,根据传入的不同类型,系统自动匹配到对应的方法,这样减少了因取名字带来的困扰,更使得类的可读性大幅度提高

成员变量与局部变量的区别

成员变量:

  1. 必须用对象调用

  2. 对象被GC会收回后,成员变量也会被回收

  3. 作用域在整个对象中

  4. 创建对象时,系统赋给默认值

整数类型:0

浮点类型:0.0

字符类型:’ ’

布尔类型:flase

引用类型:null

局部变量(方法里的变量):

  1. 方法被调用后,方法中的变量会被GC立刻回收掉

    1. 作用域在方法中
    2. 局部变量没有初始值

成员方法与静态方法的区别

成员方法:必须用对象调用

静态方法:可以用对象或者类名调用,建议使用类名直接调用,因为静态方法属于类方法

构造方法

概念

与类名相同且没有返回项的方法

作用:创建对象

注意:如果该类没有任何构造方法,系统会默认实现无参构造(没有参数的构造方法)

具体使用
public class Test {

	public static void main(String[] args) {

		//创建Perosn类的对象
		Person p1 = new Person();
		Person p2 = new Person("吴彦祖",18);
		
		System.out.println(p1.name + " -- " + p1.age);
		System.out.println(p2.name + " -- " + p2.age);
		
	}
}
//人类
class Person{
    String name;
    int age;
    
    public Person() {
	}
    
    public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
}
好处

无参构造可以创建对象,但是有参构造不仅可以创建对象还可以在创建对象时给属性赋值

private关键字

概念

private - 私有化

作用:

  1. 修饰属性:私有化属性,该属性不能在本类以外直接调用

    1. 修饰方法:私有化方法,该方法不能在本类以外直接调用
具体使用
public class Test {

	public static void main(String[] args) {

		Person p = new Person();
		
		System.out.println(p.name + " -- " + p.age);//这里会报错
		p.method01();//这里会报错
		
	}
}
//人类
class Person{
    private String name;
    private int age;
    
    public Person() {
	}
    
    public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
    
    private void method01(){
    	System.out.println("Person类私有化方法");
    }
}
好处

让属性和方法更加安全,因为不能让类的外部调用

如果不想属性和方法让外界调用,就private修饰

封装

概念

private+get/set方法,类里提供公有化的方法让外界可以获得对象中私有化的属性和方法

很多人不理解既然私有化的属性和方法,为什么还要设置公有化的方法让外界有权限去调用?

因为如果直接访问属性,程序无法记录属性何时被调用或者说被谁给调用,而公有化方法中可以做相应的记录,详情请看"具体使用"

具体使用
public class Test {

	public static void main(String[] args) {

		Person p = new Person();
		
		p.setName("吴彦祖");
		p.setAge(18);
		System.out.println(p.getName() + " -- " + p.getAge());
		p.method02();
	}
}
//人类
class Person{
    private String name;
    private int age;
    
    public Person() {
	}
    
    public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
    
    public String getName() {
    	System.out.println("name属性被获取了");
		return name;
	}

	public void setName(String name) {
		System.out.println("name属性被设置了");
		this.name = name;
	}

	public int getAge() {
		System.out.println("age属性被获取了");
		return age;
	}

	public void setAge(int age) {
		System.out.println("age属性被设置了");
		this.age = age;
	}

	private void method01(){
    	System.out.println("Person类私有化方法");
    }
	
	public void method02() {
		System.out.println("调用Person类method01私有化方法");
		method01();
	}
}

this关键字

概念

this - 本对象

作用:

​ this.属性:调用本对象的属性

​ this.方法:调用本对象的方法

​ this():根据传参类型调用本对象的构造方法(此用法只能放在除了本构造方法的其他构造里)

具体使用
public class Test1 {

	public static void main(String[] args) {

		Person p = new Person("吴彦祖",18,'男');
		p.method02();
	}
}
//人类
class Person{
    private String name;
    private int age;
    private char sex;
    
    public Person() {
	}
    
    public Person(String name, int age) {
		this.name = name;//调用本对象的属性
		this.age = age;//调用本对象的属性
	}
    
	public Person(String name, int age, char sex) {
		this(name,age);//调用本类其他的构造方法
		this.sex = sex;
	}

	public void method01(){
    	System.out.println("method方法");
    }
	
	public void method02() {
		//注意:当本方法中没有相同名字的局部变量时,可以直接被this忽略掉
		///this.method01()
		//System.out.println(this.name + " -- " + this.age);
		
		method01();//调用本对象的方法
		System.out.println(name + " -- " + age + " -- " + sex);//调用本对象的属性
	}
}

static关键字

概念

static - 私有的

作用:

  1. 修饰属性:类属性/类变量/静态变量/静态属性,直接用类名调用

​ 应用场景:状态码(静态常量),后续会碰到

  1. 修饰方法:类方法/静态方法,直接用类名调

​ 应用场景:工具类,只需要使用类里的具体功能,那就把类视作工具类,类里的方法都是静态方法, 直接用类名调用即可

  1. 静态代码块:初始化数据

​ 应用场景:初始化该类的静态属性

具体使用
具体使用 - 修饰属性
public class Test {

	public static void main(String[] args) {

		MyClass m1 = new MyClass();
		MyClass m2 = new MyClass();

		m1.str1 = "成员属性1";
		m2.str1 = "成员属性2";
		System.out.println(m1.str1);
		System.out.println(m2.str1);
		
		//静态属性是该类所有对象共享的,是类属性,所以应该用类名调用
//		m1.str2 = "静态属性1";
//		m2.str2 = "静态属性2";
//		System.out.println(m1.str2);
//		System.out.println(m2.str2);
		
		m1.str2 = "静态属性2";
		System.out.println(MyClass.str2);
	}
}
class MyClass{
	String str1;
	static String str2;
}
具体使用 - 修饰方法
public class Test {

	public static void main(String[] args) {
		int[] is = {1,5,4,2,6};
		int max = MyArrays.getMax(is);
		System.out.println("获取数组中的最大值:" + max);
	}
}
//自定义数组工具类
class MyArrays{
	public static int getMax(int[] is) {
		int max = is[0];
		for (int i = 1; i < is.length; i++) {
			if(max < is[i]){
				max = is[i];
			}
		}
		return max;
	}
}
具体使用 - 静态代码块
public class Test {

	public static void main(String[] args) {
		for (String name : NameContainer.names) {
			System.out.println(name);
		}
	}
}
//姓名容器类
class NameContainer{
	static String[] names = new String[10];
	static{//初始化静态属性的数据
		names[0] = "吴彦祖";
		names[1] = "彭于晏";
		names[2] = "何翰宇";
	}
}
具体使用 -代码块调用法则
public class Test {

	public static void main(String[] args) {
		
		//输出:静态代码块 -> 代码 -> 构造方法
		MyClass m = new MyClass();
		
		//输出:静态代码块 -> 静态等待
		MyClass.method();
	}
}
class MyClass{
	
	String str1;
	static String str2;
	
	public MyClass() {
		System.out.println("构造方法");
	}
	
	{
		str1 = "aaa";
		System.out.println("代码块 - " + str1);
	}
	
	static{
		str2 = "bbb";
		System.out.println("静态代码 - " + str2);
	}
	
	public static void method() {
		System.out.println("静态方法");
	}
}

代码块调用法则总结:

  1. 代码块可以初始化属性
  2. 静态代码块可以初始化静态属性
  3. 使用该类就会把类的字节码文件(.class文件)加载到方法区中,此时就会调用静态代码块

静态变量和成员变量的区别

静态变量:类变量,该类的所有对象共享一份,(JDK1.7 - 存储在静态常量区中 ,JDK1.8 - 堆中)

成员变量:该变量每个对象独享一份,存储在堆内存的对象中

继承

概念

子类继承父类所有属性和方法

私有化属性和方法不能直接被调用,但是可以间接调用,见 “具体使用”

使用关键字extends继承:class 子类 extends 父类{}

具体使用
public class Test {
	public static void main(String[] args) {
		
		Chinese c = new Chinese();
		c.setChineseId("123...");  //操作子类的属性并调用子类的方法
		c.setName("吴彦祖");		 //操作父类的属性并调用父类的方法
		c.setAge(18);			   //操作父类的属性并调用父类的方法
		System.out.println(c.getChineseId());//操作子类的属性并调用子类的方法
		System.out.println(c.getName()); 	 //操作父类的属性并调用父类的方法
		System.out.println(c.getAge());		 //操作父类的属性并调用父类的方法
		c.playTaiJi();//调用子类的方法
		
		Japanese j = new Japanese();
		j.setJapaneseId("xxx...");//操作子类的属性并调用子类的方法
		j.setName("水菜丽");		 //操作父类的属性并调用父类的方法
		j.setAge(26);			 //操作父类的属性并调用父类的方法
		System.out.println(j.getJapaneseId());//操作子类的属性并调用子类的方法
		System.out.println(j.getName()); 	 //操作父类的属性并调用父类的方法
		System.out.println(j.getAge());		 //操作父类的属性并调用父类的方法
		j.playVideo();//调用子类的方法
	}
}
//父类
class Person{
	private String name;
	private int age;
	
	public Person() {
	}

	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
}
//子类
class Chinese extends Person{
	
	private String chineseId;//中国人的身份证(子类独有的属性)
	
	//子类独有的方法
	
	public Chinese() {
	}

	public Chinese(String chineseId) {
		this.chineseId = chineseId;
	}

	public String getChineseId() {
		return chineseId;
	}

	public void setChineseId(String chineseId) {
		this.chineseId = chineseId;
	}
	
	public void playTaiJi(){
		System.out.println("中国人:打太极");
	}
	
}
//子类
class Japanese extends Person{
	
	private String japaneseId;//日本人的身份证(子类独有的属性)
	
	//子类独有的方法
	
	public Japanese() {
	}

	public Japanese(String JapaneseId) {
		this.japaneseId = JapaneseId;
	}

	public String getJapaneseId() {
		return japaneseId;
	}

	public void setJapaneseId(String japaneseId) {
		this.japaneseId = japaneseId;
	}
	
	public void playVideo(){
		System.out.println("日本人:拍电影");
	}
}
好处

多个类里有相同的属性和方法就可以抽取出,形成一个共同的父类,减少代码的冗余

继承中的构造方法
public class Test {
	public static void main(String[] args) {
		
		Son son = new Son();
	}
}
class Father{
	public Father() {
		System.out.println("父类无参构造");
	}
}
class Son extends Father{
	public Son() {
		//super();默认调用父类的无参构造
		System.out.println("子类无参构造");
	}
}

继承中的构造方法总结:

​ 创建子类对象会不会调用父类构造方法?

​ 会

​ 创建子类对象调用父类构造方法的目的是什么?

​ 创建子类对象会在堆里开辟空间,调用父类构造方法的目的是在将父类属性拷贝一份存入子类对象中

​ 创建子类对象会创建父类对象吗?

​ 不会

​ 创建子类对象先调用父类构造方法还是子类构造方法?

​ 先调用子类构造方法,子类构造方法中的第一句默认super(),意思是调用父类无参构造

​ 创建子类对象先完成父类构造方法还是子类构造方法?

​ 先完成父类构造方法

super关键字

super 父类的,与this的使用类似

作用:

​ super.属性:调用父类的属性

​ super.方法:调用父类的方法

​ super():根据传参类型调用父类的构造方法

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

		Chinese c = new Chinese("吴彦祖",18,"123...");
		c.playTaiJi();//调用子类的方法

		Japanese j = new Japanese("水菜丽",26,"xxx...");
		j.playVideo();//调用子类的方法
	}
}
//父类
class Person{
	private String name;
	private int age;

	public Person() {
	}

	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
}
//子类
class Chinese extends Person{

	private String chineseId;

	public Chinese() {
	}

	public Chinese(String name, int age, String chineseId) {
		super(name, age);//调用父类的有参构造
		this.chineseId = chineseId;
	}

	public String getChineseId() {
		return chineseId;
	}

	public void setChineseId(String chineseId) {
		this.chineseId = chineseId;
	}

	public void playTaiJi(){
		//调用父类的方法(间接调用父类的私有化属性)
		System.out.println(super.getName() +  ":打太极");
	}

}
//子类
class Japanese extends Person{

	private String japaneseId;

	public Japanese() {
	}

	public Japanese(String name, int age, String japaneseId) {
		super(name, age);//调用父类的有参构造
		this.japaneseId = japaneseId;
	}

	public String getJapaneseId() {
		return japaneseId;
	}

	public void setJapaneseId(String japaneseId) {
		this.japaneseId = japaneseId;
	}


	public void playVideo(){
		//调用父类的方法(间接调用父类的私有化属性)
		System.out.println(super.getName() +  ":拍电影");
	}
}

Object类

概念及常用方法

所有类的祖先类/超类/基类,一个类没有明确继承某个父类,均自动继承Object

Object作为祖先类,起着类的标杆的作用

方法描述
equals(Object obj)比较两个对象是否一致
hashCode()返回该对象的hash值
getClass()返回该类的字节码文件对象
toString()返回该对象的字符串表示
方法演示
public class Test {
	public static void main(String[] args) {

		Object obj1 = new Object();
		Object obj2 = new Object();
		
		/**
		 * equals方法:比较两个对象是否一致
		 * 源码分析:
		 * 	public boolean equals(Object obj) {
		 *      return (this == obj);
		 *  }
		 * 理解:对象==对象,直接比较的是内存地址是否一致 
		 */
		boolean equals = obj1.equals(obj2);
		System.out.println(equals);//false
		
		/**
		 * hashCode方法:获取该对象的hash值
		 * 源码分析:
		 * 	public native int hashCode();//具体实现被java隐私化
		 * 理解:hash值是通过内存地址+算法 计算出的,但是hash值不等同于内存地址
		 */
		int hashCode = obj1.hashCode();
		System.out.println(hashCode);
		
		/**
		 * getClass方法:获取该类的字节码文件对象
		 * 源码分析:
		 * 	public final native Class<?> getClass();//具体实现被java隐私化
		 * 理解:java是面向对象的语言,在此语言里万物皆对象,字节码文件(.class)也不例外,也是个对		 * 象。任意一个类的字节码只加载到内存中一次,所以该类的字节码对象都是相同的
		 */
		Class c1 = obj1.getClass();
		Class c2 = obj2.getClass();
		System.out.println(c1);//class java.lang.Object
		System.out.println(c2);//class java.lang.Object
		System.out.println(c1 == c2);//true
		
		/**
		 * toString方法:获取该对象的字符串表示
		 * 源码分析:
		 * 	public String toString() {
         *		return getClass().getName() + "@" + Integer.toHexString(hashCode());
    	 *	}
    	 * 理解:返回值是 获取该字节码文件对象的名字 + "@" + 对象hash值的十六进制表示
		 */
		System.out.println(obj1);//默认调用toString()
		System.out.println(obj1.toString());
	}
}

访问修饰符

做实验证明访问权限

关键字访问权限
private本类
默认(什么都不写)本类、相同包下
protected本类、相同包下、子类同包
public全局

方法的重写

概念

如果父类里的方法不满足子类需求时,就可以重写

规则
  1. 在继承关系中的子类里重写
  2. 返回值、方法名、参数类型必须和父类一致
  3. 访问修饰符不能比父类更严格
实际运用
public class Test {
	public static void main(String[] args) {

		Student stu1 = new Student("吴彦祖", "班级号6666", "学号001");
		Student stu2 = new Student("吴彦祖", "班级号6666", "学号002");
		
		//调用重写后的equals来比较两个对象是否一致
		System.out.println(stu1.equals(stu2));//false(学号不一样)
		
		//调用重写后的toString输出想要的对象信息
		System.out.println(stu1);//吴彦祖 -- 班级号6666 -- 学号001
		System.out.println(stu2);//吴彦祖 -- 班级号6666 -- 学号002
		
	}
}
class Student{
	
	private String name;
	private String classId;//班级号
	private String id;//学号
	
	public Student() {
	}

	public Student(String name, String classId, String id) {
		this.name = name;
		this.classId = classId;
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getClassId() {
		return classId;
	}

	public void setClassId(String classId) {
		this.classId = classId;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}
	
	//重写父类的equals方法,好处:重写以后比较两个Student对象就是比较的是两个对象的班级号和学号
	@Override
	public boolean equals(Object obj) {
		Student stu = (Student) obj;//下转型
		if(this.classId.equals(stu.classId) 
				&& this.id.equals(stu.id)){
			return true;
		}
		return false;
	}
	
	//重写父类的toString方法,好处:输出Student对象,就可以获取该对象的属性信息
	@Override
	public String toString() {
		return name + " -- " + classId + " -- " + id;
	}
}

分包

分包的基本概念:防止类的重名

项目中运用分包:项目中会由很多类,类与类的功能有相同的也有不同的,所以要分包归类管理

项目中的命名规范:com.公司名.项目名.功能名(具体参照公司的命名规范)

ps:

​ 实体类 com.qf.vo/bean/entity

​ 工具类 com.dream.utils/tools

​ 数据库 com.dram.dao

​ …

final关键字

#### 概念

final - 最终的

作用:

​ final修饰类:类不能被继承

​ final修饰方法:方法不能被重写

​ final修饰变量:不能被重新赋值,变成常量(存储在常量池中)

具体使用
//final class Father{//最终的类:不能被继承
class Father{
	
	//public final void method() {//最终的方法:不能被子类重写
	public void method() {
		System.out.println("父类方法");
	}
}
class Son extends Father{
	@Override
	public void method() {
		final int i = 10;
		//i = 100;//不能给常量重新赋值
		System.out.println("重写父类的方法");
	}
}

抽象类和抽象方法

概念

抽象类:使用abstract修饰

抽闲方法:使用abstract修饰,该方法没有代码块,交给非抽象的子类去重写

思想:抽象类更像是个模板,规定了非抽象的子类应该要完成怎样的方法。当父类里的方法不好实现而该方法又必须写在父类时,可以选择设置为抽象方法,交给非抽象的子类去实现

注意:

  1. 抽象方法必须在抽象类中

    1. 抽象类可以没有抽象方法
    2. 抽象类的子类如果也是抽象类,子类可以不重写父类的抽象方法
    3. 抽象类的子类如果是非抽象类,子类必须重写父类的抽象方法
    4. C类继承抽象类B,抽象类B继承抽象类A,那么C类就必须重写A和B的抽象方法
    5. 抽象类不能new对象
具体使用1
abstract class A{
	public abstract void methodA();
}
abstract class B extends A{
	public abstract void methodB();
}
class C extends B{
	@Override
	public void methodB() {
		System.out.println("重写抽象B方法");
	}
	@Override
	public void methodA() {
		System.out.println("重写抽象A方法");
	}
}
具体使用2
abstract class Person{
	public abstract void eat();
}
class Chinese extends Person{
	@Override
	public void eat() {
		System.out.println("中国人吃山珍海味");
	}
}
class Japanese extends Person{
	@Override
	public void eat() {
		System.out.println("日本人吃马赛克");
	}
}

接口

概念

接口,使用interface修饰,是个特殊的抽象类,当抽象类里只有静态常量或抽象方法时,可以用接口代替

注意:

  1. 接口里可以有静态常量或抽象方法,JDK1.8新特性还添加了默认方法和静态方法

    1. 接口可以继承多个接口
    2. 一个类只能继承一个父类,可以实现多个接口
    3. 接口不能new对象
具体使用1
public  class Test {
	public static void main(String[] args) {

		MyClass m = new MyClass();
		m.defaultMethod();//调用I1接口中的默认方法
		I1.staticMethod();//调用I1接口中的静态方法
	}
}
interface I1{
	public abstract void i1Method();
	
	default void defaultMethod(){
		System.out.println("I1中的默认方法");
	}
	
	public static void staticMethod(){
		System.out.println("I1中的静态方法");
	}
}
interface I2 extends I3,I4{
	public abstract void i2Method();
}
interface I3{
	public abstract void i3Method();
}
interface I4{
	public abstract void i4Method();
}
class MyClass implements I1,I2{

	@Override
	public void i3Method() {
		System.out.println("实现I3中的抽闲抽象方法");
	}

	@Override
	public void i4Method() {
		System.out.println("实现I4中的抽闲抽象方法");
	}

	@Override
	public void i2Method() {
		System.out.println("实现I2中的抽闲抽象方法");
	}

	@Override
	public void i1Method() {
		System.out.println("实现I1中的抽闲抽象方法");
	}
} 
具体使用2
interface IPerson{
	public abstract void eat();
}
class Chinese implements IPerson{
	@Override
	public void eat() {
		System.out.println("中国人吃山珍海味");
	}
}
class Japanese implements IPerson{
	@Override
	public void eat() {
		System.out.println("日本人吃马赛克");
	}
}

类与接口之间的关系

关系描述
类与类单继承
类与接口多实现
接口与接口多继承

多态

概念

多种形态

类的多态
public  class Test {
	public static void main(String[] args) {
		/**
		 * 需求:老师骑着自行车、汽车上班
		 * 
		 * 注意:此代码的设计符合OCP(开闭)原则
		 * 
		 * OCP原则 - OpenClosePrinciple
		 * 含义:需求升级时,对创建新类是欢迎的,对修改原有类是拒绝的
		 * 好处:修改原有类容易造成bug
		 * 
		 * 体现:试一试新加一个飞机类
		 * 步骤:
		 * 	创建Plane类,继承Vehicle类,
		 * 	修改main方法中Vehicle v = new Plane();
		 * 	注意:修改main方法不算修改,因为是测试代码的
		 */
		
		Teacher t = new Teacher();
		
		//类的多态:子类对象指向父类引用,引用里存的是子类对象的地址
		//Vehicle v = new Bike();
		Vehicle v = new Car();
		
		t.open(v);
		System.out.println("老师欣赏沿途的风景...");
		t.close(v);
	}
}
class Teacher{
	public void open(Vehicle v){//启动
		v.start();
	}
	public void close(Vehicle v){//关闭
		v.stop();
	}
}
class Car extends Vehicle{
	@Override
	public void start() {
		System.out.println("汽车开");
	}
	@Override
	public void stop() {
		System.out.println("汽车停");
	}
}
class Bike extends Vehicle{
	@Override
	public void start() {
		System.out.println("自行车开");
	}
	@Override
	public void stop() {
		System.out.println("自行车停");
	}
}
abstract class Vehicle{//交通工具
	public void start();
	public void stop();
}
接口的多态
public  class Test {
	public static void main(String[] args) {
		/**
		 * 需求:电脑连接usb,使用鼠标和硬盘
		 * 
		 * 注意:此代码的设计符合OCP(开闭)原则
		 * 
		 * 体现:试一试新加一个键盘Keyboard类
		 * 步骤:
		 * 	创建Keyboard类,实现IUSB接口,
		 * 	修改main方法中IUSB usb = new Keyboard();
		 * 	注意:修改main方法不算修改,因为是测试代码的
		 */
		
		Computer com = new Computer();
		
		//接口的多态:实现类对象执行接口的引用,引用里存的是实现类对象的地址
		//IUSB usb = new Mouse();
		IUSB usb = new Disk();
		
		com.connection(usb);
	}
}
class Computer{//电脑类
	public void connection(IUSB usb){
		usb.use();
	}
}
class Mouse implements IUSB{
	@Override
	public void use() {
		System.out.println("鼠标:左点点、右点点");
	}
}
class Disk implements IUSB{
	@Override
	public void use() {
		System.out.println("硬盘:上传文件、下载文件");
	}
}
interface IUSB{//接口
	public void use();//使用的抽象方法
}

对象转型

简介

引用数据的转型

向上转型:子类 转 父类类型

向下转型:父类 转 子类类型,又称为引用数据类型的强转

对象的向上转型

向上转型就是多态

注意:

  1. 可以直接调用父类非私有化属性

    1. 可以直接调用父类非私有化方法
    2. 可以直接调用子类重写父类的方法

向上转型即多态的缺点:不能调用子类的属性和方法

public  class Test {
	public static void main(String[] args) {
		
		//向上转型:就是多态
		Father f = new Son();
		
		System.out.println(f.fatherStr);//父类属性
		f.fatherMethod01();//父类方法01
		f.fatherMethod02();//子类重写父类方法02
	}
}
class Father{
	String fatherStr = "父类属性";
	
	public void fatherMethod01(){
		System.out.println("父类方法01");
	}
	public void fatherMethod02(){
		System.out.println("父类方法02");
	}
}
class Son extends Father{
	String fatherStr = "子类和父类同名的属性";
	String sonStr = "子类属性";
	
	public void sonMethod(){
		System.out.println("子类方法");
	}
	
	@Override
	public void fatherMethod02() {
		System.out.println("子类重写父类方法02");
	}
	
}
对象的向下转型

向下转型一定要用instanceof判断对象类型

public  class Test {
	public static void main(String[] args) {
		
		Animal an = new Dog();//向上转型 
		
		//Cat cat = (Cat) an;//直接向下转型容易造成类型转换异常

		if(an instanceof Dog){//判断引用an中指向的对象是否是Dog类
			//向下转型
			Dog dog = (Dog) an;
		}else if(an instanceof Cat){//判断引用an中指向的对象是否是Cat类
			//向下转型
			Cat cat = (Cat) an;
		}
	}
}
class Animal{//动物类
}
class Dog extends Animal{
}
class Cat extends Animal{
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值