国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

引用 造型 protected和private的困惑

2019-11-18 13:18:40
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

  或許大家java的多態(tài)問(wèn)題,對(duì)上溯,下溯造型有了一定的概念,對(duì)PRotected和private大家想必也很清楚,但是,這幾個(gè)個(gè)結(jié)合在一起,往往令人產(chǎn)生很多困惑,在這里,我舉一個(gè)例子,大家或許會(huì)發(fā)覺(jué)這篇文章對(duì)你來(lái)說(shuō)還是很有意義的:
  例子一共有兩個(gè)class. 可能出現(xiàn)困惑的地方我都會(huì)在后面一一解釋.
  A是一個(gè)父類,B繼續(xù)A,并且實(shí)現(xiàn)了protectedTest(Object obj)方法.如下面所示:
  B.java的源代碼:
  package cn.org.matrix.test;
  import cn.org.matrix.test.A;
  /**
   * <p>Title: protect, private and upcasting </p>
   * <p>Description: email:chris@matrix.org.cn</p>
   * <p>Copyright: Matrix Copyright (c) 2003</p>
   * <p>Company: Matrix.org.cn</p>
   * @author chris
   * @version 1.0,who use this example pls remain the declare
   */
  public class B extends A
  {
    protected int protectedb = 0;
    protected int protectedab = 0;
    
  
    protected void protectedTest(Object obj)
    {
      System.out.println("in B.protectedTest(Object):" + obj);
    }
  }
  
  A.java的源代碼:
  package cn.org.matrix.test;
  import cn.org.matrix.test.B;
  /**
   * <p>Title: protect, private and upcasting </p>
   * <p>Description: email:chris@matrix.org.cn</p>
   * <p>Copyright: Matrix Copyright (c) 2003</p>
   * <p>Company: Matrix.org.cn</p>
   * @author chris
   * @version 1.0,who use this example pls remain the declare
   */
  
  public class A
  {
    protected int protecteda = 0;
    protected int protectedab = 0;
    private void privateTest()
    {
      System.out.println("in A.privateTest()");
    }
    protected void protectedTest(Object obj)
    {
      System.out.println("in A.protectedTest(Object):" + obj );
    }
  
    protected void protectedTest( String str )
    {
      System.out.println("in A.protectedTest(String):" + str);
    }
  
    public static void main (String[] args)
    {
      // Test A
      A a1 = new A();
      a1.privateTest();
      // Test B
      String helloStr = "Hello";
      Object helloObj = helloStr;
      B b1 = new B();
      A a2 = b1;             // 這里發(fā)生了什么?困惑1
      b1=a1;               //編譯錯(cuò)誤,困惑2
      b1. privateTest();           //編譯錯(cuò)誤,困惑3
    b1.protectedTest(helloObj);      //輸出結(jié)果?困惑4
      b1.protectedTest(helloStr);       //編譯錯(cuò)誤,困惑5
      a2.protectedTest(helloObj);      //輸出結(jié)果? 困惑6
      a2.protectedTest(helloStr);       //輸出結(jié)果?困惑7 ?
    }
  }
  
  下面,我來(lái)逐個(gè)解釋每一處困惑的地方:
  
  困惑1:
  這里其實(shí)就是子類自動(dòng)上溯造型到父類A。這里a2其實(shí)是指向了一個(gè)B類型的對(duì)象. 我們通常都可以這樣作: A a2=b1, 這樣作的意思實(shí)際上就是讓a2指向了一個(gè)類型B的對(duì)象—在這里就是b1了.
    在java里面,關(guān)于跨類引用,有兩條規(guī)則應(yīng)該記住:
  1. 假如a是類A的一個(gè)引用,那么,a可以指向類A的一個(gè)實(shí)例,或者說(shuō)指向類A的一個(gè)子類.
  2. 假如a是接口A的一個(gè)引用,那么,a必須指向?qū)崿F(xiàn)了接口A的一個(gè)類的實(shí)例.
  所以,根據(jù)這兩個(gè)規(guī)則,我們就不難理解例子中的A a2 = b1是什么意思了.
  
  困惑2:
     A a2 = b1是可以的,但是為什么b1=a1卻是不行? 在這里,我們依然可以套用上面的兩條規(guī)則,我們可以看到,b1是類B的一個(gè)引用,a1既不是類B的實(shí)例,也不是類B的子類的實(shí)例,所以直接b1=a1就出現(xiàn)了編譯錯(cuò)誤.
     假如確實(shí)需要進(jìn)行這樣的轉(zhuǎn)化,我們可以這樣作:b1=(B)a1; 進(jìn)行強(qiáng)制轉(zhuǎn)化,也就是下溯造型. 在java里面,上溯造型是自動(dòng)進(jìn)行的,但是下溯造型卻不是,需要我們自己定義強(qiáng)制進(jìn)行.
    
  困惑3:
     b1. privateTest();編譯不通過(guò)? 這是很顯然的,你可以回顧一下private的定義: 私有域和方法只能被定義該域或方法的類訪問(wèn).  所以,在這里,b1不能訪問(wèn)A的方法privateTest(),即使b1是A的子類的實(shí)例.
     請(qǐng)看下面的例子:
  public class A
  {
   private int two(int i) { return i; }
  }
  class Test extends A {
   public static void main(String[] args) {
   System.out.println(A.two(3));
   }
  }
  
     System.out.println(A.two(3));這行編譯出錯(cuò),顯然,因?yàn)閜rivate方法不能在這個(gè)類之外被訪問(wèn)。
    
  而protected則不同,我們回顧一下protected的定義: 被保護(hù)的域或方法只能被類本身、類的子類和同一 程序包中的類所訪問(wèn)。
  下面是一個(gè)錯(cuò)誤使用protected的例子:
  package cn.org.matrix.test;
  public class ProtectedTest {
   protected void show() {
    System.out.println("I am in protected method");
   }
  }
  
  import cn.org.matrix.test.*;
  public class Test {
    public static void main (String[] args) {
     ProtectedTest obj = new ProtectedTest();
     obj.show();
    }
  }
  因?yàn)樵L問(wèn)權(quán)限問(wèn)題,你會(huì)得到”show() has protected access in test.ProtectedTest”的出錯(cuò)信息. 
  
  困惑4:
    b1.protectedTest(helloObj); 輸出的是”in B.protectedTest(Object):…” 這到底是為什么呢? 為什么jvm能夠確定是輸出B的方法而不是A的方法? 這就和jvm的運(yùn)行機(jī)制有關(guān)系了. 我們上面提到了,a1是一個(gè)A類型的引用,但是指向了一個(gè)B類型的實(shí)例. 在這里,假如jvm根據(jù)引用的類型-在這里就是A 來(lái)定義調(diào)用哪個(gè)方法的話,那么應(yīng)該是調(diào)用A的protectedTest(helloObj).
    然后實(shí)際上不是這樣的,因?yàn)閖vm的動(dòng)態(tài)編譯能力,jvm會(huì)在run-time來(lái)決定調(diào)用哪一個(gè)method,而不是在compile time. 也就是所謂的late-binding(run-time)和early-binding(compile-time).
    
  困惑5:
    b1.protectedTest(helloStr); 這里為什么會(huì)出現(xiàn)編譯錯(cuò)誤? 他可以調(diào)用類B的protectedTest(Object obj)方法啊,把helloStr上溯造型成一個(gè)object就行了啊..或者上溯造型到A然后調(diào)用A的protectedTest(helloStr)方法啊.
    呵呵,問(wèn)題的根源就在于此了,既然有兩種選擇,jvm應(yīng)該選擇那一種?這種不確定性假如交給jvm來(lái)動(dòng)態(tài)決定的話,勢(shì)必帶來(lái)程序的不確定性..雖然java在其他的一些地方也有類似的情形出現(xiàn),比如static變量的循環(huán)定義造成的不確定性,但是,在這里,jvm還是在編譯階段就解決了這個(gè)問(wèn)題.
    所以,我們會(huì)在這一步碰到編譯錯(cuò)誤: “reference to protectedTest is ambiguous; both method protectedTest(java.lang.String) in mytest.A and method   protectedTest(java.lang.Object) in mytest.B match at line 46.
    在這里,我們碰到的是顯式的reference ambiguous錯(cuò)誤,但是,有時(shí)候,隱式的reference ambiguous卻往往是更加的危險(xiǎn).
     在這里,我舉個(gè)例子:
    父類的 源代碼:
    public super
  {
    private void test(int i, long j);
    {
      System.out.println(i+”and”+j);
    }
  }
    子類的源代碼:
  public sub
  {
    private void test(long j, int i);
    {
      System.out.println(i+”and”+j);
    }
  }
  
    子類和父類都用有相同名稱的方法test,參數(shù)類型不同而已.這種情況下,編譯可以被通過(guò).
    但是假如你在另外一個(gè)類中用到了如下代碼:
    Sub sb = new Sub();
    sb.test(100, 3000);  
    你就會(huì)碰到編譯錯(cuò)誤,因?yàn)闆](méi)有確定的指出3000的類型,所以造成reference ambiguous的錯(cuò)誤了.
    
  困惑6:
    a2.protectedTest(helloObj);  
    輸出結(jié)果分別是:”in B.protectedTest(Object)..” 經(jīng)過(guò)上面的解釋,想必大家都能很清楚的知道為什么會(huì)有這兩個(gè)輸出結(jié)果了:a2.protectedTest(helloObj);因?yàn)閖vm的late-binding,所以在run-time的時(shí)候,調(diào)用了B類的方法,雖然在編譯期間a2只是一個(gè)父類A的引用類型。
  
  困惑7:
    a2.protectedTest(helloStr); 為什么這里會(huì)輸出” in A.protectedTest(Object)…”。為什么這里不會(huì)編譯出錯(cuò)?為什么b1. protectedTest(helloStr)會(huì)出錯(cuò)而a2. protectedTest(helloStr)會(huì)出錯(cuò)?我調(diào)用了a2.equals(b1)和a2==b1得到的結(jié)果都是true啊?但是為什么這里出這個(gè)錯(cuò)誤?
    在這里,這個(gè)問(wèn)題是最要害的,也是我們放到最后來(lái)解答的原因。
    首先,回顧一下equals()和==的在java里面的概念,記得有一道scjp

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 砚山县| 嵊泗县| 定陶县| 贵定县| 揭西县| 鸡泽县| 囊谦县| 思南县| 会同县| 白水县| 遂溪县| 绥阳县| 乌恰县| 武宁县| 资兴市| 东明县| 宁南县| 屏东市| 西和县| 太仆寺旗| 湛江市| 家居| 西青区| 英吉沙县| 息烽县| 阜南县| 海淀区| 淮阳县| 安溪县| 襄垣县| 阜南县| 连平县| 宾川县| 惠水县| 四子王旗| 广德县| 南皮县| 珲春市| 天峨县| 乐安县| 江阴市|