Java基础知识总结(三)

 1、接口

   •   接口是一种规范,是一种规则,它只给出了方法的样子,规定你要实现哪些方法,而不给出方法的实现,让接口的实现类去实现这些方法,但是对于不同的实现类来说,对方法的实现可以完全不同。

  •   接口的实现类如果实现了某一个接口,那么必须实现接口中定义的所有的待实现的方法。如果你不想要实现方法,那么实现类必须定义为抽象类,不想实现的方法必须定义为抽象方法。

  •   接口中定义的属性和方法的默认访问级别都是public,所以方法肯定不被private所修饰,所有的方法前都默认包含了abstract ,表明它是一个抽象方法,但是可以省略,而且默认是省略的

  •   接口实际上是一个抽干了的抽象类,它里面所有的方法都是抽象的,都是不能给出任何实现部分的-----   干尸类

  •   因为接口是一种特殊的“抽象类”,而且因为抽象类可以继承别的类,所以接口也可以继承接口,也只可以继承接口。但是接口不可以实现接口。

  •   一个类可以实现多个接口使用关键字implements ,一个接口可以继承多个接口使用关键字extends,一个类可以同时继承一个别的类,而且实现一个或多个接口,但是关键字extends要在前。

2、抽象类和方法 

  •   如果一个方法中存在不可预知的方法实现,那么这个方法所在的类就应该声明为抽象类   

  •   如果在两个类当中有同名的方法,按照正常道理来说,应该提取到父类里,但是这个两个方法又有明显的方法实现上的不同,那么在父类里的方法,就应该定义成为抽象,抽象方法,只给出了方法的样子,而不给出方法的具体实现,具体实现由继承这个类的具体的子类去实现

  •   抽象方法,必须在抽象类里,抽象类里不一定有抽象方法

  •   没有抽象方法的抽象类的存在也是有意义的。这决定了这个类是不能被直接实例化的,他的作用基本上是作为一个“框框”存在的。-------------种猪

  •   重写的前提是--- 父类里知道该方法如何去实现,子类不打算走原路,所以覆盖父类里的实现,

  •   父类不给出实现,也不知道该如何实现,由具体的子类自己决定如何实现,但是给出一个定义,要求子类必须实现。

3、接口和抽象类的区别

  •   接口是用来被实现的(implements),而抽象类是用类被继承的 (extends)

  •   接口可以继承别的多个接口,组成一个新的接口

  •   抽象类可以继承一个别的类,或实现一个或多个接口

  •   接口是一个100%的抽象类,里面的方法没有任何一个有任何的实现

  •   抽象类可以包含非抽象的方法,也就是说可以给出某一些方法的实现。

  •   接口一般处于代码的最底层,作出一些规定,而接口之上一层抽象类层,对接口进行第一次的实现,把不可能一次完成的方法,交由自己的子类来实现。

  •   抽象类可以有构造方法,而接口不可以有构造方法。 接口中定义的变量只能为公有的,静态的,终态的,而且会默认增加。  

4、Java 接口和Java 抽象类对比

  1 )Java 接口和 Java 抽象类最大的一个区别,就在于 Java 抽象类可以提供某些方法的部分实现,而 Java 接口不可以,这大概就是 Java 抽象类唯一的优点吧,但这个优点非常有用。如果向一个抽象类里加入一个新的具体方法时,那么它所有的子类都一下子都得到了这个新方法,而 Java 接口做不到这一点,如果向一个 Java 接口里加入一个新方法,所有实现这个接口的类就无法成功通过编译了,因为你必须让每一个类都再实现这个方法才行,这显然是Java 接口的缺点。

  2 )一个抽象类的实现只能由这个抽象类的子类给出,也就是说,这个实现处在抽象类所定义出的继承的等级结构中,而由于 Java 语言的单继承性,所以抽象类作为类型定义工具的效能大打折扣。在这一点上,Java 接口的优势就出来了,任何一个实现了一个 Java 接口所规定的方法的类都可以具有这个接口的类型,而一个类可以实现任意多个 Java 接口,从而这个类就有了多种类型。

  3 )从第 2 点不难看出,Java 接口是定义混合类型的理想工具,混合类表明一个类不仅仅具有某个主类型的行为,而且具有其他的次要行为。

  4 )结合 1、2 点中抽象类和Java 接口的各自优势,具经典的设计模式就出来了:声明类型的工作仍然由Java 接口承担,但是同时给出一个Java 抽象类,且实现了这个接口,而其他同属于这个抽象类型的具体类可以选择实现这个 Java 接口,也可以选择继承这个抽象类,也就是说在层次结构中,Java 接口在最上面,然后紧跟着抽象类,哈,这下两个的最大优点都能发挥到极至了。这个模式就是“缺省适配模式”。

  在Java 语言 API 中用了这种模式,而且全都遵循一定的命名规范:Abstract  +接口名。 Java 接口和Java抽象类的存在就是为了用于具体类的实现和继承的,如果你准备写一个具体类去继承另一个具体类的话,那你的设计就有很大问题了。Java 抽象类就是为了继承而存在的,它的抽象方法就是为了强制子类必须去实现的。  

