Java面向对象(中)

继承

   当子类继承父类,可以使子类拥有和父类相同的属性和相同的行为

继承的好处(学习目的)

   1.学习继承是学习"实现"的前提条件
   2.学习继承是学习"多态"的前提条件之一
   3.提高代码的复用性,从而提高开发效率
   4.提高代码的扩展性

继承的格式

   public class 父类类名 {}

   public class 子类类名 extends 父类类名 {}

继承的特点

   1.子类拥有和父类相同的属性和相同的行为
   2.在程序中一个子类只能拥有一个直接父类(单继承),一个父类可以拥有多个直接子类
   3.Java中虽然不支持多继承,但是支持多层继承
   4.在程序中父类和子类是一对相对的概念,例如C类继承B类,B类继承A类
       A类是B类的直接父类,A类是C类的间接父类,B类是C类的直接父类
       C类是B类的直接子类,C类是A类的间接子类,B类是A类的直接子类
   5.在Java中所有类都隐式继承一个类,这个类就是Java中顶级父类Object 

在继承关系中各成员和内容的特点

   私有成员
   静态成员
   实例变量
   实例方法
   构造器

在继承关系中私有成员的特点

   	官方结论:
       1.子类可以继承父类中所有的成员
       2.子类可以继承同包下父类的私有成员
       3.子类不可以继承父类的私有成员
       
	自己总结:
        子类可以继承父类的私有成员,但受限于private关键字的特点,
		无法直接进行方法,如果想进行访问,需要借助公共获取方式

继承关系中静态成员的特点

   子类可以继承父类的静态成员

继承关系中实例变量的特点

   子类可以继承父类中的实例变量

this和super关键字

this关键字的第一种用法:
   场景:
       子类的构造器中或子类的实例方法中
   格式:
       this.实例变量名;
       this.实例方法名(实参);
   作用:
       用来区分同一个类中同名的实例变量和局部变量
   含义:
       哪个对象调用了this关键字所在的构造器或实例方法,this关键字就代表哪个对象

super关键字的第一种用法:
   场景:
       子类的构造器中或子类的实例方法中
   格式:
       super.实例变量名;
       super.实例方法名(实参);
   作用:
       用来区分子父类继承关系中同名的实例变量
       用来区分子父类继承关系中同名的实例方法
   含义:
       哪个对象调用了super关键字所在的构造器或实例方法,super关键字就代表哪个对象的父类引用
	//子类的实例变量
	int num = 20;

	public void method () {
		//子类的局部变量
		int num = 30;

		System.out.println("num = " + num);//30 就近原则
		System.out.println("num = " + this.num);//20
		System.out.println("num = " + super.num);//10  父类的实例变量
	}

在继承关系中实例方法的特点

   子类可以继承父类的实例方法

继承关系中构造器的特点

   1.在初始化子类子类成员前先初始化父类成员,主要是由子类构造器中第一部分的内容进行加载父类的构造器
   2.当一个类的构造器中没有任何this(实参)或super(实参)时,JVM会自动分配一个super(),用来初始化子类实例成员前先初始化父类引用成员,反之不会进行分配
   3.父类的构造器子类不可以继承

方法的重写:

   含义:
       在继承关系中(或实现关系中),出现了方法名相同,形参列表相同,权限访问级别和返回类型遵循相关规则的现象
   目的:
       为了后期进行功能的扩展,并且保留原有的功能,需要将父类的方法进行重写
		//创建子类对象
		SubClass sc = new SubClass();

		//调用method()
		sc.method();

		//父类
		public void method () {
			System.out.println("父类的实例方法");
		}

		public void message () {
			System.out.println("文字短信");
		}

		//子类
		public void method () {
			System.out.println("子类的实例方法");
			//return 10;
		}

		public void message () {
			System.out.println("文字短信");
			System.out.println("图片彩信");
			System.out.println("......");
		}

方法重写的前提条件(必须满足以下全部的条件)

   1.必须要有继承关系或者实现关系
   2.重写方法的方法名必须和被重写方法的方法名相同
   3.重写方法的形参列表必须和被重写方法的形参列表相同
   4.重写方法的权限访问级别必须大于等于被重写方法的权限访问级别,并且遵循方法重写有关权限访问级别的注意事项
   (详见方法重写的注意事项)
   5.在内存中,重写方法的返回类型必须和被重写方法的返回类型相同

 回顾方法重载的前提条件(必须满足以下全部的条件)
   1.必须在同一个类中或者子父类继承关系中
   2.方法名必须相同
   3.形参列表必须不同(至少满足以下一点)
       (1)形参的个数不同
       (2)形参的数据类型不同
       (3)形参的数据类型顺序不同

