前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JavaSE篇学习之路:(六)【面向对象------中】

JavaSE篇学习之路:(六)【面向对象------中】

作者头像
百思不得小赵
发布2022-12-01 11:40:39
2550
发布2022-12-01 11:40:39
举报
文章被收录于专栏:小赵Java总结

目录

第一章:继承(Extexnds)

1.1什么是继承?作用?

继承:指一个对象直接使用另一对象的属性和方法 继承的作用: 基本作用:子类继承父类,代码可以得到复用。 主要(重要)作用:因为有了继承关系,才有了后期的方法覆盖和多态机制。

2.1继承相关特性

代码语言:javascript
复制
    ① B类继承A类,则称A类为超类(superclass)、父类、基类,
	B类则称为子类(subclass)、派生类、扩展类。
		class A{}
		class B extends A{}
		我们平时聊天说的比较多的是:父类和子类。
		superclass 父类
		subclass 子类

	② java 中的继承只支持单继承,不支持多继承,C++中支持多继承,
	这也是 java 体现简单性的一点,换句话说,java 中不允许这样写代码:
		class B extends A,C{ } 这是错误的。

	③ 虽然 java 中不支持多继承,但有的时候会产生间接继承的效果,
	例如:class C extends B,class B extends A,也就是说,C 直接继承 B,
	其实 C 还间接继承 A。

	④ java 中规定,子类继承父类,除构造方法不能继承之外,剩下都可以继承。
	但是私有的属性无法在子类中直接访问。(父类中private修饰的不能在子类中
	直接访问。可以通过间接的手段来访问。)

	⑤ java 中的类没有显示的继承任何类,则默认继承 Object类,Object类是 
	java 语言提供的根类(老祖宗类),也就是说,一个对象与生俱来就有 
	Object类型中所有的特征。

	⑥ 继承也存在一些缺点,例如:CreditAccount 类继承 Account 类会导致它
	们之间的耦合度非常高,Account 类发生改变之后会马上影响到 CreditAccount 类

什么时候可以使用继承? 能使用“is a”关系可描述清楚。

3.1方法覆盖(OverRide)

什么是方法覆盖? 当子类继承父类后,继承过来的方法无法满足子类的需求,子类将这个方法进行重写。 将继承过来的方法进行覆盖,执行覆盖后的方法。

方法覆盖满足的条件:

  1. 两个类为继承关系。
  2. 重写之后的方法和之前方法具有:相同返回值类型,相同方法名,相同形参列表
  3. 访问权限不能更低,只能更高。
  4. 重写之后的方法不能比之前的方法抛出个更多异常。

注意事项:

  1. 方法覆盖只针对于方法,与属性无关。
  2. 私有方法无法覆盖
  3. 构造方法无法覆盖
  4. 方法覆盖只针对实例方法,静态方法无意义。

代码演示:

代码语言:javascript
复制
/**
 * 父类:动物类
 */
class Animal{
    private String name;
    //无参构造方法
    public Animal() {

    }
	//有参构造方法
    public Animal(String name) {
        this.name = name;
    }
    //动物具有吃东西的方法
    public void eat(){

    }
}
代码语言:javascript
复制
/**
 * 猫继承动物类  猫是动物
 */
class Cat extends Animal{
	//无参构造方法
    public Cat(){

    }
    //猫类重写父类eat()方法!
    public void eat(){
        System.out.println("猫吃猫粮!");
    }

}
代码语言:javascript
复制
/**
 * 狗继承动物类 狗是动物
 */
class Dog extends Animal{
	//无参构造方法
    public Dog(){

    }
    //狗类重写父类的eat()方法!
    public void eat(){
        System.out.println("狗吃狗粮!!");
    }
}
代码语言:javascript
复制
/**
 1. 测试类
 */
public class Demo {
    public static void main(String[] args) {
       //创建猫对象
        Cat cat=new Cat();
        //猫吃东西
        cat.eat();
       //创建狗对象
        Dog dog=new Dog();
        //狗吃东西
        dog.eat();
    }
}

第二章:多态

1.1什么是多态?

代码语言:javascript
复制
多种形态,多种状态,编译和运行有两个不同的状态。
	编译期叫做静态绑定。
	运行期叫做动态绑定。
	Animal a = new Cat();
	// 编译的时候编译器发现a的类型是Animal,所以编译器会去Animal类中找move()方法
	// 找到了,绑定,编译通过。但是运行的时候和底层堆内存当中的实际对象有关
	// 真正执行的时候会自动调用“堆内存中真实对象”的相关方法。
	a.move();
	多态的典型代码:父类型的引用指向子类型的对象。

2.1基础语法

向上转型和向下转型的概念:

代码语言:javascript
复制
	向上转型:子--->父 (upcasting)
		又被称为自动类型转换:Animal a = new Cat();

	向下转型:父--->子 (downcasting)
		又被称为强制类型转换:Cat c = (Cat)a; 需要添加强制类型转换符。
	什么时候需要向下转型?
			需要调用或者执行子类对象中特有的方法。
			必须进行向下转型,才可以调用。
	向下转型有风险吗?
			容易出现ClassCastException(类型转换异常)
	怎么避免这个风险?
		    instanceof运算符,可以在程序运行阶段动态的判断某个引用指向的对象
			是否为某一种类型。
			养成好习惯,向下转型之前一定要使用instanceof运算符进行判断。
	
	不管是向上转型还是向下转型,首先他们之间必须有继承关系,这样编译器就不会报错。

代码演示:

