Diferența dintre asignările de tip dinamic și static în Java (Programare, Java, Moștenire, Dinamic, Static)

user3088470 a intrebat.

Având în vedere următoarea ierarhie de clase, care sunt tipurile dinamice și statice pentru următoarele declarații?

Ierarhia claselor:

class Alpha {}

class Beta extends Alpha {}

class Gamma extends Alpha {}

class Epsilon extends Alpha{}

class Fruit extends Gamma{}

class Golf extends Beta {}

class Orange extends Fruit{}

Pentru fiecare dintre următoarele declarații, tipul static? Tip dinamic?

Fruit f = new Fruit();
Alpha a = f;
Beta b = f;
a = b;
Gamma g = f;

Răspunsurile/întrebările mele
Înțeleg că Fruit f = new Fruit() va fi atât de tip static, cât și de tip dinamic Fructe.
Alpha a = f; Va fi de tip Alpha la compilare (static) și de tip Fruit la execuție (dinamic).
Gamma g = f; Va fi de tip Gamma în momentul compilării (static) și de tip Fruit în momentul execuției (dinamic).
Cu toate acestea, nu cunosc celelalte două răspunsuri. Beta b = f este o instanță în care două subclase ale aceleiași superclase sunt atribuite una alteia, așa că nu sunt sigur dacă va fi de tip Beta sau de tip Alfa la compilare (static). Iar a = b este o atribuire după declarare, așa că nu sunt sigur care ar fi răspunsul pentru aceasta. Cineva vă rog să mă ajute, mulțumesc!

Comentarii

  • Nu înțeleg cum ceva poate fi atât static cât și dinamic, dar poate gândesc într-un alt context. –  > Por MxLDevs.
  • Fie ai o greșeală de scriere în codul pe care l-ai postat, fie postezi un cod necompilabil. Ar trebui să Gamma extend Beta în loc de Alpha? –  > Por Sotirios Delimanolis.
  • Nu creați niciodată decât un Fruit iar acest tip este singurul tip care va exista vreodată la momentul execuției. Nu-și va schimba tipul atunci când adăugați referințe la el. –  > Por zapl.
  • cod de probă încărcat ideone.com/wdk7oa După cum am menționat, nu este compilabil Main.java:15: error: incompatible types Beta b = f; –  > Por Boris Ivanov.
5 răspunsuri
luis.espinal

Scriu acest lucru în grabă, așa că pls scuzați orice greșeli de scriere (le voi repara mai târziu când voi avea ocazia).

Înțeleg că Fructul f = new Fruit() va fi atât de tip static cât și de tip dinamic Fruct.

Cred că confundați puțin termenii static and dynamic tipuri cu tipurile de timp de compilare și de timp de execuție (sau ca în C++ când atribui adresa unui obiect de tip A unui pointer de tip B, B fiind clasa părinte a lui A.).

Cu excepția trucurilor de reflecție, în Java nu există tipărire dinamică. Totul este tipizat static în momentul compilării. Tipul unui obiect în momentul execuției este același cu cel la care a fost compilat.

Ceea ce se întâmplă este că confundați referințele la obiecte (a, b, c, f) cu obiectele reale instanțiate în heap (orice lucru creat cu new.)

În Java, f este o referință la un obiect, nu obiectul în sine. În plus, tipul de referință f este Fruit and sub-classes of it. Obiectul (new Fruit()) pe care i-l atribuiți se întâmplă să fie de tipul Fruit.

Acum, toate celelalte referințe din codul de exemplu, a este de tip reference to A and sub-classes of it; b este de tip reference to B and sub-classes of it; etc, etc.

Țineți minte acest lucru, deoarece este foarte important.

Alpha a = f; Va fi de tip Alpha la compilare (static) și de tip Fruit la execuție (dinamic).

a este de tipul „referință la tipul A și la subclase”. f este de tipul „referință la tipul Fruit și la subclase”.

Obiectul către care indică f este de tip „Fruit”. Atunci când spuneți „a = f” nu atribuiți „f” lui „a”. Spuneți „a va face acum referință la obiectul la care f face referire în prezent”.

Deci, după această atribuire, ce este a se face referire? Obiectul de tip Fruit referința obiectului f la care se referea în momentul atribuirii.

Nu uitați, a, b, g, f, nu sunt obiecte. Acestea sunt referințe sau mânere către obiecte create într-un fel sau altul cu ajutorul aplicației new operator.

O variabilă de referință, cum ar fi a, b sau f, este o bestie diferită de obiectele create cu new. Dar se întâmplă ca prima să poată indica spre cea din urmă.

Tipul obiectului creat cu new în timpul execuției este același cu cel determinat la compilare.

Gamma g = f; Va fi de tipul Gamma la compilare (static) și de tipul Fruit la execuție (dinamic).

