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

有时候,不是因为你没有能力,也不是因为你缺少勇气,只是因为你付出的努力还太少,所以,成功便不会走向你。而你所需要做的,就是坚定你的梦想,你的目标,你的未来,然后以不达目的誓不罢休的那股劲,去付出你的努力,成功就会慢慢向你靠近。

导读:本篇文章讲解 JavaSE篇学习之路:(六)【面向对象——中】,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

第一章:继承(Extexnds)

1.1什么是继承?作用?

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

2.1继承相关特性

    ① 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. 方法覆盖只针对实例方法,静态方法无意义。

代码演示:

/**
 * 父类:动物类
 */
class Animal{
    private String name;
    //无参构造方法
    public Animal() {

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

    }
}
/**
 * 猫继承动物类  猫是动物
 */
class Cat extends Animal{
	//无参构造方法
    public Cat(){

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

}
/**
 * 狗继承动物类 狗是动物
 */
class Dog extends Animal{
	//无参构造方法
    public Dog(){

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

/**
 1. 测试类
 */
public class Demo {
    public static void main(String[] args) {
       //创建猫对象
        Cat cat=new Cat();
        //猫吃东西
        cat.eat();
       //创建狗对象
        Dog dog=new Dog();
        //狗吃东西
        dog.eat();
    }
}

第二章:多态

1.1什么是多态?

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

2.1基础语法

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

	向上转型:子--->父 (upcasting)
		又被称为自动类型转换:Animal a = new Cat();

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

代码演示:

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

代码演示:

/**
 * 父类:动物类
 */
class Animal{

    public Animal() {

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

    }
}
/**
 * 猫继承动物类  猫是动物
 */
class Cat extends Animal {
    public Cat() {

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

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

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

}
/**
 * 狗继承动物类 狗是动物
 */
class Dog extends Animal{

    public Dog(){

    }
    //狗类重写父类的eat()方法!
    public void eat(){
        System.out.println("狗吃狗粮!!");
    }
    public void run(){
        System.out.println("狗仔跳墙!1");
    }
}
/**
 * 测试类
 */
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不能省略?
如果父与子类有相同的属性,想在子类中访问父类的特征。
代码演示:

//书
public class Book {
//书名
		String name;
//构造方法
		public Book(){
		super();
		}
	public Book(String name){
		super();
		this.name = name;
	}
 }
//纸质书
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);
		}
 }
public class BookTest {
	public static void main(String[] args) {
		PaperBook book1 = new PaperBook("零基础学 Java 卷 I");
		book1.printName();
	}
 }

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

//纸质书
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。

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

一起学习,快乐编程,欢迎攻城狮们多多交流!!!~

在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/144950.html

(0)

相关推荐

发表回复

登录后才能评论
半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!