代码语言:javascript
复制
public class OverrideTest05{
	public static void main(String[] args){
		// 静态方法可以使用“引用.”来调用吗?可以
		// 虽然使用“引用.”来调用,但是和对象无关。
		Animal a = new Cat(); //多态
		// 静态方法和对象无关。
		// 虽然使用“引用.”来调用。但是实际运行的时候还是:Animal.doSome()
		a.doSome();

	}
}

class Animal{
	// 父类的静态方法
	public static void doSome(){
		System.out.println("Animal的doSome方法执行!");
	}
}

class Cat extends Animal{
	// 尝试在子类当中对父类的静态方法进行重写
	public static void doSome(){
		System.out.println("Cat的doSome方法执行!");
	}
}

3.1 instanceof运算符

类型向下转型时,必须使用instanceof进行判断。 强调:

  1. 在运行阶段动态判断引用指向对象类型
  2. 语法: 引用 instanceof 类型
  3. 运算结果为:true 或者false
  4. 假设C instanceof Cat为true,则C引用指向堆内存Java对象为一个Cat,如果为False 说明不是一个Cat

代码演示:

代码语言:javascript
复制
/**
 * 父类:动物类
 */
class Animal{

    public Animal() {

    }
    //动物具有吃东西的方法
    public void eat(){

    }
}
代码语言:javascript
复制
/**
 * 猫继承动物类  猫是动物
 */
class Cat extends Animal {
    public Cat() {

    }
    //猫类重写父类eat()方法!

    public void eat() {
        System.out.println("猫吃猫粮!");
    }

    public void run(){
        System.out.println("猫在走猫步");
    }

}
代码语言:javascript
复制
/**
 * 狗继承动物类 狗是动物
 */
class Dog extends Animal{

    public Dog(){

    }
    //狗类重写父类的eat()方法!
    public void eat(){
        System.out.println("狗吃狗粮!!");
    }
    public void run(){
        System.out.println("狗仔跳墙!1");
    }
}
代码语言:javascript
复制
/**
 * 测试类
 */
public class Demo {
    public static void main(String[] args) {
        //向下转型:父类调用子类特有的方法。
        Animal animal=new Cat();
        Animal animal1=new Dog();
        //必须使用instanceof进行判断
        if(animal instanceof Cat) {
            Cat c=(Cat) animal;
            c.run();//子类特有
        }else if (animal1 instanceof Dog){
            Dog d=(Dog) animal1;
            d.run();//子类特有
        }

    }
}

4.1 super关键字

  1. super能出现在实例方法和构造方法中。
  2. super的语法是:“super.”、“super()”
  3. super不能使用在静态方法中。、
  4. super. 大部分情况下是可以省略的。
  5. super() 只能出现在构造方法第一行,通过当前的构造方法去调用“父类”中的构造方法,目的是:创建子类对象的时候,先初始化父类型特征。
  6. super()表示通过子类对象调用父类的构造方法
  7. 当一个无参构造方法第一行既没有this()也没有super()默认有一个super().
  8. this()与super()不饿共存,且只在第一行.父类构造方法一定执行

什么时候super不能省略? 如果父与子类有相同的属性,想在子类中访问父类的特征。 代码演示:

代码语言:javascript
复制
//书
public class Book {
//书名
		String name;
//构造方法
		public Book(){
		super();
		}
	public Book(String name){
		super();
		this.name = name;
	}
 }
代码语言:javascript
复制
//纸质书
public class PaperBook extends Book {
//构造方法
		public PaperBook(){
			super();
		}
		public PaperBook(String name){
			super();
			this.name = name;
		}
//打印书名
		public void printName(){
			System.out.println("this.name->书名 : " + this.name);
			System.out.println("super.name->书名 : " + super.name);
		}
 }
代码语言:javascript
复制
public class BookTest {
	public static void main(String[] args) {
		PaperBook book1 = new PaperBook("零基础学 Java 卷 I");
		book1.printName();
	}
 }
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

通过以上内存结构图发现 this.name 和 super.name 实际上是同一块内存空间,所以它们输出结果是完全一样的。 如果在子类中加一个name属性呢?

代码语言:javascript
复制
//纸质书
public class PaperBook extends Book {
		String name; //在子类中也定义了一个 name 属性
//构造方法
		public PaperBook(){
			super();
		}
		public PaperBook(String name){
			super();
			this.name = name;//这里的 this.name 代表子类的 name
		}
//打印书名
		public void printName(){
		System.out.println("this.name->书名 : " + this.name);
		System.out.println("super.name->书名 : " + super.name);
		}
}
在这里插入图片描述
在这里插入图片描述

父类 Book 的构造方法在执行的时候给 super.name 赋值null,子类 PaperBook 的构造方法在执行的时候给 this.name 赋值“零基础学 Java 卷 I”,由于在子类 PaperBook 中定义了重名的变量 name 导致在当前对象中有两个 name,一个是从父类中继承过来的,一个是自己的,如果此时想访问父类中继承过来的 name 则必须使用 super.name,当直接访问 name 或者 this.name 都表示访问当前对象自己的 name。

今天的分享就到这喽!!!~

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-06-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目录
  • 第一章:继承(Extexnds)
    • 1.1什么是继承?作用?
      • 2.1继承相关特性
        • 3.1方法覆盖(OverRide)
        • 第二章:多态
          • 1.1什么是多态?
            • 2.1基础语法
              • 3.1 instanceof运算符
                • 4.1 super关键字
                • 今天的分享就到这喽!!!~
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档