Java'nın işaretçileri olmadığını biliyorum, ancak Java programlarının işaretçilerle oluşturulabileceğini ve bunun java konusunda uzman birkaç kişi tarafından yapılabileceğini duydum. Bu doğru mu?
Java'nın işaretçileri olmadığını biliyorum, ancak Java programlarının işaretçilerle oluşturulabileceğini ve bunun java konusunda uzman birkaç kişi tarafından yapılabileceğini duydum. Bu doğru mu?
Yanıtlar:
Java'daki tüm nesneler referanstır ve bunları işaretçiler gibi kullanabilirsiniz.
abstract class Animal
{...
}
class Lion extends Animal
{...
}
class Tiger extends Animal
{
public Tiger() {...}
public void growl(){...}
}
Tiger first = null;
Tiger second = new Tiger();
Tiger third;
Bir boşluğun referansının kaldırılması:
first.growl(); // ERROR, first is null.
third.growl(); // ERROR, third has not been initialized.
Takma Adlandırma Sorunu:
third = new Tiger();
first = third;
Hücreleri Kaybetmek:
second = third; // Possible ERROR. The old value of second is lost.
Bunu, önce saniyenin eski değerine artık gerek olmadığından emin olarak veya başka bir işaretçiye ikinci değeri atayarak güvenli hale getirebilirsiniz.
first = second;
second = third; //OK
İkinciye başka şekillerde bir değer vermenin (NULL, yeni ...) aynı derecede potansiyel bir hata olduğunu ve işaret ettiği nesneyi kaybetmeyle sonuçlanabileceğini unutmayın.
Java sistemi, OutOfMemoryError
yeniyi aradığınızda bir istisna ( ) atar ve ayırıcı istenen hücreyi ayıramaz. Bu çok nadirdir ve genellikle kaçma özyinelemesinden kaynaklanır.
Unutmayın ki, bir dil bakış açısından, nesneleri çöp toplayıcıya bırakmak hiç de hata değildir. Bu sadece programcının bilmesi gereken bir şeydir. Aynı değişken, farklı zamanlarda farklı nesnelere işaret edebilir ve hiçbir işaretçi onlara başvurmadığında eski değerler geri alınacaktır. Ancak programın mantığı nesneye en az bir referans tutmayı gerektiriyorsa, bu bir hataya neden olacaktır.
Acemiler genellikle şu hatayı yaparlar.
Tiger tony = new Tiger();
tony = third; // Error, the new object allocated above is reclaimed.
Muhtemelen söylemek istediğin şey:
Tiger tony = null;
tony = third; // OK.
Yanlış Döküm:
Lion leo = new Lion();
Tiger tony = (Tiger)leo; // Always illegal and caught by compiler.
Animal whatever = new Lion(); // Legal.
Tiger tony = (Tiger)whatever; // Illegal, just as in previous example.
Lion leo = (Lion)whatever; // Legal, object whatever really is a Lion.
C'deki işaretçiler:
void main() {
int* x; // Allocate the pointers x and y
int* y; // (but not the pointees)
x = malloc(sizeof(int)); // Allocate an int pointee,
// and set x to point to it
*x = 42; // Dereference x to store 42 in its pointee
*y = 13; // CRASH -- y does not have a pointee yet
y = x; // Pointer assignment sets y to point to x's pointee
*y = 13; // Dereference y to store 13 in its (shared) pointee
}
Java'daki işaretçiler:
class IntObj {
public int value;
}
public class Binky() {
public static void main(String[] args) {
IntObj x; // Allocate the pointers x and y
IntObj y; // (but not the IntObj pointees)
x = new IntObj(); // Allocate an IntObj pointee
// and set x to point to it
x.value = 42; // Dereference x to store 42 in its pointee
y.value = 13; // CRASH -- y does not have a pointee yet
y = x; // Pointer assignment sets y to point to x's pointee
y.value = 13; // Deference y to store 13 in its (shared) pointee
}
}
GÜNCELLEME: yorumlarda önerildiği gibi, C'nin işaretçi aritmetiğine sahip olduğuna dikkat edilmelidir. Ancak, Java'da buna sahip değiliz.
Java'nın işaretçileri var. Java'da bir nesne oluşturduğunuzda, aslında nesneye bir işaretçi oluşturursunuz; bu işaretçi daha sonra farklı bir nesneye veya konumuna ayarlanabilir null
ve orijinal nesne hala var olacaktır (çöp toplama beklemede).
Java'da yapamayacağınız şey işaretçi aritmetiğidir. Belirli bir bellek adresine başvuruda bulunamaz veya bir işaretçiyi artıramazsınız.
Gerçekten düşük seviyeye geçmek istiyorsanız, bunu yapmanın tek yolu Java Yerel Arayüzü'nü kullanmaktır ; ve o zaman bile, düşük seviyeli kısım C veya C ++ ile yapılmalıdır.
Java'da işaretçi veri türü bulunmadığından, Java'da işaretçi kullanmak imkansızdır. Birkaç uzman bile javada işaretçileri kullanamayacak.
Ayrıca şu son noktaya da bakın: Java Dil Ortamı
Java'da işaretçiler vardır, ancak bunları C ++ veya C'de yapabildiğiniz şekilde işleyemezsiniz. Bir nesneyi ilettiğinizde, o nesneye bir işaretçi iletirsiniz, ancak C ++ ile aynı anlamda değil. Bu nesneye referansta bulunulamaz. Değerlerini yerel erişimcilerini kullanarak ayarlarsanız, Java işaretçi aracılığıyla bellek konumunu bildiği için değişecektir. Ancak işaretçi değişmez. İşaretçiyi yeni bir konuma ayarlamaya çalıştığınızda, bunun yerine diğeriyle aynı ada sahip yeni bir yerel nesne elde edersiniz. Orijinal nesne değişmez. İşte farkı göstermek için kısa bir program.
import java.util.*;
import java.lang.*;
import java.io.*;
class Ideone {
public static void main(String[] args) throws java.lang.Exception {
System.out.println("Expected # = 0 1 2 2 1");
Cat c = new Cat();
c.setClaws(0);
System.out.println("Initial value is " + c.getClaws());
// prints 0 obviously
clawsAreOne(c);
System.out.println("Accessor changes value to " + c.getClaws());
// prints 1 because the value 'referenced' by the 'pointer' is changed using an accessor.
makeNewCat(c);
System.out.println("Final value is " + c.getClaws());
// prints 1 because the pointer is not changed to 'kitten'; that would be a reference pass.
}
public static void clawsAreOne(Cat kitty) {
kitty.setClaws(1);
}
public static void makeNewCat(Cat kitty) {
Cat kitten = new Cat();
kitten.setClaws(2);
kitty = kitten;
System.out.println("Value in makeNewCat scope of kitten " + kitten.getClaws());
//Prints 2. the value pointed to by 'kitten' is 2
System.out.println("Value in makeNewcat scope of kitty " + kitty.getClaws());
//Prints 2. The local copy is being used within the scope of this method.
}
}
class Cat {
private int claws;
public void setClaws(int i) {
claws = i;
}
public int getClaws() {
return claws;
}
}
Bu, Ideone.com'da çalıştırılabilir.
Java, C'nin sahip olduğu gibi işaretleyicilere sahip değildir, ancak yığın üzerinde değişkenler tarafından "referans verilen" yeni nesneler oluşturmanıza izin verir. İşaretçilerin eksikliği, Java programlarının bellek konumlarına yasa dışı bir şekilde başvurmasını engellemek ve ayrıca Çöp Toplama işleminin Java Sanal Makinesi tarafından otomatik olarak gerçekleştirilmesini sağlamaktır.
Güvenli olmayan sınıfını kullanarak adresleri ve işaretçileri kullanabilirsiniz. Ancak adından da anlaşılacağı gibi, bu yöntemler GÜVENLİ DEĞİLDİR ve genellikle kötü bir fikirdir. Yanlış kullanım JVM'nizin rastgele ölmesine neden olabilir (aslında aynı sorun işaretçileri C / C ++ 'da yanlış kullanır)
İşaretçilere alışkın olsanız ve onlara ihtiyaç duyduğunuzu düşünseniz de (çünkü başka bir şekilde kodlamayı bilmiyorsunuz), olmadığını göreceksiniz ve bunun için daha iyi olacaksınız.
Teknik olarak, tüm Java nesneleri işaretçilerdir. Yine de tüm ilkel türler değerlerdir. Bu işaretçilerin manuel kontrolünü almanın bir yolu yok. Java sadece dahili olarak referansla geçiş kullanır.
Gerçekten değil, hayır.
Java'nın işaretçileri yoktur. Eğer gerçekten istiyorsan, yansıma gibi bir şey etrafında inşa ederek onları taklit etmeye çalışabilirsin, ama hiçbir faydası olmadan işaretçilerin tüm karmaşıklığına sahip olacaktı .
Java'nın işaretçileri yoktur çünkü onlara ihtiyacı yoktur. Bu sorudan ne tür cevaplar bekliyordunuz, yani derinlerde onları bir şey için kullanabileceğinizi mi umuyordunuz yoksa bu sadece merak mıydı?
Java'daki tüm nesneler, ilkel öğeler hariç işlevlere referans kopyası ile aktarılır.
Aslında bu, nesnenin kendisinin bir kopyası yerine orijinal nesneye işaretçinin bir kopyasını gönderdiğiniz anlamına gelir.
Bunu anlamak için bir örnek istiyorsanız lütfen yorum bırakın.
swap
Java'da iki nesneyi değiştirecek bir işlev yazamazsınız .
Diğerlerinin de söylediği gibi, kısa cevap "Hayır" dır.
Elbette, Java işaretçileriyle oynayan JNI kodu yazabilirsiniz. Neyi başarmaya çalıştığınıza bağlı olarak, belki bu sizi bir yere götürür ve belki de olmaz.
Bir dizi oluşturarak ve diziye dizinler ile çalışarak her zaman noktaları simüle edebilirsiniz. Yine, neyi başarmaya çalıştığınıza bağlı olarak, bu yararlı olabilir veya olmayabilir.
Godfrey Nolan tarafından yazılan Decompiling Android adlı kitaptan
Güvenlik, işaretçilerin Java'da kullanılmadığını, böylece bilgisayar korsanlarının bir uygulamadan çıkıp işletim sistemine giremeyeceğini belirtir . İşaretçi olmaması, başka bir şeyin - bu durumda, JVM'nin - bellek ayırma ve boşaltma ile ilgilenmesi gerektiği anlamına gelir. Bellek sızıntıları da geçmişte kalmalı, yoksa teori öyle devam ediyor. C ve C ++ ile yazılmış bazı uygulamalar, bir elek gibi bellek sızdırmasıyla ünlüdür çünkü programcılar, istenmeyen belleği uygun zamanda boşaltmaya dikkat etmezler - bunu okuyan hiç kimse böyle bir günahtan suçlu sayılmaz. Çöp toplama aynı zamanda programcıları daha verimli hale getirmeli ve bellek sorunlarının giderilmesi için daha az zaman harcanmalıdır.
değişmez değerler için de işaretçileriniz olabilir. Bunları kendin uygulamalısın. Uzmanlar için oldukça basit;). Bir int / object / long / byte dizisi kullanın ve işte işaretçileri uygulamak için temel bilgilere sahipsiniz. Artık herhangi bir int değeri o dizinin int [] işaretçisi olabilir. İmleci artırabilir, işaretçiyi küçültebilir, işaretçiyi çarpabilirsiniz. Gerçekten de işaretçi aritmetiğine sahipsiniz! 1000 int öznitelik sınıflarını uygulamanın ve tüm öznitelikler için geçerli olan genel bir yönteme sahip olmanın tek yolu budur. İnt [] yerine bayt [] dizisi de kullanabilirsiniz.
Bununla birlikte, Java'nın referans olarak değişmez değerleri geçirmenize izin vermesini diliyorum. Çizgiler boyunca bir şey
//(* telling you it is a pointer)
public void myMethod(int* intValue);
Tüm java nesneleri göstericidir çünkü adresi tutan bir değişken işaretçi ve nesne tutma adresi olarak adlandırılır. Yani nesne işaretçi değişkenidir.