方法重写的注意事项
   1.在程序中有些时候即使不满足方法的重写规则,代码也不会编译报错进行提示,例如:继承关系中的方法重载;Java中提供了一种特殊
   的语法规则--注解
       注解
           含义:
               Java中提供用来检测一些特殊语法格式的特定接口,其中就包含一个用来检测子类方法是否满足重写规则的注解
           位置:
               声明在子类重写方法上
           格式:
               @Override
               修饰符 返回类型 子类重写方法的方法名 () {}
           好处:
               将不符合Java重写语法规则的情况提前到编译期
   2.父类的私有方法不可以被子类进行重写
   3.不同包下父类的缺省方法不可以被子进行重写
   4.父类的静态方法不可以被子类进行重写,在子类中编写和父类同名且同形参列表的方法时,也需要遵循方法重写的语法规则
   (往往出现在面试过程中的笔试题)
   5.在代码中,
       当父类被重写方法的返回类型是void时,子类重写父类该方法时返回类型也必须是void
       当父类被重写方法的返回类型是基本类型时,子类重写父类该方法时返回类型也必须是该基本类型
       当父类被重写方法的返回类型是引用类型时,子类重写父类该方法时返回类型可以是该类型本身,也可以是该类型的子类类型;
       (其实就是即将要讲解的面向对象第三大特征多态)

this关键字和super关键字的第二种用法

   场景:
       子类的构造器中
   格式:
       this(实参);
   作用:
       调用本类中其它的构造器
   含义:
       当构造器没有进行实例初始化时,通过this(实参)调用本类中其它构造器完成了实例初始化

super关键字的第二种用法:
   场景:
       子类的构造器中
   格式:
       super(实参);
   作用:
       调用父类对应参数的构造器
   含义:
       在初始化子类实例成员前,先通过super()调用父类构造器完成父类的成员初始化操作

this关键字和super关键字的注意事项:

   1.在静态成员中不可以使用this关键字和super关键字
   2.在创建继承关系中的子类对象时,在子类的构造器中或实例方法中可以正常打印this关键字,但不可以打印super关键字
   3.在构造器中this(实参)或super(实参)必须编写在第一行
   4.在构造器中this(实参)或super(实参)不可以同时使用

猫鼠案例

//animal类
	private String name;
	private int age;

	public Animal() {
	}

	public Animal(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;
	}

	//抽取子类们相同且需要子类们进行重写的方法
	public void eat () {
		System.out.println("吃东东");
	}

	//抽取子类们相同且不需要子类们进行重写的方法
	public void sleep() {
		System.out.println("睡觉觉");
	}
//cat类
	//重写父类中的eat()
	@Override
	public void eat () {
		System.out.println(getAge() + "岁的" + getName() + "正在吃鱼");
	}

	//猫有特有方法
	public void catchMouse () {
		System.out.println(getAge() + "岁的" + getName() + "正在抓老鼠");
	}

	public Cat() {
		super();
	}

	public Cat(String name, int age) {
		super(name, age);
	}
//dog类
	//重写父类中的eat()
	@Override
	public void eat () {
		System.out.println(getAge() + "岁的" + getName() + "正在吃骨头");
	}

	//狗有特有方法
	public void lookHome () {
		System.out.println(getAge() + "岁的" + getName() + "正在看家");
	}

	public Dog() {
		super();
	}

	public Dog(String name, int age) {
		super(name, age);
	}
//main方法
		//创建猫对象
		Cat cat = new Cat("Tom", 2);
		cat.catchMouse();
		cat.eat();
		cat.sleep();

		System.out.println("================================");

		//创建狗对象
		Dog dog = new Dog("TwoHa", 3);
		dog.lookHome();
		dog.eat();
		dog.sleep();

Object类

   类的特点
       1.Object类是类层次的顶级父类
       2.所有的对象(包括数组)都可以调用Object类中的方法
       3.在所有的接口中都隐式含有Object类中方法的抽象形式(暂不涉及)
   类的位置
       java.lang
   类的构造器
       public Object()
           该构造器的作用不是用来创建Object类的对象的,而是创建Object类子类的对象时,
           在初始化子类成员之前通过super()调用Object类的构造器,完成父类成员的初始化工作
   类的方法
       public boolean equals(Object obj)
           指示其他某个对象是否与此对象“相等”。
       public String toString()
           返回该对象的字符串表示。

