黑马程序员技术交流社区

标题: "第二帖"之final、private、覆盖,之间的关系 [打印本页]

作者: 袁梦希    时间: 2013-4-26 12:09
标题: "第二帖"之final、private、覆盖,之间的关系
本帖最后由 袁梦希 于 2013-5-21 18:54 编辑

  1. class Clidder{
  2. //定义一个final的私有方法
  3. private final void flipper(){
  4.   System.out.println("Clidder");
  5. }
  6. }
  7. public class Clidlet extends Clidder{
  8. public final void flipper(){
  9.   System.out.println("Clidlet");
  10. }
  11. public static void main(String[] args){
  12.   
  13.   new Clidlet().flipper();
  14. }
  15. }
复制代码

问题收集1.

大家看一看我上面的代码打印出的什么内容:

A.Clidlet              B.Clidder             C.Clidder               D.Clidlet
                                                    Clidlet                   Clidder

分析这是关于私有化和final之间的关系问题,和重写的关系。尽管final方法不能被重写,但这里的方法是私有的,因为是隐藏的,
其结果是将会创建新的、可访问的fiipper()方法。因此,在本例中不会出现多态性,调用的方法只是子类的方法,不会发生错误。
所以   A正确。
---------------------------------------------------------------------------------------------------------------------------------------------------------------

一、final
 根据程序上下文环境,java关键字final有“这是无法改变的”或者“终态的”含义,它可以修饰非抽象类、非抽象类成员方法和变量。你可能出于两种理解而需要阻止改变:设计或效率。
final类不能被继承,没有子类,final类中的方法默认是final的。
final方法不能被子类的方法覆盖,但可以被继承。
final成员变量表示常量,只能被赋值一次,赋值后值不再改变。
final不能用于修饰构造方法。
注意:父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final类型的。

1、final类
 final类不能被继承,因此final类的成员方法没有机会被覆盖,默认都是final的。在设计类时候,如果这个类不需要有子类,类的实现细节不允许改变,并且确信这个类不会载被扩展,那么就设计为final类。

