Döngünün içindeki veya dışındaki değişkenleri bildirme


236

Aşağıdakiler neden işe yarıyor?

String str;
while (condition) {
    str = calculateStr();
    .....
}

Ancak bunun tehlikeli / yanlış olduğu söylenir:

while (condition) {
    String str = calculateStr();
    .....
}

Değişkenleri döngü dışında bildirmek gerekli mi?

Yanıtlar:


289

Yerel değişkenlerin kapsamı her zaman mümkün olan en küçük olmalıdır.

Örnekte ben presume stredilir değil dışında kullanılan whileiçine bildirerek, çünkü aksi takdirde soruyu soran olmaz, döngü whiledöngü bir seçenek olmazdı derlenemeyecektir.Ancak olmaz çünkü.

Yani, çünkü stredilir değil için mümkün olan en küçük kapsamı, döngünün dışında kullanılamaz strolduğu içinde iken döngü.

Yani, cevap kesinlikle o strkesinlikle süre döngü içinde ilan edilmesi gerektiğini. Hayır ifs, hayır ands, hayır buts.

Bu kuralın ihlal edilebileceği tek durum, herhangi bir nedenle, her saat döngüsünün koddan sıkılması gerektiğinde hayati önem taşıyorsa, bu durumda dış bir kapsamda bir şey başlatmayı ve yerine yeniden kullanmayı düşünebilirsiniz. bir iç kapsamın her yinelemesinde yeniden somutlaştırılır. Bununla birlikte, bu, java'daki dizelerin değişmezliği nedeniyle örneğiniz için geçerli değildir: döngünüzün başında her zaman yeni bir str örneği oluşturulur ve bunun sonunda atılır, bu nedenle orada orada optimizasyon imkanı yoktur.

EDIT: (cevabımda aşağıdaki yorumumu enjekte ediyor)

Her durumda, bir şeyler yapmanın doğru yolu, tüm kodunuzu doğru bir şekilde yazmak, ürününüz için bir performans gereksinimi oluşturmak, nihai ürününüzü bu gereksinime göre ölçmektir ve bunu karşılamıyorsa, işleri optimize edin. Ve genellikle ortaya çıkan şey, programımızın tüm kod tabanınızın her yerine geçmek ve bazı şeyleri değiştirmek ve kesmek yerine programın performans gereksinimlerini karşılamasını sağlayan birkaç yerde bazı güzel ve resmi algoritmik optimizasyonlar sağlamanın yollarını bulmanızdır. Burada ve orada saat döngülerini sıkmak için.


2
Son paragraftaki sorgu: Eğer başka bir değişkense, değişmez olmayan bir String ise, o zaman etkiler mi?
Harry Joy

1
@HarryJoy Evet, elbette, örneğin değişken olan StringBuilder'ı ele alalım. Döngünün her yinelemesinde yeni bir dize oluşturmak için bir StringBuilder kullanırsanız, StringBuilder'ı döngünün dışına ayırarak işleri optimize edebilirsiniz. Ama yine de, bu tavsiye edilen bir uygulama değil. Çok iyi bir sebep olmadan yaparsanız, bu erken bir optimizasyondur.
Mike Nakis

7
@HarryJoy Bir şeyler yapmanın doğru yolu, tüm kodunuzu doğru bir şekilde yazmak , ürününüz için bir performans gereksinimi oluşturmak, nihai ürününüzü bu gereksinime göre ölçmektir ve bunu karşılamıyorsa, bir şeyler optimize edin. Ve biliyor musun? Genellikle tüm kod tabanınızın her yerine gitmek ve burada ve burada saat döngülerini sıkmak için bir şeyler yapmak yerine hile yapacak birkaç yerde bazı güzel ve resmi algoritmik optimizasyonlar sağlayabileceksiniz.
Mike Nakis

2
@MikeNakis düşündüğüm şey çok dar bir kapsamda.
Siten

5
Görüyorsunuz, modern çok gigahertz, çok çekirdekli, pipeline, çok seviyeli bellek önbellek CPU'ları, saat döngüleri hakkında endişelenmenize gerek kalmadan en iyi uygulamalara odaklanmamıza izin veriyor. Dahası, optimizasyon sadece ve sadece gerekli olduğuna karar verilirse ve gerektiğinde, birkaç yüksek lokalize ince ayar genellikle istenen performansa ulaşırsa tavsiye edilir , bu nedenle tüm kodumuzu kirletmeye gerek yoktur. performans adına küçük hack'lerle.
Mike Nakis

