多态的好处及应用 权限修饰符 包 引用类型转换 抽象类

项目1 权限修饰符

概述

在Java中提供了四种访问权限,使用不同的访问权限修饰符修饰时,被修饰的内容会有不同的访问权限,

  • public:公共的。
  • protected:受保护的
  • default:默认的
  • private:私有的

不同权限的访问能力

publicprotecteddefault(空的)private
同一类中
同一包中(子类与无关类)
不同包的子类
不同包中的无关类

可见,public具有最大权限。private则是最小权限。

编写代码时,如果没有特殊的考虑,建议这样使用权限:

  • 成员变量使用private ,隐藏细节。
  • 构造方法使用public ,方便创建对象。
  • 成员方法使用public ,方便调用方法。

小贴士:不加权限修饰符,其访问能力与default修饰符相同

示例代码

public class Demo01 {
	private int aa = 1;       // 私有的  
	int bb = 2;               // 默认的
	protected int cc = 3;     // 受保护的
	public int dd = 4;        // 公共的   
 
	public void test1(){  // 本类中访问,都可以
		System.out.println(aa);
		System.out.println(bb);
		System.out.println(cc);
		System.out.println(dd);
	}
}

public class Demo02 extends Demo01 {  // 同包子类
	 public void test(){
		 //System.out.println(aa);  // 不能访问私有的
		 System.out.println(bb);
		 System.out.println(cc);
		 System.out.println(dd);
	 }
}

public class Demo03 extends Demo01{ // 不同包子类
	public void test(){
		//System.out.println(aa);
		//System.out.println(bb);  // 不同包中,default的也不能访问
		System.out.println(cc);
		System.out.println(dd);
	}
}

public class Demo04 {  // 不同包类
	public static void main(String[] args) {
	    Demo01 demo = new Demo01();
	    //System.out.println(demo.aa);
	    //System.out.println(demo.bb);
		//System.out.println(demo.cc); 
	    System.out.println(demo.dd);
	}
}

项目2 包

基本用法

例如:package com.offcn.test 系统自动建立三个文件夹,结构如下:

com

​ offcn

​ test

该文件中所定义的类都在test文件夹下。
示例代码

package com.offcn.finaltest;

JDK中的包

1、java.lang包含一些Java语言的核心类,如String、Math、Integer 、System和Thread,提供常用功能。

2、java.util包含一些实用工具类,如集合、日期等。

3、java.io 包含能提供多种输入/输出功能的类。

4、java.net包含执行与网络相关的操作的类。

5、java.awt包含构成抽象窗口工具集的多个类,这些类用来创建和管理应用程序的图形用户界面(GUI)。

import的多导入

import com.offcn.*;引入该包下所有类。

使用import语句应该注意的几点:

1、import语句定义在package语句后

2、java.lang包是默认被导入的,该包下所有类都可以直接使用。

3、包的导入不是迭代的,也就是当使用com.offcn.*时只会导入该包下的所有类,如果该包下有文件夹a,则a下的所有类不会被导入。

4、同一个包下的类,不需要导入。

项目3多态

泛化

泛化就是抽象化,把具体的事物当作抽象的东西看待(把猫看成动物)。

泛化也叫向上转型,是通往多态的路口。

以用同样的类型处理不同的东西。

注意:只有向上转型,没有向下转型。向下转型叫做强转,这样做很不安全!

 Cat c = (Cat)o; 编译可以通过,但是运行时会出现错误。

泛化指的是引用的泛化,不是对象的泛化,内存中的对象还是原来的对象,只是把引用的类型给改变了

多态的概念
简单来说,多态就是一个事物的多种状态(形态)。

比方说按下 F1 键这个动作,如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档;如果当前在 Word 下弹出的就是Word 帮助;在 Windows 下弹出的就是 Windows 帮助和支持。同一个事件发生在不同的对象上会产生不同的结果。

多态的分类

Java中的多态,可以分为静态多态和动态多态。

静态多态就是指方法的重载。

动态多态是指“动态绑定”。而我们这里所说的多态,大多数是指动态多态。

多态应该具备的条件

  • 继承
  • 子类重写父类的方法
  • 父类引用指向子类对象(泛化)

动态绑定和静态绑定

所谓动态绑定,是指在编译期不能确定引用指向什么类型,而是在运行期选择具体的类型。

double ran = Math.random();
		Animal a;
		if(ran>0.5){
			a = new Cat();
		}else{
			a = new Dog();
		}
		a.eat();

多态中成员方法的访问特点:编译看左边,运行看右边

静态绑定
静态绑定是指编译期就确定调用的是父类中的成员。

动态绑定只是针对类中的普通方法,而对于成员变量静态变量静态方法,采用的是静态绑定。也就是说,对于成员变量,静态变量,和静态方法,绑定的是声明时类型中的成员。

Animal a = new Cat();
a.eat();   //动态绑定
		
System.out.println(a.name);  //静态绑定
a.sayHello();  // 静态绑定

总结:成员变量、静态方法、静态变量、私有变量等采用静态绑定

编译看左边,运行看左边

项目4 引用类型转换

多态的转型分为向上转型与向下转型两种:
向上转型

  • 向上转型:多态本身是子类类型向父类类型向上转换的过程,这个过程是默认的。

当父类引用指向一个子类对象时,便是向上转型。

使用格式:

父类类型  变量名 = new 子类类型();
如:Animal a = new Cat();

向下转型

  • 向下转型:父类类型向子类类型向下转换的过程,这个过程是强制的。

一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制类型转换的格式,便是向下转型。

使用格式:

子类类型 变量名 = (子类类型) 父类变量名;:Cat c =(Cat) a;  

