java基础--笔记9

来源:互联网 发布:spark大数据分析 pdf 编辑:程序博客网 时间:2024/05/17 05:04

多态:可以理解为事物存在的多种体现形态。父类的引用指向子类的对象。
1,多态的体现
     父类的引用指向了自己的子类对象
2,多态的前提
     要使用多态来描述一个对象时,这个对象所属的类一定要继承一个父类,或实现了接口。
     通常还有一个前提:存在覆盖。
3,多态的好处
     多态的出现大大的提高了程序的扩展性。
4,多态的弊端
     一旦父类的引用指向了子类对象时,这时使用父类的引用调用方法时,只能调用父类中的方法,而无法使用子类特有的方法。
5,多态的应用


当我们把父类的引用强转成子类类型时,需要先做判断,如果不做判断,很有可能发生ClassCastException类型转换异常。
由于方法使用的是父类型在接受所有的子类,而在强转时,我们把未知子类型强转成其他的子类了。这时就发生异常。
要避免这个异常的话,在强转之前一定要进行类型的判断。需要使用java中的关键字 instanceof
格式:
if(父类型引用  instanceof  子类型)
{
     里面进行强转;
}

总结:在多态调用中,自始至终都是子类对象在做着类型的转换,真真正正做事的还是子类对象在做事。在把父类型转成子类型时,一定要做判断,否则会发生类型转换异常ClasscastException。

多态中成员的变化:
1,成员变量
          在多态调用中,当使用父类的引用时。
          在编译的时候
               编译器看的引用所属的类中是否存在当前使用的这个变量,如果存在编译通过,否则编译失败。
          在运行时期
               仍然使用引用所属类中的成员变量的值。

2,成员函数
          在多态中,当子父类出现同名的成员方法时,这时通过引用去调用方法的时候,是子类的方法在运行。
          多态调用方法时
          编译时期:编译器会检查引用所属的类是否引用所属的方法,如果有,编译通过。没有,则编译失败。
          运行时期:JVM会到这个引用所指的对象中所属的类中去找对象的方法执行。
          编译看左边,运行看右边。

3,静态方法
          在多态中,方法如果是静态的
          编译时:编译器会检查引用所属的类中是否引用所调用的方法,如果有,编译通过。没有,编译失败。
          运行时:JVM会到这个引用所属的类中去找对应的方法执行
          编译,运行都看左边。

总结:
     在多态中,对于成员变量和静态方法,编译运行都看引用所属的类。
     对于非静态的方法,编译时看引用所属的类中是否有这个方法,而运行时看引用所指的对象中的方法。



Object 类
     object中的构造函数给所有子类进行初始化的。

equals方法
     在Object类中的equals方法其实就是在比较两个对象的内存地址是否相等。
public boolean equals(Object obj)
 {
        return (this == obj);
 }
     在开发中需要根据两个对象中的数据进行比较时,不能直接使用Object中equals方法,原因equals方法比较的是两个对象的内存地址(哈希值)。这时Object中的equals方法不合适当前对象的比较。可以在子类中复写父类的equals方法指定适合自己的比较方式。
复写时,方法签名要一模一样。包括参数列表。
public boolean equals(Object obj)  
     {
          //先对传递进来的obj进行合法验证
          if( obj == null)
          {
               return false;
          }
          //判断this和obj是不是同一个
          if(this == obj)
          {
               return true;
          }
          if(obj instanceof Person)
          {
               Person p = (Person)obj;
               return this.age == p.age;
          }
          return false;

toString
查阅API发现,让所有的子类都要去复写Object中toString方法

在使用输出语句输出数据时,会自动的 调用对象的toString

注意:在以后的开发中,需要我们复写对象中的equals,建立对象自身的比较方式。同时也需要复写对象的toString方法,建立可以描述本类性特点的字符串表现形式。


内部类:
          写在其他类的内部的类。内部类可以存在与外部类的成员位置上,也可以存在与外部类的局部位置上。
    
     当内部类处于外部类的成员位置上时,这个内部类就相当于外部类的成员,那么要访问一个类的成员,这时必须建立这个类的对象,通过对象来访问成员。

     当内部类放在外部类的成员位置上,并且这个内部类没有私有,那么我们可以在外部类以外的其他类中访问这个内部类。
     访问格式是:
          Outer.Inner in = new Outer().new Inner();
     说明:先创建外部类对象,再创建内部类对象。

     当内部类放在外部类的成员位置上时,在外部类的其他方法中可以创建内部类对象,来访问内部类。
     格式:
          Inner in = new Inner();
    
     当内部类在外部类成员位置上时,被私有了,只能通过外部类中其他的方法创建内部类对象来访问内部类。

     当内部类在外部类成员位置上时,被静态修饰,同时没有被私有,这时在外部类以外的其他地方是可以访问这个被静态修饰的内部类的。
     访问格式:
          Outer.Inner in = new Outer.Inner();
    
     当内部类在外部类成员位置上时,被静态修饰,同时没有被私有,在外部类以外的其他地方是可以访问内部类中静态的方法
     格式:
          外部类名.内部类名.方法名();
    


*/
class Outer
{
     //内部类在外部类的成员位置。那么这个类就可以被成员修饰符修饰。
     class Inner
     {
          static final int num = 4;
          void show()  // Outer.Inner.show();
          {
               System.out.println("inner num="+num);
          }
     }
     void method()
     {
          //当内部类放在外部类的成员位置上时,在外部类的其他方法中可以创建内部类对象,来访问内部类。
          Inner in = new Inner();
          in.show();
          System.out.println("Outer method()");
     }
}


class InnerDemo
{
     public static void main(String[] args)
     {
          //访问静态的内部类
//          Outer.Inner in = new Outer.Inner();
//          in.show();
          //访问静态内部类中的静态方法
          //Outer.Inner.show();


          //Outer out = new Outer();
          //out.method();
          Outer.Inner in =  new Outer().new Inner();
          in.show();
     }
}


当把内部类放置在外部类的局部中。
其实就是把内部类放在外部类的方法中。

     当把一个类放置在方法的内部,那么在这个方法的外部的其他地方是不可见。即就是在这个方法的外部是无法创建这个内部类对象,来调用内部类中的方法。
     注意,当内部类在外部类的局部位置时,如果要访问外部类的局部变量,这个变量必须被final修饰。

abstract class Abs
{
     abstract void show();
}


class Outer
{
     Abs in ;//定义在外部类的成员位置上

     void method()
     {
          class Inner extends Abs
          {
               int num = 3;
               void func()
               {
                    System.out.println("num="+num);
               }
               void show()
               {
                    System.out.println("Inner show run");
               }
          }
          in = new Inner(); //把局部内部类对象赋给in引用
          Inner i = (Inner)(in);
          i.func();
     }

     void function()
     {
          in.show();
          //in.func(); // in是Abs类型,只能调用父类中的方法,这个地方无法调用子类特有的方法。
          //Inner i = (Inner).in;  这里错误,由于内部类在外部类的局部啊,在外部类的其他地方,根本得不到内部类的真实类型。

     }

}


class InnerDemo3
{
     public static void main(String[] args)
     {
          Outer out = new Outer();
          out.method();//目的是in变量指向内部类对象
          out.function();
          System.out.println("Hello World!");
     }
}

0 0
原创粉丝点击