293

Bu iki (benzer) örneğin bayt kodunu karşılaştırdım:

Şimdi 1. örneğe bakalım :

package inside;

public class Test {
    public static void main(String[] args) {
        while(true){
            String str = String.valueOf(System.currentTimeMillis());
            System.out.println(str);
        }
    }
}

sonra javac Test.java, javap -c Testalacaksınız:

public class inside.Test extends java.lang.Object{
public inside.Test();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   invokestatic    #2; //Method java/lang/System.currentTimeMillis:()J
   3:   invokestatic    #3; //Method java/lang/String.valueOf:(J)Ljava/lang/String;
   6:   astore_1
   7:   getstatic       #4; //Field java/lang/System.out:Ljava/io/PrintStream;
   10:  aload_1
   11:  invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   14:  goto    0

}

Şuna bakalım 2. örneğe bakalım :

package outside;

public class Test {
    public static void main(String[] args) {
        String str;
        while(true){
            str =  String.valueOf(System.currentTimeMillis());
            System.out.println(str);
        }
    }
}

sonra javac Test.java, javap -c Testalacaksınız:

public class outside.Test extends java.lang.Object{
public outside.Test();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   invokestatic    #2; //Method java/lang/System.currentTimeMillis:()J
   3:   invokestatic    #3; //Method java/lang/String.valueOf:(J)Ljava/lang/String;
   6:   astore_1
   7:   getstatic       #4; //Field java/lang/System.out:Ljava/io/PrintStream;
   10:  aload_1
   11:  invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   14:  goto    0

}

Gözlemler, bu iki örnek arasında hiçbir fark olmadığını göstermektedir . JVM spesifikasyonlarının bir sonucu ...

Ancak en iyi kodlama uygulaması adına, değişkenin mümkün olan en küçük kapsamda bildirilmesi önerilir (bu örnekte, değişkenin kullanıldığı tek yer olduğundan, döngü içinde yer alır).


3
Bu, derleyici optimizasyonunun değil JVM Soecification'ın sonucudur. Bir yöntemin gerektirdiği yığın yuvalarının tümü yönteme girişte tahsis edilir. Bayt kodu bu şekilde belirtilir.
Lorne Marquis

2
@Arhimed, döngü içine koymak için bir neden daha var (veya sadece '{}' bloğu): derleyici, o kapsamda bir miktar aşırı değişken bildirirseniz, başka bir kapsamda değişken için yığın çerçevesine ayrılan belleği yeniden kullanır .
Serge

1
Bir veri nesneleri listesi üzerinden dönüyorsa, o zaman toplu veri için herhangi bir fark yaratacak mı? Muhtemelen 40 bin.
Mithun Khatri

7
Eğer herhangi biri için finalseverler: bildirerek strolarak finaliçinde insidepaket durumda da hiç fark etmez =)
skia.heliou

27

En küçük kapsamdaki nesnelerin bildirilmesi okunabilirliği artırır .

Performans bugünün derleyicileri için önemli değil. (Bu senaryoda)
Bakım açısından 2. seçenek daha iyidir.
Değişkenleri aynı yerde, mümkün olan en dar kapsamda tanımlayın ve başlatın.

As Donald Ervin Knuth anlattı:

"Zamanın yaklaşık% 97'sini küçük verimlilikleri unutmalıyız: erken optimizasyon tüm kötülüklerin köküdür"

ie) bir programcının performans değerlendirmelerinin bir kod parçasının tasarımını etkilemesine izin verdiği durum . Bu bir tasarım neden olabilir gibi temiz değil olabilirdi olarak veya kod, çünkü yanlıştır kod komplike tarafından optimizasyon ve programcı tarafından dikkati dağılır optimize .


1
"2. seçenek biraz daha hızlı performansa sahip" => ölçtünüz mü? Cevaplardan birine göre bayt kodu aynı, bu yüzden performansın nasıl farklı olabileceğini göremiyorum.
assylias

Üzgünüm ama bu gerçekten bir java programının performansını test etmek için doğru bir yol değil (ve yine de sonsuz bir döngü performansını nasıl test edebilirsiniz?)
assylias

