2016-03-16 3 views
0
class A{ 
    int foo=10; 
} 
class B extends A{ 
    int foo=10; 
} 
class Test{ 
    public static void main(String [] args){ 
     A a=new B(); 
     System.out.println(a.foo); 
     //System.out.println(a.getClass()); 
    } 
} 

В этом случае выводится 10. Если я не ошибаюсь, это связано с тем, что переменная a имеет тип A, а назначение переменной - статическое связывание, а статическое связывание выполняется во время компиляции, просматривая тип переменной. Так как здесь a имеет тип A, то вызывается int foo. Однако, когда я называюОбъект refrence and type casting in java

System.out.println(a.getClass()); 

, то это дает класс B, то есть a имеет тип B. Я смущен этим. Пожалуйста, объясните мне a, какой тип и как напечатан int foo. Но, посмотрев на этот код

class A{} 

class B extends A{} 

class Test{ 
    public static void main(String [] args){ 
     B b=new B(); 
     A a=b; 
     B b1=(B)a; // compiles and run fine (a is of type B) 
    } 
} 

Как это возможно? Что тут происходит? Первый b имеет тип B, затем во второй строке a становится типа A, так как A a=.. написано, но a.getClass() указывает, что он имеет тип B. Как? Если a имеет тип B, то почему он вызывает int foo в первом примере? Пожалуйста, объясните оба примера.

Кроме того, действительно ли ссылки на изменение кастинга или какие-либо другие вещи?

+0

объект в куче остается тем же самым. То, как вы обращаетесь к нему, меняется. –

+1

Вы затеняете переменную, для переменной нет переопределения. btw нет другого возможного выхода, тогда 10;). В этом случае вы просто получаете доступ к переменной 'foo' из' A', потому что именно так определяется ваша переменная. Поскольку для переменных нет переопределения, тип объявления важен, если вы напрямую обращаетесь к переменным от типа. – SomeJavaGuy

+1

* В этом случае 10 выводится *: что еще он может напечатать? Вы вводите в заблуждение объявленный тип переменной и время выполнения, конкретный тип объекта, на который ссылается эта переменная. Объект никогда не меняет тип. Вызов getClass() возвращает его конкретный тип. Но две переменные разных типов могут относиться к одному и тому же объекту, потому что B ** является ** A. –

ответ

1

Важно, что Java имеет только примитивные и ссылочные типы переменных. Это означает, что когда вы пишете

A a = 

a это просто ссылка на объект (или нуль) не является объектом.

Когда вы

A a = new B(); 

нет литая здесь, ни одна работа не будет сделано, ни один объект не был нанесен вред или изменен.

Когда вы вызываете метод экземпляра в классе, он вызывает метод для класса объекта.

Object o = new B(); 
assert o.getClass() == B.class; 

длиннее пример

B b = new B(); 
A a = b; 
assert a == b; // always true as they point to the same object. 
assert b.getClass() == B.class; 
// so it makes sense that since a == b 
assert a.getClass() == B.class; 

ссылка изменения отливки типа или делать какие-либо другие вещи?

Он изменяет тип ссылки и не выполняет другие действия, такие как изменение типа объекта.

метода последующего наследование, однако поля следовать тип ссылки в поле не может быть отменена, она может быть скрыта только.

B b = новый B(); A x = b; B b1 = (B) x; // компилируется и выполняется нормально (х типа б) в этой строке, когда х имеет тип

правильно, и вы не смогли бы (B)x исключением случаев, когда x была ссылка на B переменных x является A, что означает, что он должен указывать на объект A или подкласс класса A, например B вы можете написать

B b = new B(); 
A x = b; 
assert x == b; // they still point to the same object. 
B b1 = (B) x; 
assert b1 == b; // same object 
assert x == b1; // same object. 

Нет новых объектов не создаются, ни объект изменился.

+0

B b = новый B(); \t \t A x = b; \t \t B b1 = (B) x; // компилируется и выполняется нормально (x имеет тип b) в этой строке, когда x имеет тип –

+0

@MayankSingh правильно, и вы не сможете '(B) x', если' x' не является ссылкой на ' B' Я обновил свой ответ –

+0

A a = new B() // в этом случае a имеет тип A или B –

0

Довольно просто, почему он печатает foo из A, поскольку a определяется как A. Поскольку для переменных нет переопределения, вы просто присоединяетесь к переменным, которые доступны для типа, объявленного переменной, который в этом случае равен A.

public static void main(String[] args) { 
    A a = new A(); 
    System.out.println(a.foo); // prints the foo of A, since a is of the type A 
    A b = new B(); 
    System.out.println(b.foo); // prints the foo of A, since b is of the type A 
    B c = new B(); 
    System.out.println(c.foo); // prints the foo of B, since c is of the type B 
} 

В конце концов, это называется затенением того, что вы там делаете. У вашего класса B есть переменная с тем же именем, что и A. Так как они не Overridable вы можете скрыть foo от A, если переменная имеет тип B, где вы обращаетесь foo из B

+0

в коде A a = (B) x ... (B) x означает, что мы хотим перевести x в B. Это значит, что мы хотим, чтобы x была переменной refrence типа B. ?? –

+0

@MayankSingh нет, это означает, что 'x' на самом деле является экземпляром' B' или любого его подкласса. Это, скорее всего, имеет смысл только в том случае, если 'x' будет иметь тип' Object' на этом довольно крошечном примере. Но я не понимаю, откуда у вас этот кусок кода. – SomeJavaGuy

+0

, но некоторые из них я читал, что литье типа обычно означает, что мы меняем ссылку –

0

Ваш вопрос связан с Javas полиморфного поведения и динамический (поздно) против статического (раннего) связывания. Доступ ко всем переменным-членам в Java осуществляется после статической привязки. Это означает, что в этом случае у вас нет полиморфизма. Методы экземпляра динамически связаны. Метод экземпляра, используемый для вызова, будет определяться классом объекта, а не ссылочным типом. Например:

public class Main { 

    static class A{ 
     String foo="A"; 

     public String getFoo() { 
      return foo; 
     } 
    } 
    static class B extends A{ 
     String foo="B"; 

     @Override 
     public String getFoo() { 
      return foo; 
     } 
    } 

    public static void main(String[] args) throws Exception { 

     A a=new B(); 
     System.out.println(a.foo); // prints A 
     System.out.println(a.getFoo()); // prints B 
     System.out.println(a.getClass()); // prints Main$B 
    } 
} 

Late binding

Early Binding

Polymorphism