==和equals()的区别:
   ==既可以比较基本类型的数据,也可以比较引用类型的数据
       当比较基本类型的数据时,比较的是基本类型的数据值是否相等
       当比较引用类型的数据时,比较的是引用类型的地址值是否相等
  equals()只能比较引用类型的地址值是否相等,不能比较基本类型
       当比较引用类型的数据时,比较的是引用类型的地址值是否相等
       当比较的引用类型重写Object类中的equals(),需要根据重写后的规则进行比较

特殊的实例方法toString()
 		 在使用输出语句打印对象名(包含数组)时,其实就是在隐式调用toString(),打印char[]数组除外
		//创建2个学生对象
		Student s1 = new Student();
		Student s2 = new Student();
		System.out.println(s1);
		System.out.println(s2);

		//比较两个对象地址值是否相等
		System.out.println(s1.equals(s2));
		System.out.println(s1 == s2);

		//创建学生对象
		Student s = new Student();
		System.out.println(s.toString());
		System.out.println(s);

		//创建int类型数组
		int[] ints = {11,22,33};
		System.out.println(ints.toString());
		System.out.println(ints);

		//创建char类型数组
		char[] chars = {'a','b','c'};
		System.out.println(chars.toString());
		System.out.println(chars); //abc

权限访问级别

 封装思想的核心就是权限访问级别,给不同的内容添加不同的权限访问级别

 权限访问级别从小到大的顺序是:
   private < 缺省 < protected < public

 权限访问级别修饰内容的范围:
   private级别:
       修饰范围:
           被private修饰的内容只能在本类中有效,在本类之外无法进行访问
   "缺省"级别:
       修饰范围:
           兼容private级别的作用范围
           "缺省"级别的内容在本包(同一个包)中有效,在本包(同一个包)之外位无法进行访问
   protected级别:
       修饰范围:
           兼容"缺省"级别的作用范围
           protected级别修饰的内容在同一个项目且有继承关系时有效
               如果同一个模块中,可以直接使用
               如果不在同一个模块中,修改项目的配置文件,无需手动修改可以使用alt+enter
  public级别:
       修饰范围:
           兼容"protected"级别的作用范围
           public级别修饰的内容在同一个项目有效
               如果同一个模块中,可以直接使用
               如果不在同一个模块中,修改项目的配置文件,无需手动修改可以使用alt+enter

权限访问级别的补充:

   类(class,interface,enum)文件:
       权限级别:只能public和缺省,推荐使用public
   类中的成员量:
       权限级别:四种都可以,推荐使用private
   类中的成员方法:
       权限级别:四种都可以,推荐使用public(常规方法),protected(复杂继承关系),private(只限自己访问的方法)
   类中的成员内部类:
       权限级别:四种都可以,推荐使用缺省和private
   类中的构造器:
       权限级别:四种都可以,推荐使用public(常规)和private(在外界不想创建对象时)
   类中的构造器代码块:
       权限级别:只能缺省
   类中的静态代码块:
       权限级别:只能缺省
   局部内容:
      权限级别:只能缺省

abstract(抽象) 关键字

关键字的由来(继承关系代码中存在的安全隐患)
   1.父类是多个子类抽取的共性内容,希望这个类不可以被实例化对象,但是实际上可以创建父类对象
   2.父类中抽取多个子类相同且需要重写的方法,最终创建对象调用的方法肯定执行子类重写后的方法,父类声明的方法就显得不是那么重要了,希望在父类中声明这个方法时,省略方法体,但是实际上省略方法体代码编译报错;
   3.程序员在重写父类中的方法时,偶尔会出现忘记某个类重写方法,希望代码编译报错进行友情提示,但是实际上没有任何提示

为了解决上述问题,引出面向对象中的"抽象"

abstract关键字:

   含义:
       抽象的
   修饰:
       类(class),方法

抽象类:
   含义:
       被abstract关键字修饰的类,也被称之为"加强版父类"或者"父类plus"
   位置:
       修饰父类
   格式:
       public abstract class 父类类名 {}
   注意:
       1.被abstract关键字修饰的类,不可以被实例化对象
       2.抽象类中可以含有构造器,构造器的作用是创建子类对象时,初始化父类成员用的
       