Diğer noktalarınıza katılıyorum - sadece performans farkı olmadığını düşünüyorum.
assylias

11

strdış mekanda da kullanmak istiyorsanız ; dışarıda beyan ederim. Aksi takdirde, 2. sürüm gayet iyi.


11

Lütfen güncellenmiş cevaba atlayın ...

Performansı önemseyenler için System.out'u çıkarın ve döngüyü 1 bayt ile sınırlayın. Double (test 1/2) ve String (3/4) kullanarak geçen süreler milisaniye cinsinden aşağıda Windows 7 Professional 64 bit ve JDK-1.7.0_21 ile verilmiştir. Bayt kodları (aşağıda test1 ve test2 için de verilmiştir) aynı değildir. Değişken ve nispeten karmaşık nesnelerle test etmek için çok tembeltim.

çift

Test1 aldı: 2710 ms

Test2 aldı: 2790 msn

String (testlerde double ile string'i değiştirin)

Test3 aldı: 1200 msn

Test4 aldı: 3000 milisaniye

Derleme ve bayt kodu alma

javac.exe LocalTest1.java

javap.exe -c LocalTest1 > LocalTest1.bc


public class LocalTest1 {

    public static void main(String[] args) throws Exception {
        long start = System.currentTimeMillis();
        double test;
        for (double i = 0; i < 1000000000; i++) {
            test = i;
        }
        long finish = System.currentTimeMillis();
        System.out.println("Test1 Took: " + (finish - start) + " msecs");
    }

}

public class LocalTest2 {

    public static void main(String[] args) throws Exception {
        long start = System.currentTimeMillis();
        for (double i = 0; i < 1000000000; i++) {
            double test = i;
        }
        long finish = System.currentTimeMillis();
        System.out.println("Test1 Took: " + (finish - start) + " msecs");
    }
}


Compiled from "LocalTest1.java"
public class LocalTest1 {
  public LocalTest1();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]) throws java.lang.Exception;
    Code:
       0: invokestatic  #2                  // Method java/lang/System.currentTimeMillis:()J
       3: lstore_1
       4: dconst_0
       5: dstore        5
       7: dload         5
       9: ldc2_w        #3                  // double 1.0E9d
      12: dcmpg
      13: ifge          28
      16: dload         5
      18: dstore_3
      19: dload         5
      21: dconst_1
      22: dadd
      23: dstore        5
      25: goto          7
      28: invokestatic  #2                  // Method java/lang/System.currentTimeMillis:()J
      31: lstore        5
      33: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
      36: new           #6                  // class java/lang/StringBuilder
      39: dup
      40: invokespecial #7                  // Method java/lang/StringBuilder."<init>":()V
      43: ldc           #8                  // String Test1 Took:
      45: invokevirtual #9                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      48: lload         5
      50: lload_1
      51: lsub
      52: invokevirtual #10                 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
      55: ldc           #11                 // String  msecs
      57: invokevirtual #9                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      60: invokevirtual #12                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      63: invokevirtual #13                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      66: return
}


Compiled from "LocalTest2.java"
public class LocalTest2 {
  public LocalTest2();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]) throws java.lang.Exception;
    Code:
       0: invokestatic  #2                  // Method java/lang/System.currentTimeMillis:()J
       3: lstore_1
       4: dconst_0
       5: dstore_3
       6: dload_3
       7: ldc2_w        #3                  // double 1.0E9d
      10: dcmpg
      11: ifge          24
      14: dload_3
      15: dstore        5
      17: dload_3
      18: dconst_1
      19: dadd
      20: dstore_3
      21: goto          6
      24: invokestatic  #2                  // Method java/lang/System.currentTimeMillis:()J
      27: lstore_3
      28: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
      31: new           #6                  // class java/lang/StringBuilder
      34: dup
      35: invokespecial #7                  // Method java/lang/StringBuilder."<init>":()V
      38: ldc           #8                  // String Test1 Took:
      40: invokevirtual #9                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      43: lload_3
      44: lload_1
      45: lsub
      46: invokevirtual #10                 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
      49: ldc           #11                 // String  msecs
      51: invokevirtual #9                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      54: invokevirtual #12                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      57: invokevirtual #13                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      60: return
}

GÜNCEL YANIT