5、方法、代码块 

  注1. 一个方法中定义的局部变量是不能被声明为静态的。因为静态修饰符 static是一个与类而非类实例相关的概念,而方法是一个局部概念,它们附属于类实例,其生命周期不同于类实例,更不同于类,而方法内部变量会随着方法的推出而被撤销,因此一个方法体中声明的局部变量是不能被 static 修饰的。即使方法被声明为静态的,其内部变量也不能被声明为静态的。一个被 static 修饰符修饰的静态方法,除了可以访问中其内部定义的变量外,则只能访问被static 修饰符修饰的静态变量。如果需要访问非静态类的属性,则必须先实例化一个类实例,再通过该类实例引用非静态类的属性。但是,一个非静态的方法可以访问一个静态变量。

  注2. 对静态方法和非静态方法的调用方式不同,对非静态方法的调用时在运行期决定的,而对静态方法的调用则发生在编译期。一个非静态方法可以调用一个静态方法,但是不允许一个静态方法直接调用非静态方法,除非通过类实例调用。

  注3. 一个静态方法不能重写为一个非静态方法,只能被重写为一个静态方法,但是可以被重载为一个非静态的方法,重写的含义是始终只有一个定义,只是原来的含义完全被后来的含义所取代,即形式不能变,而重载的含义是指同一个样的东西在不同的地方具有不同的含义。

  注4. 静态代码块不是一个方法,实际上只是一个 static修饰符,后跟一个方法主体(一对大括号内的一组语句) 。静态代码块主要用于初始化,该代码块中的代码仅被执行一次,即在构造函数执行前执行,而且只执行一次,如果继承的父类里有静态代码块,先执行父类的,但是子类的静态代码块还是要先于父类的构造函数。如果一个类中存在多个静态代码块,那么其运行次序取决于在类中定义的次序。

  注5. 非静态代码块不是一个方法,实际上只是一个方法主体( 一对大括号内的一组语句)。每当创建类实例时,非静态代码块获得执行,其运行在父类构造器之后,所在类构造器之前。如果一个类中存在多个非静态代码块,那么其运行顺序取决于在类中定义的次序。  

  静态代码块与非静态代码块执行顺序如下:

 1 public class Father {
 2     public Father(){
 3         System.out.println("这是父类的构造方法!");
 4     }
 5     {
 6         System.out.println("这是父类的非静态代码块!");
 7     }
 8     static {
 9         System.out.println("这是父类的静态代码块!");
10     }
11 }
 1 public class Son extends Father{
 2     public Son(){
 3         System.out.println("这是子类的构造方法!");
 4     }
 5     {
 6         System.out.println("这是子类的非静态代码块!");
 7     }
 8     static {
 9         System.out.println("这是子类的静态代码块!");
10     }
11 }
1 public class Test {
2     public static void main(String[] args) {
3         new Son();
4         new Son();
5     }
6 }

  执行结果:

 1 这是父类的静态代码块!
 2 这是子类的静态代码块!
 3 这是父类的非静态代码块!
 4 这是父类的构造方法!
 5 这是子类的非静态代码块!
 6 这是子类的构造方法!
 7 这是父类的非静态代码块!
 8 这是父类的构造方法!
 9 这是子类的非静态代码块!
