黑马程序员——Java基础---继承、抽象、接口(二)

本文主要探讨了Java中的多态性概念,包括多态概述和成员特点,如成员变量和非静态成员函数的使用。同时,介绍了内部类的详细内容,包括内部类的定义位置,如成员位置和局部位置,以及匿名内部类的应用示例。

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


一、多态

1.多态概述 

    定义:某一类事物的多种存在形态。
    

    例:动物中猫,狗。
    猫这个对象对应的类型是猫类型:猫 x = new 猫();
    同时猫也是动物中的一种,也可以把猫称为动物:动物 y = new 猫();
    动物是猫和狗具体事物中抽取出来的父类型。父类型引用指向了子类对象。

    多态性简单说就是一个对象对应着不同类型。

    体现:
    父类或者接口的引用指向或者接收自己的子类对象。

    作用:
    多态的存在提高了程序的扩展性和后期可维护性。

    
    前提:
    1. 需要存在继承或者实现关系。
    2. 需要有覆盖操作。

    
    好处:
    提高了代码的扩展性,前期定义的代码可以使用后期的内容。
    弊端:
    前期定义的内容不能使用(调用)后期子类的特有内容。

示例:
/**
 * 需求:演示多态
 * 思路:程序中注释部分
 * @author jinlong
 * */
package com.blog.part2.继承;

//定义抽象类Animal
abstract class Animal
{
    abstract void eat();
}
//定义抽象类的子类Dog
class Dog extends Animal
{
	//重写了抽象类eat方法
    void eat()
    {
         System.out.println("啃骨头");
    }
    //他还有自己的特有方法
    void lookHome(){
         System.out.println("看家");
    }
}
//类似上边Dog类,再定义一个Cat类
class Cat extends Animal
{
    void eat()
    {
         System.out.println("吃鱼");
    }
    //同样有自己的特有方法
    void catchMouse()
    {
         System.out.println("抓老鼠");
    }
}
//与cat、Dog类似
class Pig extends Animal
{
    void eat()
    {
         System.out.println("饲料");
    }
    void gongdi()
    {
         System.out.println("拱地");
    }
}

class DuoTaiDemo
{
    public static void main(String[] args)
    {
        //自动类型提升,猫对象提升到了动物类型。但是特有功能无法访问,作用就是限制对特有功能的访问。
        //专业讲:向上转型,将子类型隐藏。就不能使用子类的特有方法了。
        Animal a = new Cat();
        //但是还可以使用覆盖自父类的方法eat
        a.eat();
        //a.catchMouse();//报错,

        //如果还想用具体动物猫的特有功能。
        //你可以将该对象进行向下转型。
        Cat c = (Cat)a; //向下转型的目的是为了能够使用子类中的特有方法。
        c.eat();
        c.catchMouse();

        //注意:对于转型,自始至终都是子类对象在做类型的变化。
        //Animal a = new Dog();
        //Cat c = (Cat)a;//但是类型不能随意转换,否则可能会报出ClassCastException的异常
        /*
         为了避免这种错误,可以使用instanceof判断
        if(a instanceof Cat)
           { 
             Cat c = (Cat )a;
            c.catchMouse();
           } 
         */
   }
   //定义方法调用eat,传入参数类型为这个抽象类
    public static void method(Animal a)
    {
         a.eat();
    }
}
运行结果:


2.多态时成员的特点 

1.成员变量
               编译时:参考引用型变量所属的类中是否有调用的成员变量。有,编译通过,没有,编译失败。
      运行时:参考引用型变量所属的类中是否有调用的成员变量,并运行该所属类中的成员变量。
      简单说:编译和运行都参考等号的左边。
       
package com.blog.part2.继承;
class Fu
{
    int num = 3;
}

class Zi extends Fu
{
    int num = 4;
    
}

class DuoTaiDemo1
{
    public static void main(String[] args)
    {    
    	//编译和运行都是看等号左边变量所属类是否有成员变量
         Zi f1 = new Zi();
         System.out.println(f1.num);
         
         Fu f2 = new Zi();
         System.out.println(f2.num);
    }
}
运行结果:

2.成员函数(非静态)
       编译时:参考引用型变量所属的类中是否有调用的函数。有,编译通过。没有,编译失败。
       运行时:参考的是对象所属的类中是否有调用的函数。
       简单说:编译看左边,运行看右边。


示例:
package com.blog.part2.继承;
class Fu
{
    void show()
    {
    	System.out.println("Fu show");
    }
}

class Zi extends Fu
{
    void show()
    {
    	System.out.println("Zi show");
    }
    
}

class DuoTaiDemo1
{
    public static void main(String[] args)
    {    
    	//编译看左边,运行看右边
         Zi f1 = new Zi();
         f1.show();
         
         Fu f2 = new Zi();
        f2.show();
    }
}
运行结果:

3.成员函数(非静态)
        编译时:参考的是对象所属的类中是否有调用的函数。
   运行时:参考的是对象所属的类中是否有调用的函数。
   简单说:编译和运行看左边。


package com.blog.part2.继承;
class Fu
{
    static void show()
    {
    	System.out.println("Fu show");
    }
}

class Zi extends Fu
{
    static void show()
    {
    	System.out.println("Zi show");
    }
    
}

class DuoTaiDemo1
{
    public static void main(String[] args)
    {    
    	//静态方法无序实例化就可以直接用类名调用,这里为了和上边的示例对比
    	//编译运行都看左边
         Zi f1 = new Zi();
         f1.show();  //其实就是Zi.show()      
         Fu f2 = new Zi();
        f2.show();//其实就是Fu.show()
        
    }
}
运行结果:


二、内部类

1.概述

    定义:
    将一个类定义在另一个类的里面,里面那个类就称为内部类(内置类,嵌套类)。

    访问特点:
    内部类可以直接访问外部类中的成员,包括私有成员。
    而外部类要访问内部类中的成员必须要建立内部类的对象。

    内部类设计:在设计事物时,发现这个事物中还有事物,并且这个事物还在访问被描述事物的内容,这是时就定义内部类。

2.内部类的位置

1.内部类在成员位置
      内部类定义在成员位置上可以被private、static成员修饰符修饰。
   被static修饰的内部类只能访问外部类中的静态成员,这就出现了访问局限

   访问格式:当内部类定义在外部类的成员位置上,且非私有,可以在外部其他类中直接建立内部类对象。格式如下:

          Outer.Inner in=new Outer().new Inner();

示例:
/**
 * 需求:内部类展示
 * @author jinlong
 * */
package com.blog.part2.继承;

class Outer
{
	//外部类静态成员
    private static int num = 3;
    private int sum=0;
    //内部类
    static class Inner
    {
    	//静态内部类的非静态方法
          void show()
          {
                  System.out.println("static show run..." + num);
                  //静态内部类只能访问外部类的静态成员,访问非静态会报错
                 // System.out.println("show run..." + sum);
          }
      	//静态内部类的静态方法
          static void show1()
          {
        	  System.out.println("show run..." + num);
          }
    }
}

class InnerClassDemo
{
    public static void main(String[] args)
    {  
    	  //访问静态成员不需要创建对象
    	Outer.Inner.show1();
          //如果内部类是静态的,相当于一个外部类
         Outer.Inner in = new Outer.Inner();
         in.show();
      
         
    }
}
  注意:当内部类中定义了静态成员,该类也必须是静态的。当外部类的静态方法访问内部类时,该类也必须是静态的。
 

         
2.内部类在局部
    内部类定义在局部位置上,也可以直接访问外部类中的成员。
    同时可以访问所在局部中的局部变量,但必须是被final修饰的。
/**
 * 需求:内部类定义在局部
 * @author jinlong
 * */
package com.blog.part2.继承;
class Outer
{
    int num = 3;
    //如果要被inner类中函数使用,这里参数必须被final修饰
    void method(final int y)
    {
          final int x = 9;
          //局部定义的内部类,在method方法中
          class Inner
          {
                void show()
                {
                     System.out.println("show..." + x + "," + y);
                }
          }
          //创建内部类对象。
         Inner in = new Inner();
         in.show();
    }
}

class InnerClassDemo
{
    public static void main(String[] args)
    {
          new Outer().method(4);
    }
}

3.匿名内部类

1.概述

    定义:
    就是内部类的简化写法。

    前提:
    内部类可以继承或实现一个外部类或者接口。

    格式:
    new 外部类名或者接口名(){覆盖类或者接口中的代码,(也可以自定义内容。)}


    简单理解:
    就是建立一个带内容的外部类或者接口的子类匿名对象。


    什么时候使用匿名内部类呢?
    通常使用方法是接口类型参数,并且该接口中的方法不超过三个,可以将匿名内部类作为参数传递。

    好处:
    增强阅读性。


2.一些常见示例

示例一:

/**
 * 需求:同过匿名类使用抽象类中的方法。
 * @author jinlong
 * */

package com.blog.part2.继承;
//定义一个抽象类
abstract class Demo
{
    abstract void show();
}

class Outer
{
    int num = 4;

    void method()
    {
    	//
          new Demo(){//匿名内部类,在局部
                void show()
                {
                	//重写了抽象类的函数
                     System.out.println("show......" + num);
               }
          }.show();
    }
}

class InnerClassDemo
{
    public static void main(String[] args)
    {
    	//一次性调用,可以用匿名类
          new Outer().method();
    }
}

实例二:

package com.blog.part2.继承;
/**
 * 需求:同过匿名类使用接口中的方法
 * @author jinlong
 * */
//定义一个接口
interface Inter
{
    void show1();
    void show2();
}

class Outer
{
    public void method()
    {
    	//主以这里其实是new Inter(){...};结构最后的分号不要丢
    	//最后用inter类型的变量指向他
         Inter in = new Inter()
         {
        	   //覆盖接口的方法
                public void show1()
                {
                       System.out.println("...show1...." );
                }
                public void show2()
                {
                       System.out.println("...show2...." );
                }
         };
         //调用复写的方法。
         in.show1();
         in.show2();
    }
}

class InnerClassDemo
{
    public static void main(String[] args)
    {
          new Outer().method();
    }
}

示例三:

/**
 * 
   通常的使用场景之一:
   当函数参数是接口类型时,而且接口中的方法不超过三个。
   可以用匿名内部类作为实际参数进行传递。
   
   思考:实际上类似于前边多态的例子,只不过这里不创建抽象类的真正意义上的子类
             而通过new 抽象类()
                                {
                                     重写抽象类方法func1...func2...
                                };
             这种形式,作为一种临时性的使用。                   
 
 * @author jinlong
 * */
package com.blog.part2.继承;
interface Inter
{
    void show1();
    void show2();
}

class InnerClassDemo
{
   public static void main(String[] args)
   {
	   //注意这里的结构,为show(Inter in),但是参数的传入值有点胖
	   //结构为 new Inter(){..show1.....show2...}
          show(new Inter()
          {
                public void show1()
                {
                     System.out.println("...show1..." );
                }
                public void show2(){
                     System.out.println("...show2..." );
                }
         });
    }
   
    public static void show(Inter in)
    {
         in.show1();
         in.show2();
    }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值