Performansı tüm JVM optimizasyonlarıyla karşılaştırmak gerçekten kolay değil. Ancak, bu biraz mümkündür. Google Kaliper'de daha iyi test ve ayrıntılı sonuçlar

  1. Blogdaki bazı ayrıntılar: Bir döngü içinde veya döngüden önce bir değişken bildirmeli misiniz?
  2. GitHub deposu: https://github.com/gunduru/jvdt
  3. Çift kasa ve 100M döngü için Test Sonuçları (ve evet tüm JVM ayrıntıları): https://microbenchmarks.appspot.com/runs/b1cef8d1-0e2c-4120-be61-a99faff625b4

1.759.209 tarihinden önce beyan edilen 2.242.308

  • 1.759.209 ns tarihinden önce
  • 2.242.308 ns içinde

Çifte Beyan için Kısmi Test Kodu

Bu, yukarıdaki kodla aynı değildir. Sadece kukla bir döngü kodlarsanız JVM atlar, bu yüzden en azından bir şey atamanız ve iade etmeniz gerekir. Bu, Kaliper belgelerinde de önerilir.

@Param int size; // Set automatically by framework, provided in the Main
/**
* Variable is declared inside the loop.
*
* @param reps
* @return
*/
public double timeDeclaredInside(int reps) {
    /* Dummy variable needed to workaround smart JVM */
    double dummy = 0;

    /* Test loop */
    for (double i = 0; i <= size; i++) {

        /* Declaration and assignment */
        double test = i;

        /* Dummy assignment to fake JVM */
        if(i == size) {
            dummy = test;
        }
    }
    return dummy;
}

/**
* Variable is declared before the loop.
*
* @param reps
* @return
*/
public double timeDeclaredBefore(int reps) {

    /* Dummy variable needed to workaround smart JVM */
    double dummy = 0;

    /* Actual test variable */
    double test = 0;

    /* Test loop */
    for (double i = 0; i <= size; i++) {

        /* Assignment */
        test = i;

        /* Not actually needed here, but we need consistent performance results */
        if(i == size) {
            dummy = test;
        }
    }
    return dummy;
}

Özet: Dekore edilmiş önce daha iyi performans gösterir - gerçekten küçük - ve en küçük kapsam ilkesine aykırıdır. JVM aslında bunu sizin için yapmalı


Geçersiz test yöntemi ve sonuçlarınızla ilgili herhangi bir açıklama sunmuyorsunuz.
Lorne Marquis

1
@EJP Bu konuya ilgi duyanlar için oldukça açık olmalıdır. Metodoloji, daha faydalı bilgiler sağlamak için PrimosK'un cevabından alınmıştır. Dürüst olmak gerekirse, bu cevabı nasıl geliştireceğime dair hiçbir fikrim yok, belki düzenle'yi tıklayabilir ve bize nasıl düzgün bir şekilde yapılacağını gösterebilirsiniz?
Onur Günduru

2
1) Java Bytecode çalışma zamanında optimize edilir (yeniden sıralanır, daraltılır, vb.), Bu nedenle .class dosyalarında ne yazıldığını umursamayın. 2) 2.8s performans kazanmak için 1.000.000.000 çalışma vardır, bu yüzden çalışma başına yaklaşık 2.8ns güvenli ve uygun programlama tarzı. Benim için açık bir kazanan. 3) Isınma hakkında bilgi vermediğiniz için zamanlamalarınız oldukça işe yaramaz.
Hardcoded

@Kalip ile daha iyi testler / mikro kıyaslama sadece çift ve 100M döngüler için. Sonuçları çevrimiçi, diğer durumlarda düzenlemek çekinmeyin.
Onur Günduru

Teşekkürler, bu 1) ve 3) noktalarını ortadan kaldırır. Ancak zaman, döngü başına ~ 5ns'a kadar çıksa bile, bu hala göz ardı edilecek bir zamandır. Teoride küçük bir optimizasyon potansiyeli vardır, gerçekte döngü başına yaptığınız şeyler genellikle çok daha pahalıdır. Bu nedenle, potansiyel birkaç dakika hatta saatlerce maksimum birkaç saniye olacaktır. Bu tür düşük seviye optimizasyonlarına zaman ayırmadan önce kontrol edebileceğim daha yüksek potansiyele sahip başka seçenekler de vardır (örneğin Çatal / Birleştirme, paralel Akışlar).
Hardcoded