10 这是子类的构造方法!

  相同点:都是在JVM加载类时且在构造方法执行之前执行,在类中都可以定义多个,一般在代码块中对一些static变量进行赋值。

  不同点:静态代码块在非静态代码块之前执行。(静态代码块—>非静态代码块—>构造方法静态代码块只在第一次new执行一次,之后不再执行,而非静态代码块在每new一次就执行一次。非静态代码块可在普通方法中定义(不过作用不大);而静态代码块不行。JVM加载类时会执行这些静态的代码块,如果static代码块有多个,JVM将按照它们在类中出现的先后顺序依次执行它们,每个代码块只会被执行一次。

6、重写与重载的区别

   1、重载(Overloading)

    (1)方法重载是让类以统一的方式处理不同类型数据的一种手段。多个同名函数同时存在,具有不同的参数个数/类型。重载Overloading是一个类中多态性的一种表现。

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

    (3) 重载的时候,方法名要一样,但是参数类型或个数不一样,返回值类型可以相同也可以不相同。无法以返回型别作为重载函数的区分标准

  无法以返回型别作为重载函数的区分标准
1
public class Test2 { 2 public int test(int i,float f){ //编译错误 3 return i; 4 } 5 public int test(int i,float f){ //编译错误 6 return f; 7 } 8 }

  2、重写(Overriding)

    (1) 父类与子类之间的多态性,对父类的函数进行重新定义。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。在Java中,子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。方法重写又称方法覆盖。

    (2)若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法。如需父类中原有的方法,可使用super关键字,该关键
字引用了当前类的父类。(重写不代表销毁,而是覆盖)

    (3)子类函数的访问修饰权限不能少于父类的;

    总结:重载和重写(覆盖)。
        方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被“屏蔽”了,而且如果子类的方法名和参数类型和个数都和父类相同,那么子类的返回值类型必须和父类的相同;如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。Overloaded的方法是可以改变返回值的类型。也就是说,重载的返回值类型可以相同也可以不同。

  3、子类和父类方法之间的重载

 1 //父类
 2 public class Father {
 3     public int eat(int i){
 4         System.out.println("i="+i);
 5         return i;
 6     }
 7 }
 8 //子类
 9 public class Son extends Father{
10     public float eat(float i){
11         System.out.println("i="+i);
12         return i;
13     }
14 }
15 //测试类
16 public class Test {
17     public static void main(String[] args) {
18         Son son=new Son();
19         son.eat(10);
20         son.eat((float)10.0);
21     }
22 }
23 //测试结果
24 i=10
25 i=10.0

  1. Override 特点

    1、覆盖的方法的标志必须要和被覆盖的方法的标志完全匹配,才能达到覆盖的效果;

    2、覆盖的方法的返回值必须和被覆盖的方法的返回一致;

    3、覆盖的方法所抛出的异常必须和被覆盖方法的所抛出的异常一致,或者是其子类;

    4、方法被定义为final不能被重写。

    5、对于继承来说,如果某一方法在父类中是访问权限是private,那么就不能在子类对其进行重写覆盖,如果定义的话,也只是定义了一个新方法,而不会达到重写覆盖的效果。(通常存在于父类和子类之间。)

  2.Overload 特点

    1、在使用重载时只能通过不同的参数样式。例如,不同的参数类型,不同的参数个数,不同的参数顺序(当然,同一方法内的几个参数类型必须不一样,例如可以是fun(int, float), 但是不能为fun(int, int));

    2、不能通过访问权限、返回类型、抛出的异常进行重载;

    3、方法的异常类型和数目不会对重载造成影响;

    4、重载事件通常发生在同一个类中,不同方法之间的现象,但也可以发生在父子类中,如上程序举例所示。

  其具体实现机制: overload是重载,重载是一种参数多态机制,即代码通过参数的类型或个数不同而实现的多态机制。 是一种静态的绑定机制(在编译时已经知道具体执行的是哪个代码段)。 override是覆盖。覆盖是一种动态绑定的多态机制。即在父类和子类中同名元素(如成员函数)有不同 的实现代码。执行的是哪个代码是根据运行时实际情况而定的。

原文地址:https://www.cnblogs.com/gw811/p/2681251.html