抽象方法:
   含义:
       被abstract关键字修饰且没有方法体的方法
   位置:
       抽象类中
   格式:
       修饰符 abstract 返回类型 方法名 ();
   注意:
       1.抽象类可以没有抽象方法,但是含有抽象方法的类一定是抽象类
       2.抽象类的子类必须重写抽象父类中所有抽象方法,否则编译报错,除非该子类也是抽象类

猫鼠案列

//animal 类
	public abstract class Animal {
		private String name;
		private int age;
	
		public Animal(String name, int age) {
			this.name = name;
			this.age = age;
		}
		public Animal() {
		}
		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;
		}
		//抽取子类们中的共性方法,且需要重写
		public abstract void eat();
		//抽取子类们中的共性方法,且不需要重写
		public void sleep () {
			System.out.println("睡觉觉");
		}
	}
//其余的和上面的一样

final关键字

   含义:
       不可改变的,最终的
   修饰:
       类,方法,变量
   特点:
       被final修饰的类,不可以被继承
       被final修饰的方法,不可以被重写
       被final修饰的变量,不可以被重新赋值,其实就是自定义常量

最终类:

   含义:
       被final修饰的类
   格式:
       public final class 类名 {

       }
   注意:
       1.被final修饰的类,不可以被继承
       2.abstract关键字和final关键字不可以同时修饰一个类

最终方法:

   含义:
       被final关键字修饰的成员方法
   格式:
       修饰符 final 返回类型 方法名 () {}
   注意:
       1.被final关键字修饰的成员方法不可以被重写
       2.abstract关键字和final关键字不可以同时修饰一个方法

自定义常量:

   含义:
       被final修饰的变量
   格式:
       修饰符 final 数据类型 常量名 = 初始化值;
   分类:
       局部常量
       实例常量
       静态常量
   注意:
       1.被final修饰的变量不可以被二次赋值,其实就是一个自定义常量
       2.常量名的命名规范:
           一个单词:
               单词全部大写
           多个单词:
               单词全部大写,且每个单词间使用下划线连接
       3.在程序中,JVM会将被final修饰,且通过直接声明初始化的自定义常量当成字面值常量进行使用

实例常量:

   含义:
       被final关键字修饰的实例变量
   注意:
       1.实例常量在进行加载的时候,JVM不会给其进行赋默认值操作
       2.如果实例常量在成员中进行先声明后初始化,我们需要在所有的构造器中完成实例常量的赋值操作
           如果所有构造器中给该实例常量赋的值都相同,可以将该条代码提取到"构造器代码块"中
           如果所有构造器中给该实例常量赋的值不相同,只能在每个构造器中进行赋值操作

静态常量:

   含义:
       被final关键字修饰的静态变量
   注意:
       1.静态常量在进行加载的时候,JVM不会给其进行赋默认值操作
       2.如果静态常量在成员中进行先声明后初始化,我们需要在静态代码块中给该静态常量进行初始化赋值操作

接口

   含义:
       接口和类都是数据类型
       接口是定义一组固定数据和行为的标准
   好处:
       1.开发过程中的标准(类似于写论文的"大纲"或者"脑图")
       2.提高程序的扩展性
       3.提高程序的复用性,从而提高开发效率
       4.学习接口的"实现关系",是学习多态的前提条件之一
       5.接口的实现关系可以避免单继承的局限性

接口的格式

   public interface 父接口名 {
       内部接口(暂不涉及)
       静态常量
       抽象方法
       默认方法(JDK8.0)
       静态方法(JDK8.0)
       私有方法(JDK9.0)
   }

实现类的格式:
   在实现的同时,也具有继承关系:
       public class 实现类类名 extends 父类类名 implements 父接口名1,父接口名2,......,父接口名n{}
   在实现的同时,没有继承关系:
      public class 实现类类名 implements 父接口名1,父接口名2,......,父接口名n{}

接口的继承格式(了解):
   public interface 接口名 extends 父接口名1,父接口名2,......,父接口名n{}

 接口的注意事项:
   1.接口中的成员只有6个:内部接口,静态常量,抽象方法,默认方法,静态方法,私有方法,除外之外没有任何内容
   2.接口无法直接创建对象,但是可以通过接口创建实现类对象
       实现类:类与接口之间的关系是实现关系(和继承类似,但有些不同),将实现接口的类称之为实现类
   3.程序中类文件的关系(类,接口)
       类与类之间的关系:
           单继承
       类与接口之间的关系:
           多实现
       接口与接口之间的关系:
           多继承