La fel ca mai sus. Variabila g este o referință la un obiect de tip reference to type Gamma and sub-classes. În această atribuire, g este făcută să indice același obiect indicat de f. Care este tipul acestui obiect? Același tip dat la compilare: Fructe.

Cu toate acestea, nu cunosc celelalte două răspunsuri. Beta b = f este o instanță în care două subclase ale aceleiași superclase sunt atribuite una alteia, așa că nu sunt sigur dacă ar fi de tip Beta sau de tip Alfa la compilare (static).

b este de tip reference to type Beta and sub-classes of it. Obiectul pe care îl indică după atribuire b = f este de tip Fruit, tipul pe care îl avea în momentul compilării.

  1. Tipul referințelor obiectelor a, b, g și f este determinat la compilare. Acestea sunt tipizate static și nu se modifică în timpul execuției.

  2. Tipul unui obiect creat cu new este, de asemenea, determinat în momentul compilării. Acestea sunt, de asemenea, tipizate static și nu se modifică în timpul execuției.

  3. Obiectele, referințele de obiect stuff a, b, g și f, indică spre la momentul execuției, care este determinată de faptul că declarațiile sunt considerate valide de către compilator. Atribuțiile se pot schimba, dar acest lucru nu are nimic de-a face cu faptul că referințele de obiect sau obiectul în sine sunt tipizate static sau dinamic.

Dacă doriți să vedeți o distincție clară între tipizarea dinamică și cea statică, luați în considerare următoarele:

// Java, statically typed.
int x = 3;
x = 5; // good
x = "hi"; // compiler error

## Ruby, dynamically typed
x = 3 # ok
x = 5 # ok
x = "hi" # still ok

Apoi, există o distincție între limbajele puternic tipizate și cele slab tipizate (ambele pot fi tipizate dinamic.) Există o mulțime de literatură pe această temă.

Sper să vă fie de ajutor.

Comentarii

  • mulțumesc pentru un răspuns atât de bun : @luis.espinal, puteți preciza ce înțelegeți mai exact prin „referință la tipul X și sub-classes din acesta” ? mulțumesc anticipat. –  > Por Mohan Sharma.
  • Fructul nu este o subclasă a lui Beta, deci ce sens are b = f ? Se pare că nu ar trebui să se compileze. –  > Por redfiloux.
meriton

tipurile dinamice și statice pentru următoarele instrucțiuni

Erm, o instrucțiune nu are un tip, cel puțin nu există o astfel de noțiune în specificația limbajului Java. Specificația definește două tipuri diferite de tipuri: tipul tipul declarat al unei variabile, al unui câmp sau al unui parametru și tipul clasa în timp de execuție a unui obiect.

După cum indică și numele, tipul tipul declarat al unei variabile, al unui câmp sau al unui parametru este tipul pe care îl menționați în declarație. De exemplu, declarația Foo bar; declară o variabilă numită bar de tip Foo.

Adresa clasa de execuție a unui obiect este determinată de instanța de clasă sau de expresia de creare a tabloului utilizată pentru a-l construi și rămâne aceeași pe toată durata de viață a obiectului respectiv.

Așadar, codul:

Integer i = 1;
Number n = i;
Object o = n;

declară 3 variabile de tipul Integer, Number și Object, respectiv , care se referă toate la un singur obiect cu clasa de execuție Integer.

JB Nizet

Tipul concret, de execuție, al lui f este Fructe (după cum ați afirmat corect în întrebarea dumneavoastră).

Prin urmare, Beta b = f; initilizează o variabilă al cărei tip declarat, la compilare, este Beta și al cărei tip la execuție este Fructe. Totuși, acest lucru nu se va compila, deoarece tipul în timp de compilare al lui f este Fruit, iar Fruit nu este o subclasă a lui Beta, deci f nu poate fi atribuită unei variabile de tip Beta.

În a = b;, b, al cărui tip de execuție este Fruit (vezi mai sus) este atribuit variabilei a, declarată ca Alpha a. Deci aeste Alpha, iar tipul său în timp de execuție este Fruit.

Comentarii

  • Dar Fruit nu derivă din Betadeci Beta b = f; nu se compilează –  > Por Henry.
Clive Ferreira

În primul rând pentru a clarifica tipul „Variabilă de referință”:

Object obj;

Nu indică nimic și variabila de referință obj nu ar avea niciun tip.Acum

Object obj = new String();
System.out.println(obj.getClass());//prints class java.lang.String

obj indică un șir de caractere și variabila de referință obj are tipul String.

Ideea este că Java este un limbaj cu tipare statică și toate variabilele de tip referință au un tip atribuit la compilare. Variabila de referință obj poate indica un alt obiect, atâta timp cât acesta este o subclasă de Object. În acest caz, aproape orice. Luați în considerare