7

Bu sorunun bir çözümü while döngüsünü kapsayan değişken bir kapsam sağlamak olabilir:

{
  // all tmp loop variables here ....
  // ....
  String str;
  while(condition){
      str = calculateStr();
      .....
  }
}

Dış kapsam sona erdiğinde otomatik olarak referans kaldırılır.


6

İçeride, değişken ne kadar az kapsam o kadar iyi görünür.


5

strWhile-after döngüsünü (kapsamla ilgili) kullanmanız gerekmiyorsa , ikinci koşul yani

  while(condition){
        String str = calculateStr();
        .....
    }

yığındaki bir nesneyi yalnızca conditiondoğru olduğunda tanımlarsanız daha iyidir . Yani ihtiyacın olursa kullan


2
İlk varyantta bile, koşul yanlışsa hiçbir nesne oluşturulmadığını unutmayın.
Philipp Wendler

@ Phillip: Evet, haklısın. Benim hatam. Şimdi olduğu gibi düşünüyordum, ne düşünüyorsun?
Cratylus

1
"Yığında bir nesne tanımlamak" Java dünyasında biraz garip bir terimdir. Ayrıca, yığına bir değişken ayırmak genellikle çalışma zamanında bir düğümdür, bu yüzden neden rahatsız edelim? Programcıya yardım etmeyi amaçlamak asıl mesele.
Philipp Wendler

3

Sorunuzu cevaplamak için en iyi kaynak aşağıdaki yazı olacağını düşünüyorum:

Döngüden önce veya döngü içinde değişkenleri bildirme arasındaki fark nedir?

Anladığım kadarıyla bu şey dile bağlı olacaktır. IIRC Java bunu optimize eder, bu yüzden herhangi bir fark yoktur, ancak JavaScript (örneğin) döngüdeki her seferinde tüm bellek tahsisini yapacaktır.Java'da özellikle profilleme yapıldığında ikincisinin daha hızlı çalışacağını düşünüyorum.


3

Birçok insanın işaret ettiği gibi,

String str;
while(condition){
    str = calculateStr();
    .....
}

bundan daha iyi DEĞİLDİR :

while(condition){
    String str = calculateStr();
    .....
}

Bu nedenle, yeniden kullanmıyorsanız değişkenleri kapsamlarının dışında bildirmeyin ...


1
muhtemelen bu şekilde hariç: bağlantı
Dainius Kreivys

2

Wile döngüsünün dışında String str bildirimi, while döngüsünün içinde ve dışında referans gösterilmesini sağlar. While döngüsünün içindeki String str bildirimi, yalnızca while döngüsünün içinde referans gösterilmesini sağlar .


1

Değişkenler mümkün olduğunca kullanıldıkları yere yakın olarak bildirilmelidir.

RAII'yi (Kaynak Edinimi Başlatma) kolaylaştırır.

Değişkenin kapsamını sıkı tutar. Bu, optimize edicinin daha iyi çalışmasını sağlar.



1

strDeğişken kullanılabilir ve hatta kodunun altına infaz ederken sonra hafızada biraz boşluk saklıdır olacaktır.

 String str;
    while(condition){
        str = calculateStr();
        .....
    }

strDeğişken kullanılamaz ve ayrıca hafıza için tahsis edildiği çıkacak strkod aşağıda değişken.

while(condition){
    String str = calculateStr();
    .....
}

İkincisini takip edersek, bu sistem belleğimizi azaltacak ve performansı artıracaktır.


0

Döngünün içinde bildirmek, ilgili değişkenin kapsamını sınırlar. Her şey, değişkenin kapsamına göre projenin gereksinimine bağlıdır.


0

Gerçekten, yukarıda belirtilen soru bir programlama sorunudur. Kodunuzu nasıl programlamak istersiniz? 'STR' e nereden erişmeniz gerekiyor? Yerel olarak global değişken olarak kullanılan bir değişkeni bildirmenin bir faydası yoktur. Programlamanın temelleri inanıyorum.


-1

Bu iki örnek aynı şeyle sonuçlanır. Ancak birincisi, strdeğişkenin while döngüsünün dışında kullanılmasını sağlar ; İkincisi değil.


-1