为什么要转型

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误。也就是说,不能调用子类拥有,而父类没有的方法。这也是多态给我们带来的一点"小麻烦"。所以,想要调用子类特有的方法,必须做向下转型。

转换前,我们最好先做一个判断

abstract class Animal {  
    abstract void eat();  
}  

class Cat extends Animal {  
    public void eat() {  
        System.out.println("吃鱼");  
    }  
    public void catchMouse() {  
        System.out.println("抓老鼠");  
    }  
}  

class Dog extends Animal {  
    public void eat() {  
        System.out.println("吃骨头");  
    }  
    public void watchHouse() {  
        System.out.println("看家");  
    }  
}
____________________________________________
public class Test {
    public static void main(String[] args) {
        // 向上转型  
        Animal a = new Cat();  
        a.eat();               // 调用的是 Cat 的 eat

        // 向下转型  
        if (a instanceof Cat){
            Cat c = (Cat)a;       
            c.catchMouse();        // 调用的是 Cat 的 catchMouse
        } else if (a instanceof Dog){
            Dog d = (Dog)a;       
            d.watchHouse();       // 调用的是 Dog 的 watchHouse
        }
    }  
}

项目5 多态的好处及应用

好处

站在更高的层次管理对象的行为
例如:气象专家告诉农民收割庄稼。

多态的应用

1.2多态的应用
案例1: 多态做为形参(接受范围更广的对象,避免方法重载过度使用)
需求:完成喂动物操作。定义一个动物园类,类中有一个喂动物的方法。
动物包括:老虎,猴子,狗,猫。每个动物类中都有一个eat的方法。(喂动物即是调用动物的eat方法)  

示例代码

public class Animal {
	public void eat(){
		System.out.println("吃");
	}
}

public class Tiger extends Animal{
	public void eat(){
		System.out.println("吃肉###");
	}
}

public class Monkey extends Animal{
	public void eat(){
		System.out.println("吃桃...");
	}
}
public class Cat extends Animal{
	public void eat(){
		System.out.println("吃鱼");
	}
}

public class Dog extends Animal{
	public void eat(){
		System.out.println("啃骨头");
	}
}

public class Zoo {
	public void feed(Animal a){
		a.eat();
	}
	
/*	
	public void feed(Tiger tiger){
		tiger.eat();
	}
	
	public void feed(Monkey monkey){
		monkey.eat();
	}
	
	public void feed(Cat cat){
		cat.eat();
	}
	
	public void feed(Dog dog){
		dog.eat();
	}
	
*/
}

public static void main(String[] args) {
		Zoo zoo = new Zoo();
		
		Tiger tiger = new Tiger();
		zoo.feed(tiger);
		
		Monkey monkey = new Monkey();
		zoo.feed(monkey);
		
		Cat cat = new Cat();
		zoo.feed(cat);
		
		Dog dog = new Dog();
		zoo.feed(dog);
}
案例2: 多态做为返回值类型(简单工厂模式)
需求:有一个生产汽车的工厂,有一个生产汽车的方法,根据客户不同的需求,可以生产出不同的汽车。汽车包括:奔驰(benz)、宝马(BMW)、法拉利(ferrari)

示例代码

public class Car {
	public void run(){
		System.out.println("run");
	}
}
public class CarFactory {
	public Car makeCar(String name){
		if("bmw".equals(name)){
			return new BMW();
		}
		if("benz".equals(name)){
			return new Benz();
		}
		if("ferrari".equals(name)){
			return new Ferrari();
		}
		return null;
	}

	/*
	public BMW makeBMW(){
		
		return new BMW();
	}
	
    public Benz makeBenz(){
		
		return new Benz();
	}
    
    public Ferrari makeFerrari(){
		
		return new Ferrari();
	}
	*/
}
public class BMW extends Car{
	public void run(){
		System.out.println("宝马在路上飞驰...");
	}
}
public class Benz extends Car{
   
	 public void run(){
		 System.out.println("奔驰在路上奔驰###");
	 }
}
public class Ferrari extends Car{
	  public void run(){
		  System.out.println("法拉利跑的很快");
	  }
}

项目6 抽象类

抽象方法

abstract关键字修饰的方法,称为抽象方法。

抽象方法的特点:只有方法的声明,没有方法体。

抽象方法的作用:被子类重写,为子类规定了方法的调用格式,具体的操作内容等待子类去完成。

生活中的例子:简历模板

示例代码

public abstract void show();

抽象方法存在的类必须是一个抽象类

抽象类

特点:
1、 抽象类不能被实例化抽象类的唯一用途就是被子类继承。
2、继承抽象类的类,有责任去实现抽象类中的所有抽象方法。如果不实现,那么子类也必须声明为抽象类。

抽象类中可以包含非抽象方法


public abstract class Person {   
	public abstract void eat();   
    
    public void testMethod(){
        //非抽象方法
        System.out.println("抽象类中可以存在非抽象方法");
    }
}

抽象类的其他细节

1、抽象类不能创建对象,那么抽象类中是否有构造方法?

抽象类中一定有构造方法。主要为了初始化抽象类中的属性。通常由子类实现。

public abstract class Vehicle {   // 抽象类 至少包含一个抽象方法的类
	public Vehicle(){
		System.out.println("抽象类的构造方法");
	}
	
	public abstract void run();   // 抽象方法——只有方法声明,没有方法体
}

2、final和abstract是否可以同时修饰一个类?

一定不能同时修饰。因为:抽象类的作用就是被继承,而final修饰的类不能被继承。

总结:
  1. 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。

    理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。

  2. 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。

    理解:子类的构造方法中,有默认的super(),需要访问父类构造方法。

  3. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。

    理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意义。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值