Object obj = new String();
System.out.println(obj.getClass());//prints class java.lang.String
Number num = new Byte((byte)9);
obj = num;
System.out.println(obj.getClass());//prints class java.lang.Byte

În timpul execuției, la fel ca la compilare, variabila de referință obj are tipul Byte.

Pentru mine, tipul static/dinamic al unui obiect are de-a face cu moștenirea. Mai exact, mecanismul de suprapunere. Cunoscut și sub numele de polimorfism dinamic și Late Binding.

Luați în considerare suprascrierea funcției equals() din clasa Object:

public class Types {

    @Override
    public boolean equals(Object obj){
        System.out.println("in class Types equals()");
        return false;//Shut-up compiler!
    }

    public static void main(String[] args){
        Object typ = new Types();
        typ.equals("Hi");//can do this as String is a subclass of Object
    }
}

Acum știm că tipul variabilei de referință typ este Types.

Object typ = new Types();

Când vine vorba de

typ.equals("Hi");

Așa cred că gândește compilatorul.

În cazul în care equals() este

1.NU este static și final, ceea ce este.

2.Referită dintr-o clasă de bază (mai multe despre acest lucru în curând).

atunci compilatorul amână metoda care va fi apelată la JVM. Metoda exactă care este invocată depinde de Tipul dinamic(mai multe în curând) al variabilei care apelează metoda. În cazul nostru, variabila de referință este typ.Acest lucru este cunoscut sub numele de Invocare dinamică a metodei.

Acum se face referire la o clasă de bază: Din codul de mai sus

Object typ = new Types();
typ.equals("Hi");

Type Object ar putea fi considerat ca fiind tipul de bază al lui typ, cunoscut și sub numele de tip static a unei variabile de referință, iar ecuația equals() este referită de la tipul de bază, în acest caz Object.

Dacă am avea

Types typ = new Types();

Nu ar exista nicio referință de la un tip de bază și, prin urmare, nicio invocare dinamică a metodei.

Acum, la tip dinamic al unei variabile de referință.

Object typ = new Types();
typ.equals("Hi");

tip dinamic a tipului este Tipuri și, în conformitate cu Invocarea dinamică a metodelor, funcția equals() din clasa Tipuri va fi apelată în timpul execuției.

Să presupunem, de asemenea, că avem o altă clasă care extinde Types, TypesSubClass.And TypesSubClass are, de asemenea, o clasă suprascrisă equals(). În acest caz,

Object typ = new TypesSubClass();
typ.equals("Hi");

ar face ca Tip dinamic de tip TypesSubClass, iar Equals() din TypesSubClass ar fi apelat în timpul execuției.

Ca să fiu sincer, eu personal nu am știut de ce avem nevoie de toate acestea și am postat o întrebare referitoare la acest lucru. verificați

Care este motivul care stă la baza rezoluției dinamice a metodelor într-un limbaj cu tipare statică, cum este Java?

Adjit

Ar trebui să aruncați o privire la acest articol: http://www.sitepoint.com/typing-versus-dynamic-typing/

Tiparea statică este atunci când un limbaj nu cere ca variabila să fie inițializată.

De ex.

/* C code */ 
static int num, sum; // explicit declaration 
num = 5; // now use the variables 
sum = 10; 
sum = sum + num;

Tiparea dinamică este atunci când un limbaj cere ca variabila să fie inițializată.

De exemplu.

/* Python code */ 
num = 10 // directly using the variable

Comentarii

  • Deci, deoarece Java cere ca o variabilă locală să fie atribuită definitiv înainte de a fi utilizată, nu este tipizată static? –  > Por meriton.
  • @meriton Java este un limbaj static. Deci, într-un limbaj dinamic poți spune pur și simplu num = 10 spre deosebire de un limbaj static în care trebuie să spui int num; num = 10 Dar faptul că poți spune pur și simplu int num; și apoi să-i dai o valoare mai târziu îl face static. Gândiți-vă la asta în felul următor… când spuneți int num; programul dvs. stabilește un anumit loc în memorie și îl desemnează drept variabilă num deci acum, de fiecare dată când atribuiți o valoare la num aceasta va fi întotdeauna plasată în spațiul de memorie care i-a fost alocat. Prin urmare, static –  > Por Adjit.
  • Cred că vreți să spuneți că un sistem de tip static necesită specificarea unui tip pentru fiecare variabilă în declarația sa. Acest lucru nu este chiar adevărat. Un sistem static de tipuri necesită ca fiecare variabilă să să aibă un tip, modul în care compilatorul determină acel tip este irelevant. În special, C# este considerat un limbaj cu tipare statică, chiar dacă puteți cere compilatorului să deducă tipul unei variabile prin utilizarea funcției var cuvântul cheie. –  > Por meriton.