精华内容
下载资源
问答
  • JAVA加载机制JAVA类加载器 加载层次关系 加载机制的特性JAVA加载机制JAVA类加载器java类加载器负责把一个一个编译好的class文件装入内存中,并为其创建对应的java.lang.Class对象。java中有如下几种类加载器...

    JAVA类加载机制

    JAVA类加载器

    java类加载器负责把一个一个编译好的class文件装入内存中,并为其创建对应的java.lang.Class对象。加载器是java动态特性的核心,提供了多态特性以及服务器热部署的能力。

    java中有如下几种类加载器:

    BootstrapClassLoader

    • implemented by native language (C/C++/汇编。区别于JRE版本。其他loader都是java)
    • load the core classes of JDK

    ExtesionClassLoader

    • loader the class from jre/lib/ext

    ApplicationClassLoader

    • load user-define classes
    • ClassLoader.getSystemClassLoader() == application class loader

    other class loaders

    • SecureClassLoader
    • URLClassLoader (2/3的父类)
    • user-define ClassLoader

    这里写图片描述

    类加载层次关系:

    !!非继承关系.

    这里写图片描述
    (图片摘自马士兵老师教程)

    每次ClassLoader加载类时,都会向上层询问是否已经加载该类,若已加载,则不会再加载。一方面节省资源,另一方面出于安全的考虑,保护核心class不会被覆盖。

    按需加载,用到的时候再加载(new / class.forName() / classLoader.load())

    URLClassLoader是ApplicationClassLoader、ExtesionClassLoader的父类,主要负责显式的指明类加载的path。

    这里写图片描述

    类加载机制的特性:

    1. 全盘负责
    2. 父类委托
    3. 缓存机制

    全盘负责是指,当一个类加载器负责加载某个Class时,还要负责加载该Class的引用和依赖(除非有显式声明指定让其他加载器来加载)。

    父类委托是指,类加载器再载入类的时候,会优先让parent加载器(关系中的)来加载,当该parent加载器无法载入指定类时,才会尝试从自己的类路径加载该类。[递归定义*]

    缓存机制是指,jvm会保证所有加载过的Class都会被缓存下来,当程序要使用某个Class时,会优先在缓存里搜索该类(如何辨别?),若搜索不到则载入该类class文件,并将其转换成Class对象。[这也导致了,我们修改程序后,必须重启应用程序(JVM)才能生效]

    JVM如何辨别是不是同一个类:
    符合类标识规则(类名,包名,加载器名)的类才会被认为是同一个类。

    类加载流程:

    这里写图片描述

    其中:
    第5.6步允许用户重写ClassLoader中的findClass()方法来实现自己的载入策略,甚至可以重写loadClass()方法来具体实现整个载入过程。


    tips:

    • java -verbose:class 可以观察类的具体加载过程

    • static 语句块在加载后只执行一次

    • dynamic语句块每次new新的对象都会执行{ }
      等同于无条件 ‘在所有构造语句之前的执行的’ 语句。

    源码:
    https://github.com/timo1160139211/java-tranning/tree/master/src/site/gaoyisheng/test/classloader


    在线画图工具:
    https://go.gliffy.com/go/html5/launch

    当然更推荐Dia画图。

    展开全文
  • Java加载,内部,及多态的实现 一,java加载的过程: 1.加载的过程: 加载的机制: ...类加载器: Boostrap ClassLoader 启动类加载器 文件名地址 jre/lib/*.jar -> rt.jar Ext Cl...

    Java类加载,内部类,及多态的实现

    一,java类加载的过程:
    1.类加载的过程:
    类加载的机制:
    jvm把class文件加载到内存,并对数据进行校验,解析和初始化,最终形成居民可以直接使用的java类型的过程。

    (1)装载阶段:
    类加载器: Boostrap ClassLoader 启动类加载器 文件名地址 jre/lib/*.jar -> rt.jar
    Ext ClassLoader 扩展类加载器 文件名地址jre/lib/ext/jar
    AppClassLoader 应用类加载器 文件名地址 CLASSPATH
    **

    以上加载器依次遵循继承关系

    类加载器的代理模式:双亲委派模型(双亲委托机制)
    双亲委派:

    例从应用类加载器开始 找之前是否加载过例,如果加载过,将加载产物Class对象返回。如果没有加载过,啧一次在其父类找知道Boostrap。在终极类加载器C/C++时返回为null,从Boostrap开始尝试向子类依次尝试加载,加载产物Class对象返回,直至最后路径找不到加载失败。

    双亲委派模型的优点:1)安全
    2)避免类的重复加载

    如果一个类他的类加载器是启动类加载器,此时getClassLoader();返回值为null;因为类加载器的最终类加载器是c/c++。

    (2)链接阶段:

    验证: 文件格式验证,主次版本号
    准备:准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将在方法区中进行分配。coount在方法区中分配4字节内存,并赋类 型默认值0.
    解析:将符号引用改为直接引用过程

    (**3)初始化阶段:**对类的静态变量,静态代码块实质性初始化操作。
    在Java中对类变量进行初始值设定有两种方式:
    1)声明类变量是指定初始值。
    2)使用静态代码块为类变量指定初始值。

    Java内部类

    Java内部类分为:实例内部类,静态内部类,匿名内部类,局部内部类。

    1.实例内部类:

    class  Outer{
    class  inner{}
    }

    编译上述代码会产生两个文件:Outer.class和Outer$inner.class
    2.静态内部类:
    静态的含义是该内部类可以像其他静态成员一样,没有外部类对象时,也能够访问它。静态嵌套类不能访问外部类的成员和方法。

    class  Outer{
    static class Inner{}
    }
    class Test{
    public static void main(String[] args){Outer.Inner  n =new  Outer.Inner();
    
    }
    }

    3.匿名内部类:
    匿名内部类就是没有名字的内部类。什么情况下需要使用匿名内部类?如果满足下面的一些条件,使用匿名内部类是比较合适的:

    ·只用到类的一个实例。

    ·类在定义后马上用到。

    ·类非常小(SUN推荐是在4行代码以下)

    ·给类命名并不会导致你的代码更容易被理解。

    在使用匿名内部类时,要记住以下几个原则:

    ·匿名内部类不能有构造方法。

    ·匿名内部类不能定义任何静态成员、方法和类。

    ·匿名内部类不能是public,protected,private,static。

    ·只能创建匿名内部类的一个实例。

    ·一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。

    ·因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。

    4.局部内部类:
    向上造型:基类(基接口)引用派生类的对象(实现该接口的类对象)

    他们之间的访问修饰符的区别:

    1)修饰成员:

    public 默认 protect private ->修饰成员
    protect 《—》默认 包访问权限
    继承:子类和父类定义在不同的包下,子类可以访问父类有protect。
    2)修饰类:
    2.1)修饰内部变量:public 默认 两种
    2.2)修饰外部类:默认 public private protectde 四种

    多态的实现

    多态的实现原理:在这里插入图片描述

    发生多态的三个条件:
    1)继承
    2 )方法的重写
    3 )父类引用引用派生类对象(向上造型)

    多态分为静多态和动多态

    动多态(运行期多态/动态绑定)
    运行期
    静多态 :
    静多态也称编译时的多态,就是我们所说的方法重载。相同的函数名,根据形参类型个数的不同调用不同的方 法。在编译期间就已经确定要调用的方法。
    发生动态绑定的条件:
    (1)继承 (2)重写 (3)向上改造

    重写和重载的区别:
    Java的方法重载,就是在类中可以创建多个方法,它们具有相同的名字,但可具有不同的参数列表、返回值类型。调用方法时通过传递的参数类型来决定具体使用哪个方法,这就是多态性。

    Java的方法重写,是父类与子类之间的多态性,子类可继承父类中的方法,但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。重写的参数列表和返回类型均不可修改。
    总结:
    1 首先重载和重写他们所处的作用域范围不同。重载是在同一个类中进行方法的定义,重写是在父子类中进 行方法的定义。
    2 其次,他们的定义方式也不同。重载是方法名相同,参数列表不同。而重写是方法名相同参数列表也相同。

    展开全文
  • 越努力越幸运!...多态的使用大家应该都比较了解,但是多态的实现原理就有点抽象了,查了很多很多资料,连续几天断断续续的看,有时候看着看着就走神了。毕竟太抽象,哈哈~ 不过依然硬着头皮看下...

    越努力越幸运!

     0.前言

    转载请标明出处:http://blog.csdn.net/seu_calvin/article/details/52191321

    多态在Java技术里有很重要的地位,在面试中也会经常被问到。

    多态的使用大家应该都比较了解,但是多态的实现原理就有点抽象了,查了很多很多资料,连续几天断断续续的看,有时候看着看着就走神了。毕竟太抽象,哈哈~

    不过依然硬着头皮看下来了(也不知道看了多少遍),并且将很多资料里关于多态的知识进行了整理(添添加加删删减减了很久,也把重点根据自己的理解用红字标出),便有了这篇文章。通过这篇文章相信可以帮助你更加深刻的理解多态。

    1.Java多态概述

    Java的方法重载,就是在类中可以创建多个方法,它们具有相同的名字,但可具有不同的参数列表、返回值类型。调用方法时通过传递的参数类型来决定具体使用哪个方法,这就是多态性。

    Java的方法重写,是父类与子类之间的多态性,子类可继承父类中的方法,但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。重写的参数列表和返回类型均不可修改。

    2.方法重写后的动态绑定

    多态允许具体访问时实现方法的动态绑定。Java对于动态绑定的实现主要依赖于方法表,通过继承和接口的多态实现有所不同。

    继承:在执行某个方法时,在方法区中找到该类的方法表,再确认该方法在方法表中的偏移量,找到该方法后如果被重写则直接调用,否则认为没有重写父类该方法,这时会按照继承关系搜索父类的方法表中该偏移量对应的方法。 

    接口:Java 允许一个类实现多个接口,从某种意义上来说相当于多继承,这样同一个接口的的方法在不同类方法表中的位置就可能不一样了。所以不能通过偏移量的方法,而是通过搜索完整的方法表。

    3.JVM的结构(拓展知识,不了解可以看看)

    从上图可以看出,当程序运行需要某个类时,类加载器会将相应的class文件载入到JVM中,并在方法区建立该类的类型信息(包括方法代码,类变量、成员变量、以及本博文要重点讨论的方法表)。 
    注意,这个方法区中的类型信息跟在堆中存放的class对象是不同的。在方法区中,这个class的类型信息只有唯一的实例(所以方法区是各个线程共享的内存区域),而在堆中可以有多个该class对象。可以通过堆中的class对象访问到方法区中类型信息。就像在java反射机制那样,通过class对象可以访问到该类的所有信息一样。

    【重点】 

    方法表是实现动态调用的核心。为了优化对象调用方法的速度,方法区的类型信息会增加一个指针,该指针指向记录该类方法的方法表,方法表中的每一个项都是对应方法的指针。这些方法中包括从父类继承的所有方法以及自身重写(override)的方法。

    4.Java 的方法调用方式(拓展知识,可以不看)

    Java 的方法调用有两类,动态方法调用与静态方法调用。

    静态方法调用是指对于类的静态方法的调用方式,是静态绑定的;而动态方法调用需要有方法调用所作用的对象,是动态绑定的。

    类调用 (invokestatic) 是在编译时就已经确定好具体调用方法的情况。

    实例调用 (invokevirtual)则是在调用的时候才确定具体的调用方法,这就是动态绑定,也是多态要解决的核心问题。

    JVM 的方法调用指令有四个,分别是 invokestatic,invokespecial,invokesvirtual 和 invokeinterface。前两个是静态绑定,后两个是动态绑定的。本文也可以说是对于JVM后两种调用实现的考察。


    5.方法表与方法调用


    如有类定义 Person, Girl, Boy


    class Person { 
     public String toString(){ 
        return "I'm a person."; 
         } 
     public void eat(){} 
     public void speak(){} 
        
     } 
     
     class Boy extends Person{ 
     public String toString(){ 
        return "I'm a boy"; 
         } 
     public void speak(){} 
     public void fight(){} 
     } 
     
     class Girl extends Person{ 
     public String toString(){ 
        return "I'm a girl"; 
         } 
     public void speak(){} 
     public void sing(){} 
     }
          当这三个类被载入到 Java 虚拟机之后,方法区中就包含了各自的类的信息。Girl 和 Boy 在方法区中的方法表可表示如下:

    可以看到,Girl 和 Boy 的方法表包含继承自 Object 的方法,继承自直接父类 Person 的方法及各自新定义的方法。注意方法表条目指向的具体的方法地址,如 Girl 继承自 Object 的方法中,只有 toString() 指向自己的实现(Girl 的方法代码),其余皆指向 Object 的方法代码;其继承自于 Person 的方法 eat() 和 speak() 分别指向 Person 的方法实现和本身的实现。

    如果子类改写了父类的方法,那么子类和父类的那些同名的方法共享一个方法表项。

    因此,方法表的偏移量总是固定的。所有继承父类的子类的方法表中,其父类所定义的方法的偏移量也总是一个定值。
    Person 或 Object中的任意一个方法,在它们的方法表和其子类 Girl 和 Boy 的方法表中的位置 (index) 是一样的。这样 JVM 在调用实例方法其实只需要指定调用方法表中的第几个方法即可。

    如调用如下:

     class Party{ 
     void happyHour(){ 
     Person girl = new Girl(); 
     girl.speak(); } 
     }
    当编译 Party 类的时候,生成 girl.speak()的方法调用假设为:

    Invokevirtual #12

    设该调用代码对应着 girl.speak(); #12 是 Party 类的常量池的索引。JVM 执行该调用指令的过程如下所示:


    (1)在常量池(这里有个错误,上图为ClassReference常量池而非Party的常量池)中找到方法调用的符号引用 。
    (2)查看Person的方法表,得到speak方法在该方法表的偏移量(假设为15),这样就得到该方法的直接引用。 
    (3)根据this指针得到具体的对象(即 girl 所指向的位于堆中的对象)。
    (4)根据对象得到该对象对应的方法表,根据偏移量15查看有无重写(override)该方法,如果重写,则可以直接调用(Girl的方法表的speak项指向自身的方法而非父类);如果没有重写,则需要拿到按照继承关系从下往上的基类(这里是Person类)的方法表,同样按照这个偏移量15查看有无该方法。

    6.接口调用

    因为 Java 类是可以同时实现多个接口的,而当用接口引用调用某个方法的时候,情况就有所不同了。

    Java 允许一个类实现多个接口,从某种意义上来说相当于多继承,这样同样的方法在基类和派生类的方法表的位置就可能不一样了。

    interface IDance{ 
       void dance(); 
     } 
     
     class Person { 
     public String toString(){ 
       return "I'm a person."; 

     public void eat(){} 
     public void speak(){} 
        
     } 
     
     class Dancer extends Person implements IDance { 
     public String toString(){ 
       return "I'm a dancer."; 
      } 
     public void dance(){} 
     } 
     
     class Snake implements IDance{ 
     public String toString(){ 
       return "A snake."; } 
     public void dance(){ 
     //snake dance 
         } 
     }


    可以看到,由于接口的介入,继承自接口 IDance 的方法 dance()在类 Dancer 和 Snake 的方法表中的位置已经不一样了,显然我们无法仅根据偏移量来进行方法的调用。

    Java 对于接口方法的调用是采用搜索方法表的方式,如,要在Dancer的方法表中找到dance()方法,必须搜索Dancer的整个方法表。

    因为每次接口调用都要搜索方法表,所以从效率上来说,接口方法的调用总是慢于类方法的调用的。


    --------------------- 
    作者:SEU_Calvin 
    来源:CSDN 
    原文:https://blog.csdn.net/SEU_Calvin/article/details/52191321?utm_source=copy 
    版权声明:本文为博主原创文章,转载请附上博文链接!

     

     

    展开全文
  • 2.如果没有父类加载器,则要么Parent是根类加载器,要么本身就是根类加载器,则跳到第4步,如果父类加载器存在,则进入第3步。 3.请求使用父类加载器去载入目标,如果载入成功则跳至第8步,否则接着执行第5步。 ...

    一、异常

    1.异常的结构

    Throwable
    Error
    Exception
    虚拟机错误 VirtualMachineError
    内存溢出 OutOfMermoryError
    线程死锁 ThreadDeath
    RuntimeException
    IO异常
    SQL异常
    NullPointerException
    ArrayIndexOutOfBoundsException

    1)Error : JVM错误,无法处理
    2)Exception:(可处理)

    (1)运行期异常

    ArrayIndexOutOfBoundException
    NullPointerException

    (2)编译期异常

    InterruptedException
    ClassNotFoundException
    NoSuchFiledException
    NoSuchMethodException

    2.异常

    异常处理(一般只针对编译期异常)->五个关键字

    1)try

    try{
    //可能发生异常的代码
    arr[1]=10;
    Thread.sleep(1000);
    //return之前调用finally进行退出
    return}
    catch(ArrayIndexOutOfBoundsException e){//关心的异常,不关心的用基类Exception处理
        e.PrintStackTrace();//先用子类处理,再用父类处理
    }
    catch(Exception e){
        e.PrintStackTrace();
    }finally{
        //特点是无论是否会发生异常必定会被执行到
        System.out.println("finally");
    }
    

    注意:
    一个try块中存在多条可能会发生异常的代码A/B/C,如果A发生异常,此时B、C语句是不会被执行到
    try块尽量避免嵌套

    2)catch:

    catch(NullPointerException){
       //先用关心的子类处理,再用父类处理
    }
     尽量避免过细划分异常
    

    3)finally

    • final finally finalize 的区别? 如果try块里包含
    • return;并且finally块也包含return(从finally块return退出)
    • 如果try块里面也含有退出System.exit();finally也包含System.exit();
    • 问此时从哪里退出?
      从try块中的System.exit();中退出

    4)throw

    throw new EmptyStackException();
    扔异常对象

    5)throws

    void fun() throws InterruptedException{
    /
    }
    调用处:
    try{
    fun();
    }catch(InterruptedException){
     e.PrintStackTrace();
    }
    

    二、类加载

    1.类加载过程

    从磁盘加载到JAVA虚拟机的过程,分为三大阶段

    1.1装载阶段

    类加载器:(继承关系)
    null C/C++终极类加载器
    如果一个类他的类加载器是启动加载器,此时getClassLoader();
    返回值null,C/C++实现

    1.2Boostrap ClassLoader 启动类加载器

    它用来加载 Java 的核心类,是用原生代码来实现的,并不继承自 java.lang.ClassLoader(负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类)。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。

    1.3 Ext ClassLoader 拓展类加载器

    它负责加载JRE的扩展目录,lib/ext或者由java.ext.dirs系统属性指定的目录中的JAR包的类。由Java语言实现,父类加载器为null。

    1.4App ClassLoader 应用类加载器

    它负责在JVM启动时加载来自Java命令的-classpath选项、java.class.path系统属性,或者CLASSPATH换将变量所指定的JAR包和类路径。
    标识文件类型:魔数+次版本号+主版本号
    过程:双亲委派模型
    注:加载类 ->(parent)委派模型

    • 找之前是否加载过类,如果加载过,从父类到子类依次尝试加载,将加载产物
    • Class对象返回。如果没有加载过,依次在其父类中查找,直到Boostrap ClassLoader。
    • 路径找不到加载失败 ClassNotFoundException
      路径找不到加载失败 ClassNotFoundException
      双亲委派模型的优点:
    • 安全性
    • 避免类的重复加载
      类加载器加载Class大致要经过如下8个步骤:
      1.检测此Class是否载入过,即在缓冲区中是否有此Class,如果有直接进入第8步,否则进入第2步。
      2.如果没有父类加载器,则要么Parent是根类加载器,要么本身就是根类加载器,则跳到第4步,如果父类加载器存在,则进入第3步。
      3.请求使用父类加载器去载入目标类,如果载入成功则跳至第8步,否则接着执行第5步。
      4.请求使用根类加载器去载入目标类,如果载入成功则跳至第8步,否则跳至第7步。
      5.当前类加载器尝试寻找Class文件,如果找到则执行第6步,如果找不到则执行第7步。
      6.从文件中载入Class,成功后跳至第8步。
      7.抛出ClassNotFountException异常。
      8.返回对应的java.lang.Class对象。

    1.2链接阶段

    1.2.1验证

    • 主次版本号
    • 文件格式验证

    1.2.2准备

    • 变量所使用的内存在方法区中进行分配
    • count在方法区分配4字节内存,并赋类型默认值为0.

    1.2.3解析

    • 将符号引用改为直接引用的过程
      3.初始化阶段:
      给静态变量赋值操作:count=10;
      自定义类加载器:
      1.根据路径找到字节码文件 findClass文件
      2.采用双亲委派模型加载 loadClass方法
      3.加载字节码文件生成对应的Class对象

    1. 3.初始化阶段:

    自定义类加载器:
    1.根据路径找到字节码文件 findClass文件
    2.采用双亲委派模型加载 loadClass方法
    3.加载字节码文件生成对应的Class对象
    初始化一个类的子类(会首先初始化子类的父类)

    2.反射

    生成对象
    第一步:
    获取当前类的Class对象:

    Class c=People.classclass people{
       //public static Class class;
    隐含记录Class对象(加载阶段产生)存储位置
    }
    
    Class c=Class.forName("com.tulun.scr7.People);
    //异常
    
    People p=new People();
      Class c=p.getClass();//getClass()->继承自Object里的方法
    

    三、内部类

    内部类包含:实例内部类、静态内部类、匿名内部类、局部内部类

    3.1实例内部类

    public class TestDemo {
    //    private int age;
    //    public class Test{
    //        private String name;
    //        public Test(){
    //            this.name=name;
    //            TestDemo.this.age=age;
    //        }
    //    }
    //}
    

    3.2静态内部类

    public class TestDemo{
        private int age;
                public static class Test{
            private String name;
            public Test(){
                this.name=name;
                    }
                }
    

    实例内部类与静态内部类的区别:

    • 实例内部类包含两个this(指向当前对象,外部类对象的this)

    • 静态内部类包含一个this->指向当前对象的this

    3.2匿名内部类

    向上造型:
    基类(基接口)的引用,引用派生类对象(实现该接口的类对象)

      public interface InterfaceA{
           InterfaceA interfaceA=new InterfaceA() {
               @Override
               protected void finalize() throws Throwable {
                   super.finalize();
               }
           };
    }
    

    3.4局部内部类

    局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。

    class People{
        public People() {
             
        }
    }
     
    class Man{
        public Man(){
             
        }
         
        public People getWoman(){
            class Woman extends People{   //局部内部类
                int age =0;
            }
            return new Woman();
        }
    }
    

    访问修饰符:

    1.修饰成员:

    • public 默认 protected private
    • protected <=>默认 包访问权限
    • 继承:子类和父类定义在不同包下,子类可以访问父类修饰用protected
      2.修饰类:
    • 修饰外部类:public 默认
    • 修饰内部类:默认 public private protected

    3.5实例内部类对象与静态内部类对象

    public class TestDemo{
        public static void main(String[] args) {
            //实例内部类对象:
    //        OutClass.InnerClass i =new OutClass().new InnerClass();
            //静态内部类对象:
            OutClass.InnerClass i =new OutClass.InnerClass();
        }
    }
    

    四、多态的实现

    一个函数名根据对象不同对应不同实现
    多态实现原理
    动多态的实现原理:地址覆盖
    1)静多态(编译期多态/静态绑定)-> 重载(覆盖)
    重载条件:在一个类,函数名相同,参数列表不同
    2)动多态(运行期多态/动态绑定)->重写
    发生动态绑定的条件:
    a.继承 b.重写 c.向上造型(基类的引用 引用派生类对象)

    Animal a=new Cat();//是一个
    Object o=new Integer();
    

    4.1抽象

    关键字:abstract
    如果一个类包含抽象方法,那么该类必须是抽象类;是抽象类但不一定含有抽象方法
    任何子类必须重写父类的抽象方法,或者声明自身为抽象类。

    interface FlyInter {
        void fly();
    }
     
    public abstract class FlyGroups implements FlyInter{
        public String name = "飞行类";
        public String getName(){
            return name;
        }
        abstract void fun();
    }
     
     
    public class Airplane extends FlyGroups {
        @Override
        public void fly() {
            String name = super.getName();
            System.out.println(name);
        }
        @Override
        public void fun(){
        }
    }
    

    4.2接口

    接口与类的区别:

    • 接口不能用于实例化对象。
    • 接口没有构造方法。
    • 接口中所有的方法必须是抽象方法。
    • 接口不能包含成员变量,除了 static 和 final 变量。
    • 接口不是被类继承了,而是要被类实现。
    • 接口支持多继承。
      接口特性
    • 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public
      abstract(只能是 public abstract,其他修饰符都会报错)。
    • 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)。
    • 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。
    • 接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字。
    • 接口中每一个方法也是隐式抽象的,声明时同样不需要abstract关键字。
    • 接口中的方法都是公有的。
      抽象类和接口的区别
    1. 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
    2. 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
    3. 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
    4. 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
    interface 接口名称 [extends 其他的接口名] {
            // 常量
            // 抽象方法
    }
    可继承
    interface A{
        void funA();
    }
    interface B extends A{
        void funB();
    }
    

    4.3方法重写与重载

    4.3.1方法重写

    若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法。 如需父类中原有的方法,可使用super关键字,该关键字引用了当前类的父类。方法重写是要注意权限的问题,子类中的权限不能小于父类的权限,当父类的权限为private时,子类无法继承。也就无法产生所谓的重写。(修饰符高低:private < 默认修饰符(produced) < public)

    public class Parent{
     
        public void fun(){
        }
    }
     
    public class Child extends Parent{
        @Override
        public void fun(){
            //子类的重写
        }
    }
    

    4.3.2方法重载

    方法的重载是方法的类同,方法名相同,参数列表不同。

    public class Demo {
     
    	//一个普通得方法,不带参数,无返回值
    	public void add(){
    		//method body
    	}
    	
    	//重载上面的方法,并且带了一个整形参数,无返回值
    	public void add(int a){
    		//method body
    	}
    	
            //重载上面的方法,并且带了两个整型参数,返回值为int型
    	public int add(int a,int b){
    		//method body
    		return 0;
    	}
     
    }
    
    
     
    
    
    展开全文
  • 访问控制   内 包内 子类 任意 public y y y y protected y y y   default y y     private y
  • 多态 {#toc_0} 目标 {#toc_1} 多态 面向对象三大特性 封装 根据 职责 将 属性 和 方法 封装 到一个抽象的 中 定义的准则 继承 实现代码的重用,相同的代码不需要重复的编写 设计的技巧 子类针对自己...
  • 反射和类加载器

    2015-12-21 22:33:16
    当初看了几本书后因为觉得反射,多态,动态链接有共同的...反射和类加载器的关系,即是我们在反射调用某个时,这个会被类加载器加载一次,第一个问题,如何去加载这个,第二个问题,谁来加载这个。加载的这个
  • OOP 多态和构造执行顺序在java的面试题中,对象的初始化顺序配合多态是一种常见考题!今天我就来详细的回顾一下!中一般包括这几个部分: 静态成员 包括静态的成员变量 静态代码块、 非静态的成员变量 构造函数 ...
  • Java实现多态的机制是后期绑定。 但Java也有些地方可以用前期绑定,比如:final,static,private(隐式final)和构造方法(隐式static)是前期绑定。 另外,Java只有普通方法的调用可以是多态的,如果直接访问某个...
  • 多态

    2016-05-17 22:45:09
    多态
  • class A {  static { ...//只有在类加载时候会执行一次  }    public A() {  System.out.print("x");  }   }   class B extends A {  static {  System.out.print("b")...
  • Java中加载器和反射

    千次阅读 2019-07-23 12:01:23
    一、类加载器 1、的加载 2、初始化时机(何时加载到内存中) 3、类加载器的组成 二、反射 1、反射原理步骤 2、获取一个的 class 文件对象的三种方式 3、获取class 文件中的成员 (1) 使用反射获取无参...
  • Rico's Blogs 潜心修炼,成为一个更好的人。 ...赠书 | 异步2周年,技术图书免费选 程序员8月书讯 项目管理+...深入理解Java类加载器(一):Java加载原理解析 标签: Java加载原理双亲委派模型启动加载
  • 多态与内部

    2021-07-23 19:31:49
    2、掌握Java多态的使用 3、掌握引用数据类型转换及异常处理 4、掌握几种内部的使用 5、理解Java内存管理与垃圾回收机制 第1章 模板设计模式 1.1 模板设计模式概述 **模板设计模式定义:**定义一个操作中的算法...
  • 抽象和接口对比 抽象 特点: abstract修饰,只能被单继承 abstract修饰抽象方法,只有方法名字,不能有实现(方法体)(普通方法可以有方法体【即可以有方法实现】) ...存在构造吗? 存在,不能
  • 什么是多态为什么要有多态一些理解多态的表述构造多态实例化一个对象的过程参考 什么是多态 不局限于特定编程语言中,我们先从概念上理解多态多态是同一个行为具有多个不同表现形式或者形态的能力;也就是,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 42,768
精华内容 17,107
关键字:

多态类加载器