接口的使用

   1.根据接口创建接口的实现类
   2.重写接口中的抽象方法
   3.在测试类中创建接口的实现类对象
   4.调用实现类对象的方法完成需求

接口中的静态常量

   格式:
       [public] [static] [final] 数据类型 常量名 = 初始化值
   调用:
       接口名.静态常量名
   注意:
       1.接口中声明的静态常量只能直接声明初始化,不可以先声明后初始化
       2.[]中的关键字在声明接口中的静态常量时,可以省略不写,如果不写,由JVM隐式补全
       3.实现类可以继承接口中的静态常量

接口中的抽象方法:

   格式:
       [public] [abstract] 返回类型 方法名 ();
   注意:
       []中的关键字可以省略不写,如果不写由JVM进行补全

接口的默认方法(JDK8.0):

   含义:
       其实就是接口实现类的实例方法,为了满足JavaBean设计规范,将实例方法提取到接口中以默认方法形式声明
   格式:
       [public] default 返回类型 方法名 () {}
   注意:
       [ ]中public可以省略不写,如果不写由JVM自动补全

猫狗案例(接口版)

//animalInterface 接口类
	public interface AnimalInterface {
		//设计动物吃功能,需要重写
		void eat();
	
		//设计动物睡觉功能,不需要重写
		default void sleep() {
			System.out.println("睡觉觉");
		}
	}

//animal 类
	public abstract class Animal implements AnimalInterface {
		private String name;
		private int age;
	
		public Animal() {
		}
		public Animal(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;
		}
	}

// cat 类
	public class Cat extends Animal {
		public Cat() {
		}
	
		public Cat(String name, int age) {
			super(name, age);
		}
	
		@Override
		public void eat() {
			System.out.println(getAge() + "岁的" + getName() + "正在吃鱼");
		}
	
		//猫的特有方法
		public void catchMouse () {
			System.out.println(getAge() + "岁的" + getName() + "正在抓老鼠");
		}
	}
//dog 类
	public class Dog extends Animal {
		public Dog() {
		}
	
		public Dog(String name, int age) {
			super(name, age);
		}
	
		@Override
		public void eat() {
			System.out.println(getAge() + "岁的" + getName() + "正在吃骨头");
		}
	
		//狗的特有方法
		public void lookHome () {
			System.out.println(getAge() + "岁的" + getName() + "正在看家");
		}
	}
//main 方法
		//创建猫对象
		Cat cat = new Cat("Tom", 2);
		cat.catchMouse();
		cat.eat();
		cat.sleep();

		System.out.println("===============");

		//创建狗对象
		Dog dog = new Dog("TwoHa", 3);
		dog.lookHome();
		dog.eat();
		dog.sleep();

默认方法

默认方法学习目的:
    1.源码中存在默认方法
    2.面试题或笔试题

默认方法的注意事项
   1.一个类继承父类同时实现父接口,父类中的实例方法和父接口中的默认方法发生同名的会时候,通过子类对象调用这个同名的方法,
   执行的是父类中的实例方法
   2.一个类不继承父类,同时实现多个父接口,且多个父接口中存在同名的默认方法,此时子类会编译报错,需要子类重写父接口中的同名
   默认方法才可以

接口中的静态方法(JDK8.0)

   格式:
       [public] static 返回类型 方法名 () {}
       []中关键字可以省略不写,当不写时由JVM自动进行填补
   调用:
       接口名.静态方法名();
   注意:
       继承关系和实现关系的区别:
           1.在继承关系中子类可以继承父类的静态方法
             在实现关系中实现类不可以继承父接口的静态方法
           2.继承关系:
               如果是类与类之间的关系:只支持单继承
               如果是接口与接口之间的关系:支持多继承
             实现关系:
               类与接口之间的关系:多实现

接口中的私有方法(JDK9.0)

   格式:
       private 返回类型 方法名 () {}
           没有static的私有方法是抽取多个默认方法的共性内容存储在私有方法中
       private static 返回类型 方法名 () {}
           含有static的私有方法是抽取多个静态方法的共性内容存储在私有方法中
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Patient365

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值