第二部分 面向对象篇
多态 内部类 枚举类型 包与权限
前言
面向对象程序设计的三大支柱是封装、继承和多态。多态意味着父类的变量可以指向子类对象。内部类是Java里面常见的功能,在开发时也都会运用到。
一、多态
1.什么是多态?
一个对象在不改变自身的情况下,可以在不同的场景担任不同的身份,注意既然在不同的场景 担任不同的身份 其表现的行为是有限制的,但是这些身份之间,必须是有继承关系的!
例如:一个先生本人不变
在老婆面前,他的身份是丈夫;
在爸爸面前,他的身份是儿子;
在爷爷面前,他的身份是孙子;
在儿子女儿面前,他的身份是爸爸;
对于同一个父类方法,不同的子类会有不同的实现方式。
对Java当中的对象而言,对象的多态指的是什么?
指的就是对象可以当做其父类数据类型的一个对象来使用,但是不能当做子类数据类型的对象来使用。
(1)定义形式:(必须满足有子父类关系)
父类类型 变量名=new 子类类型();
(2)理解:多态就是同一个行为具有多个不同表现形式或形态的能力。多态就是同一个接口,使用不同的实例而执行不同操作。
如下实例,定义五个动物,每个动物都有自己的功能,有一个饲养员需要喂这五个动物。
public class DuoTaiDemo {
public static void main(String[] args) {
Dog dog = new Dog();
Cat cat = new Cat();
Panda panda = new Panda();
Pig pig = new Pig();
Breeder breeder = new Breeder();
breeder.feed(dog);
breeder.feed(cat);
breeder.feed(panda);
breeder.feed(pig);
}
}
class Breeder {
//向上转型 :儿子装老爹 儿子所能表现出来的行为 只能是老爹的行为 所谈论的数据 也只能是老爹的数据
//向上转型 并不改变对象自身原本的数据类型
//Animal animal = new Dog();
//Animal animal = new Cat();
//Animal animal = new Panda();
//Animal animal = new Pig();
//Object obj = new Dog();
//Object是所有类的父类 如果某一个类没有指明父类的话 其父类默认是Object
public void feed(Animal animal) {
System.out.println("饲养员喂养一个动物~");
animal.eat();
/*
error:(只能获取父类里面的方法,子类自身的方法无法获取)
animal.kanmen();
animal.zhuolaoshu();
animal.maimeng();
animal.gongbaicai();
*/
}
/*
public void feed(Dog dog) {
System.out.println("饲养员开始喂养狗");
dog.eat();
dog.kanmen();
}
public void feed(Cat cat) {
System.out.println("饲养员开始喂养猫");
cat.eat();
cat.zhuolaoshu();
}
public void feed(Panda panda) {
System.out.println("饲养员开始喂熊猫");
panda.eat();
panda.maimeng();
}
public void feed(Pig pig) {
System.out.println("饲养员开始喂猪");
pig.eat();
pig.gongbaicai();
}
*/
}
abstract class Animal extends Object {
public abstract void eat();
}
class Pig extends Animal{
public void eat() {
System.out.println("猪 吃剩饭");
}
public void gongbaicai() {
System.out.println("猪 可以睡觉");
}
}
class Dog extends Animal{
public void eat() {
System.out.println("狗 吃狗粮");
}
public void kanmen() {
System.out.println("狗 可以看门");
}
}
class Cat extends Animal{
public void eat() {
System.out.println("猫 吃猫粮");
}
public void zhuolaoshu() {
System.out.println("猫 可以捉老鼠");
}
}
class Panda extends Animal{
public void eat() {
System.out.println("熊猫 吃竹子");
}
public void maimeng() {
System.out.println("熊猫 可以卖萌");
}
}
从上述代码可以看出:
多态的好处:提高了程序的扩展性 降低程序的冗余;
多态的弊端:通过父类的引用操作对象时,只能使用父类中已有的方法,或者被子类重写的方法,不能调用子类自身特有的行为。
2.多态的转型
多态的转型分为向上转型和向下转型两种,多态本身就是向上转型过的过程。而向下转型是一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类引用类型转为子类引用各类型。(注意这里如果不判断数据类型,会发ClassCastException异常)
什么时候用到向上转型?
当不需要面对子类类型时,通过提高扩展性,或者使用父类的功能就能完成相应的操作,这时就使用向上转型。
什么时候用到向下转型?
当要使用类的特有功能时,就需要向下转型(强制转换 将大类型转为小类型),在转换的时候,就得需要先判断数据类型,否则会发生ClassCastException 类型转换异常。
如下:
Animal a = new Dog();
Cat cat = (Cat) a; //Error a本身的对象Dog类型 Dog类型不能转为Cat类型
Animal a = new Animal();
Dog dog = (Dog) a; //Error a本身的对象Animal类型 Animal不能转为Dog类型
//此处调用调用的是具体某一个类的特有行为
//animal.gongbaicai();
//ClassCastException
if (animal instanceof Pig) {
Pig pig = (Pig)animal;
pig.gongbaicai();
}
就例如:D extends C extends B extends A
对于C c而言,c可以向上转型为B b或A a,那么a b向下转型时 只能强制到C这个数据类型,C不能穿D的衣服 同样C也不能向下转型为D。
instanceof关键字
作用:用来判断某个对象是否属于某种数据类型。(注意: 返回类型为布尔类型)
3.多态中成员的一些特点
(1)多态成员变量:编译运行看左边
Fu fu=new Zi();
System.out.println(f.num);//fu是Fu中的值,只能取到父中的值
(2)多态成员方法:编译看左边,运行看右边
fu.show();//fu的门面类型是Fu,但实际类型是Zi,所以调用的是重写后的方法。
public class DuoTaiDemo {
public static void main(String[] args) {
Fu fu = new Zi();
//多态成员变量:编译运行看左边
//当打印成员变量时 始终打印的是父类的成员变量
//与子类的成员变量无关
System.out.println(fu.num);
//多态成员方法:编译看左边,运行看右边
//当调用成员函数时 使用的是父类的成员函数 或者是子类重写的父类函数
fu.show();
}
}
class Fu {
int num = 5;
public void show() {
System.out.println("Fu show...");
}
}
class Zi extends Fu{
int num = 10;
public void show() {
System.out.println("Zi show....");
}
}
4.多态所暴露出的接口的思想
本身接口的出现就是扩展了类的功能,但是接口其实就是暴露出来的规则,接口的出现就降低了耦合性(耦合性 指的就是事物与事物之间的关联性)
如下实例,鼠标,键盘,电脑之间的连接
public class DuoTaiDemo {
public static void main(String[] args) {
Mouse m1 = new Mouse("雷蛇");
Mouse m2 = new Mouse("Logi");
KeyBoard k1 = new KeyBoard("樱花");
KeyBoard k2 = new KeyBoard("联想");
Computer comp = new Computer();
comp.getUSB_AConnection(m1);
comp.getUSB_BConnection(k2);
comp.getUSB_AConnection(m2);
comp.getUSB_BConnection(k1);
}
}
class Computer {
USB usb_A;
USB usb_B;
//USB usb = new Mouse();
//USB usb = new KeyBord();
public void getUSB_AConnection(USB usb) {
usb_A = usb;
usb_A.getConnection();
}
public void getUSB_BConnection(USB usb) {
usb_B = usb;
usb_B.getConnection();
}
}
interface USB {
public void getConnection();
}
class Mouse implements USB {
String name;
public Mouse(String name) {
this.name = name;
}
public void getConnection(){
System.out.println(name + "的鼠标获取链接,开始使用");
}
}
class KeyBoard implements USB {
String name;
public KeyBoard(String name) {
this.name = name;
}
public void getConnection(){
System.out.println(name + "的键盘获取链接,开始使用");
}
}
二、内部类
1.什么是内部类?
将类写在其他类的内部,可以写在其他的成员位置和其他类的局部位置。
什么时候使用内部类?
在描述事物的时候,若一个事物内部还包括其他可能包含的事物,比如在描述汽车时,汽车内部还包含发动机这个事物 这时发动机就可以用内部类描述。即就是内部事物必须寄宿在外部事物里面的。
2.内部类是外部类的非静态非私有成员
public class InnerClassDemo {
public static void main(String[] args) {
//同级别目录下找不到Inner这个类 所以报错
// Inner in = new Inner();
//需要包含Outter.Inner的封闭实例
// Outter.Inner in = new Outter.Inner();
Outter outter = new Outter();
Outter.Inner in = outter.new Inner();
System.out.println(in.num);
in.show();
}
}
class Outter {
//外部类成员变量
int num = 5;
//外部类成员函数
public void show() {
System.out.println(num);
}
//外部类成员内部类
class Inner {
//内部类成员变量
int num = 10;
//内部类成员函数
public void show() {
System.out.println(num);
//访问外部类的成员变脸
System.out.println(Outter.this.num);
//访问外部类的成员函数
Outter.this.show();
}
}
}
3.内部类是外部类的静态非私有成员
public class InnerClassDemo {
public static void main(String[] args) {
Outter.Inner inner = new Outter.Inner();
inner.show();
System.out.println(Outter.Inner.lala);
System.out.println(Outter.Inner.haha);
}
}
class Outter {
//外部类成员变量
int num = 5;
//外部类成员函数
public void show() {
System.out.println(num);
}
public static int xixi = 20;
//外部类的静态内部类
static class Inner {
//在内部类中 定义一个静态常量 是没有问题的 因为常量最终被数字替代
static final int haha = 20;
//在内部类中 定义一个静态变量/静态函数 是有问题的
//静态的内容是随着类的加载而存在 加载到静态方法区 它们是优先于对象存在 对象又优先于成员变量和成员函数的存在
//如何解决 如果一个成员内部类中 包含了静态成员 那么这个内部类就必须是静态的
static int lala = 100;
//内部类成员变量
int num = 10;
//内部类成员函数
public void show() {
System.out.println(haha);
System.out.println(lala);
System.out.println(num);
//访问外部类的成员变量
// System.out.println(Outter.this.num);
//访问外部类的成员函数
// Outter.this.show();
}
}
}
提示:在函数中能否再去创建一个类呢?可以,不常用(局部内部类)
三、枚举类型
1.什么是枚举类型(enum)
枚举enum是一种特殊类class:
class是将属性和行为进行封装的数据类型;
enum只是将有限集的属性进行封装的数据类型。
如下实例,我们如果使用类来存储周一到周日的话:
class Day {
public static final int Monday = 1;
public static final int Tuesday = 2;
public static final int Wednesday = 3;
public static final int Thursday = 4;
public static final int Friday = 5;
public static final int Saturday = 6;
public static final int Sunday = 1;
}
//通过类来调用定义的
Day.Monday//访问的是1
Day.Thursday//访问的是4
//注意这里会出现重复的定义,一个数可以用来表示两个事物,在后面的调用时会出现问题,这也称为数值型的枚举(枚举的意思就是把事物一个一个列举出来)
//所以可以直接枚举类
enum Day {
Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
}
Day.Monday//访问的是Monday,Monday本身就是常量
实例测试:
public class EnumDemo {
public static void main(String[] args) {
Day today = Day.Monday;
Day tomory = Day.Tuesday;
System.out.println(today);
System.out.println(tomory);
System.out.println(today == tomory);
//System.out.println(today + tomory); 报错,不是数值不能相加
}
}
enum Day {
Monday,Tuesday,Wednesday,Thursday,Friday,
Saturday,Sunday
}
结果:

四、包与权限
1.包
包,其实就是指文件夹,例如:com.heng.haha 其实就是说在com这个文件夹下有一个heng文件夹下有一个haha文件夹。
com
-heng
-haha
DemoA.java
DemoB.java


包的存在,其实也就是为了将代码进行分类管理。
到了后期学习中,一个完整的Java项目中,它会包含好多个类,会导致有很多代码,代码和字节码在一起,不方便维护。所以在后期代码基本是可以分为好几种类:
实体类:主要用于描述事物
工具类:主要为程序提供功能工具
主类:主要用于运行程序的类
数据库类:主要用于操作数据库
…
2.权限
public protected default(默认,可写可不写) private
同一个类中 √ √ √ √
同包别的类 √ √ √
同包子类中 √ √ √
不同包子类中 √ √
不同包别的类 √
本文深入探讨Java的面向对象特性,包括多态的概念、转型及其优缺点,内部类的使用场景及分类,以及枚举类型的特性。通过实例展示了如何利用多态提高程序扩展性和降低冗余,内部类如何描述内部事物,并介绍了枚举作为特殊类在封装有限集合属性时的应用。同时,简述了包和权限在代码组织和访问控制上的作用。
3685

被折叠的 条评论
为什么被折叠?