Bu sorudaki hemen hemen herkes için uyarı: Burada, döngü içinde Java 7 ile bilgisayarımda 200 kat daha yavaş olabileceği örnek kod var (ve bellek tüketimi de biraz farklıdır). Ama bu sadece kapsamla değil, tahsisle de ilgilidir.

public class Test
{
    private final static int STUFF_SIZE = 512;
    private final static long LOOP = 10000000l;

    private static class Foo
    {
        private long[] bigStuff = new long[STUFF_SIZE];

        public Foo(long value)
        {
            setValue(value);
        }

        public void setValue(long value)
        {
            // Putting value in a random place.
            bigStuff[(int) (value % STUFF_SIZE)] = value;
        }

        public long getValue()
        {
            // Retrieving whatever value.
            return bigStuff[STUFF_SIZE / 2];
        }
    }

    public static long test1()
    {
        long total = 0;

        for (long i = 0; i < LOOP; i++)
        {
            Foo foo = new Foo(i);
            total += foo.getValue();
        }

        return total;
    }

    public static long test2()
    {
        long total = 0;

        Foo foo = new Foo(0);
        for (long i = 0; i < LOOP; i++)
        {
            foo.setValue(i);
            total += foo.getValue();
        }

        return total;
    }

    public static void main(String[] args)
    {
        long start;

        start = System.currentTimeMillis();
        test1();
        System.out.println(System.currentTimeMillis() - start);

        start = System.currentTimeMillis();
        test2();
        System.out.println(System.currentTimeMillis() - start);
    }
}

Sonuç: Yerel değişkenin büyüklüğüne bağlı olarak, fark çok büyük değişkenlerde olmasa bile çok büyük olabilir.

Sadece bazen, döngünün dışında veya içinde önemli olduğunu söylemek gerekir.


1
Tabii, ikincisi daha hızlı, ama farklı şeyler yapıyorsun: test1 büyük dizilerle bir sürü Foo Nesnesi yaratıyor, test2 değil. test2 aynı Foo nesnesini tekrar tekrar kullanıyor ve bu da çok iş parçacıklı ortamlarda tehlikeli olabilir.
Hardcoded

Çok iş parçacıklı ortamda tehlikeli ??? Lütfen nedenini açıklayınız. Yerel bir değişken hakkında konuşuyoruz. Yöntemin her çağrısında oluşturulur.
rt15

Foo Nesnesini, verileri eşzamansız olarak işleyen bir işleme geçirirseniz, içindeki verileri değiştirirken işlem yine de Foo örneği üzerinde çalışıyor olabilir. Yan etkileri olması için çok iş parçacıklı olması bile gerekmez. Bu nedenle, örneği hala kimin kullandığını bilmediğinizde örnek yeniden kullanımı oldukça tehlikelidir
Hardcoded

Ps: setValue Yönteminiz olmalıdır bigStuff[(int) (value % STUFF_SIZE)] = value;(2147483649L değerini deneyin)
Hardcoded

Yan etkiler hakkında konuşmak: Yöntemlerinizin sonuçlarını karşılaştırdınız mı?
Hardcoded

-1

Bence nesnenin büyüklüğü de önemli. Projelerimden birinde, uygulamanın bellek yetersiz bir istisna atmasını sağlayan iki boyutlu büyük bir dizi bildirdik ve başlattık. Bunun yerine bildirimi döngüden çıkardık ve diziyi her yinelemenin başında temizledik.


-2

Sen riski var NullPointerExceptionsenin eğer calculateStr()metot bize boş ve sonra Dairenin bir yöntemi çağırmak deneyin.

Daha genel olarak, boş değerli değişkenlere sahip olmaktan kaçının . Bu arada sınıf nitelikleri için daha güçlü.


2
Bu, soru ile ilgili bir yol değildir. NullPointerException (gelecekteki işlev çağrılarında) olasılığı, bir değişkenin nasıl bildirildiğine bağlı değildir.
Desert Ice

1
Ben öyle düşünmüyorum, çünkü soru "Bunu yapmanın en iyi yolu nedir?". IMHO Daha güvenli bir kod tercih ederim.
Rémi Doolaeghe

1
Sıfır NullPointerException.kodu vardır. Bu kod denendiğinde return str;derleme hatasıyla karşılaşır.
Lorne Marquis
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.