2、final方法
如果一个类不允许其子类覆盖某个方法,则可以把这个方法声明为final方法。
使用final方法的原因有二:
第一、把方法锁定,防止任何继承类修改它的意义和实现。
第二、高效。编译器在遇到调用final方法时候会转入内嵌机制,大大提高执行效率。
例如:
  1. public class Test1 {

  2. public static void main(String[] args) {
  3. // TODO 自动生成方法存根
  4. }

  5. public void f1() {
  6. System.out.println("f1");
  7. }
  8. //无法被子类覆盖的方法
  9. public final void f2() {
  10. System.out.println("f2");
  11. }

  12. public void f3() {
  13. System.out.println("f3");
  14. }

  15. private void f4() {
  16. System.out.println("f4");
  17. }
  18. }

  19. public class Test2 extends Test1 {

  20. public void f1(){
  21. System.out.println("Test1父类方法f1被覆盖!");
  22. }

  23. public static void main(String[] args) {
  24. Test2 t=new Test2();
  25. t.f1();
  26. t.f2(); //调用从父类继承过来的final方法
  27. t.f3(); //调用从父类继承过来的方法
  28. //t.f4(); //调用失败,无法从父类继承获得

  29. }
复制代码
回复继续....



作者: 何俊森    时间: 2013-4-26 12:51
{:soso_e179:}学习了。
作者: 刘凯    时间: 2013-4-26 13:19
不知道吧下边的public改为private,会不会出问题 所以试了下
  1. class Test
  2. {
  3.         public static void main(String[] args)throws Exception
  4.         {
  5.                 //调用子类中的方法
  6.                 new Clidlet().method();
  7.         }       
  8. }

  9. class Clidder{
  10. //定义一个final的私有方法
  11.         private final void flipper(){
  12.           System.out.println("Clidder");
  13.         }
  14. }
  15. class Clidlet extends Clidder{
  16. //子类中同样这个方法
  17.          private final void flipper(){
  18.                  System.out.println("Clidlet");
  19.          }
  20.          //调用本类中的私有方法flipper
  21.         public void method(){          
  22.                 flipper();
  23.         }
  24. }
复制代码
这个貌似就是说,如果一个方法设为私有,那么就不存在复写这么一个说法,也就是说Clidlet 类中的这个flipper方法不算是复写
于此不同的是,如果上下两个flipper方法都为public  那么由于final的原因,就会报错
于是有个问题出来了  如果这个两个方法不是final 的 且是private   那么算不算是复写?    自我感觉貌似是不算
作者: 殇_心。    时间: 2013-4-26 13:39
刘凯 发表于 2013-4-26 13:19
不知道吧下边的public改为private,会不会出问题 所以试了下这个貌似就是说,如果一个方法设为私有,那么就 ...

  也是不算复写的。  因为private修饰的函数,子类是看不到的。 是属于本类独有方法。
作者: 曹睿翔    时间: 2013-4-26 14:35
不够啊,继续整理,{:soso_e141:}
我要好好搜刮一番
作者: 曹睿翔    时间: 2013-4-26 14:51
曹睿翔 发表于 2013-4-26 14:35
不够啊,继续整理,
我要好好搜刮一番

说的对,长期任务,非把大家的基础提一个层次不可!!
作者: 袁梦希    时间: 2013-5-1 15:50
曹睿翔 发表于 2013-4-26 14:51
说的对,长期任务,非把大家的基础提一个层次不可!!

等我把面试弄完   我在找题   你大爷了,5月1过后面试了,过不去就卡脸了
作者: 曹睿翔    时间: 2013-5-1 15:53
袁梦希 发表于 2013-5-1 15:50
等我把面试弄完   我在找题   你大爷了,5月1过后面试了,过不去就卡脸了

禽兽,你要是卡到面试让你卧槽不起
作者: 江大海    时间: 2013-5-1 17:21
刘凯 发表于 2013-4-26 13:19
不知道吧下边的public改为private,会不会出问题 所以试了下这个貌似就是说,如果一个方法设为私有,那么就 ...

它都private了,子类都主知道有这一个东西,怎么复写??不过编译不会出错
作者: 棉/mg花/x糖    时间: 2013-5-21 18:48
本帖最后由 棉/mg花/x糖 于 2013-5-21 18:51 编辑
刘凯 发表于 2013-4-26 13:19
不知道吧下边的public改为private,会不会出问题 所以试了下这个貌似就是说,如果一个方法设为私有,那么就 ...


显然不会是重写啊,因为父类中若为private方法,那么子类根本上就继承不到这个方法
也就是说子类中根本就不知道父类有这个方法,所以在子类中任意写和父类同名的这个private方法是不会报错的
在子类中写这样的方法算是子类特有的方法,与父类的这个private方法毫无半点关系,自然不会报错!


作者: 袁梦希    时间: 2013-5-21 18:55
3、final变量(常量)
 用final修饰的成员变量表示常量,值一旦给定就无法改变!
 final修饰的变量有三种:静态变量、实例变量和局部变量,分别表示三种类型的常量。
 从下面的例子中可以看出,一旦给final变量初值后,值就不能再改变了。
 另外,final变量定义的时候,可以先声明,而不给初值,这中变量也称为final空白,无论什么情况,编译器都确保空白final在使用之前必须被初始化。但是,final空白在final关键字final的使用上提供了更大的灵活性,为此,一个类中的final数据成员就可以实现依对象而有所不同,却有保持其恒定不变的特征。
package org.leizhimin;

public class Test3 {
private final String S="final实例变量S";
private final int A=100;
public final int B=90;

public static final int C=80;
private static final int D=70;

public final int E; //final空白,必须在初始化对象的时候赋初值

public Test3(int x){
E=x;
}

/**
* @param args
*/
public static void main(String[] args) {
Test3 t=new Test3(2);
//t.A=101; //出错,final变量的值一旦给定就无法改变
//t.B=91; //出错,final变量的值一旦给定就无法改变
//t.C=81; //出错,final变量的值一旦给定就无法改变
//t.D=71; //出错,final变量的值一旦给定就无法改变

System.out.println(t.A);
System.out.println(t.B);
System.out.println(t.C); //不推荐用对象方式访问静态字段
System.out.println(t.D); //不推荐用对象方式访问静态字段
System.out.println(Test3.C);
System.out.println(Test3.D);
//System.out.println(Test3.E); //出错,因为E为final空白,依据不同对象值有所不同.
System.out.println(t.E);

Test3 t1=new Test3(3);
System.out.println(t1.E); //final空白变量E依据对象的不同而不同
}

private void test(){
System.out.println(new Test3(1).A);
System.out.println(Test3.C);
System.out.println(Test3.D);
}

public void test2(){
final int a; //final空白,在需要的时候才赋值
final int b=4; //局部常量--final用于局部变量的情形
final int c; //final空白,一直没有给赋值.
a=3;
//a=4; 出错,已经给赋过值了.
//b=2; 出错,已经给赋过值了.
}
}


4、final参数
当函数参数为final类型时,你可以读取使用该参数,但是无法改变该参数的值。

public class Test4 {
public static void main(String[] args) {
new Test4().f1(2);
}

public void f1(final int i){
//i++; //i是final类型的,值不允许改变的.
System.out.print(i);
}
}

作者: 袁梦希    时间: 2013-5-21 18:59
java jdk1.6 访问级别修饰符 public protected 默认 private
java jdk1.6中。
我在很长时间里对级别访问修饰符都很迷惑。
最后自己测试一番结果与所学的有所出入(可能是版本或其它问题)。
下面是自己测试的一点总结(对其中的名词术语,可能不准确。但所表达的意思应该还是能)。

一:对于类的级别访问修饰符来说,只有public和默认不写两种情况。
public:所有类都可以访问(一定级别的 类的成员变量,下同)。
默认不写:只有在同一个包下的类可以访问。

二:对于类成员来说(可能有的人把static修饰的成员叫做类方法和类变量,我这里就我分了。只叫静态,非静态)
注释:所有类(不管是public或者是private等修饰符修饰的类)他们的成员都能被类自身访问。
1.
对于static类的成员(属性和方法)
1.1  public:允许任何类访问。
1.2  protected:允许本类所在包下的类访问和其它包下的子类访问。
1.3 默认不写:只允许本类所在包下的类访问。

作者: 神之梦    时间: 2013-5-21 20:45
曹睿翔 发表于 2013-4-26 14:35
不够啊,继续整理,
我要好好搜刮一番

{:soso_e183:}搜刮完后,链接全整一帖中去




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2