2014-04-24 31 views
5

Java sabitini değiştirmem gereken bir durum var.Statik değişkenin değiştirilmesi İlkel Sarıcı ile çalışır ancak ilkel tipte değil

Ben

import java.lang.reflect.Field; 
import java.lang.reflect.Modifier; 

public class Main { 
    public static final Integer FLAG = 44; 

    static void setFinalStatic(Class<?> clazz, String fieldName, Object newValue) throws NoSuchFieldException, IllegalAccessException { 
     Field field = clazz.getDeclaredField(fieldName); 
     field.setAccessible(true); 
     Field modifiers = field.getClass().getDeclaredField("modifiers"); 
     modifiers.setAccessible(true); 
     modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); 
     field.set(null, newValue); 
    } 

    public static void main(String... args) throws Exception { 
     System.out.printf("Everything is %s%n", FLAG); 
     setFinalStatic(Main.class, "FLAG", 33); 
     System.out.printf("Everything is %s%n", FLAG); 
    } 
} 

Yukarıda çalıştırırsanız, ben çıkış aşağıdaki almak çalışma koduna aşağıda bulunmaktadır:

Everything is 44 
Everything is 33 

Ama FLAG değişkeni değiştirirseniz yani

public static final int FLAG = 44; 

int O çalışmıyor. çıktısı:

Everything is 44 
Everything is 44 

o Primitive Tip int ile çalışması için başka bir yolu var mı.

+1

Eğer değiştirmek isterseniz, değişken sonunu neden bildiriyorsunuz? Finali kaldır. Yukarıdaki yoruma – mvmn

+0

+1. Kolay cevap, ints olmayan değişkendir, ama ben –

+0

derleme zaman sabitleri inline ile cevap vermek için yeterli derin java bilmiyorum. Değer çalışma zamanına kadar bilinmiyorsa, değiştirilebilir. Not: 'final' değişkenlerini değiştirmek, karışıklığa neden olduğundan, bunu aslında üretimde yapmazsınız. –

cevap

6

jls-4.12.4

basit tür ve tip String bir değişken, nihai bir derleme sabit ifade (§15.28) başlatıldı olan bir constant variable olarak adlandırılır.

da bölüm 13.1 söyler (§4.12.4) gösterilir sabit bir değere derleme zamanında çözümlenir sürekli değişkenler alanlara (vurgu benim)

3 .. Referanslar . Böyle bir alan için herhangi bir referans kodda bir ikili dosyada bulunmamalıdır (alanı başlatacak kod içeren alan veya sınıf dahilinde olanlar hariç). Böyle bir alan her zaman başlatılmış görünmelidir (§12.4.2); Böyle bir alanın türü için varsayılan başlangıç ​​değeri asla gözlenmemelidir.

O zamanında son referanstan okuyamaz derleyici tarafından kod doğrudan konacaktırsabit değişkenlerden derleme zamanı sabit ifade (o satır içine yerleştirilmiş olacak) anlamına gelir. Eğer Foo.x değeri değil' anlamına gelir Foo sınıf yüklenmemiş demektir Foo sınıfının, statik bloktan hiçbir çıkış görürsünüz main yöntem

class Foo{ 
    static{ 
     System.out.println("test if class will be loaded"); 
    } 
    public static final int x = 42; 
} 

class Bar{ 
    public static void main(String [] args){ 
     System.out.println(Foo.x); 
    } 
} 

sınıf Bar gelen yürütme Örneğin

Bu sınıftan gelmeyin. Aslında Bar bu şekilde Yani zamanında Foo.x bile değişen değeri değeri Bar sınıfında main yöntemde basılmış etkiler olmayacak

class Bar{ 
    public static void main(String [] args){ 
     System.out.println(42); // reference Foo.x will be removed by compiler 
           // and replaced with actual value because 
           // compiler assumes that value can't/shouldn't 
           // change at runtime 
    } 
} 

derlenmiştir.

Bu mekanizmayı değiştiremezsiniz.


Olası bir yol etrafında (onlarderleme zamanı sabiti ifadeleri olmalarını engelleyebilen, hangi derleme sırasında var olamazdı) çalışma zamanı sırasında oluşturulan değerlerle son alanları başlatılıyor olacaktır. Bunun yerine

public static final String x = "foo"; 

ait

public static final int x = new Integer(42); 
+0

Arama yapmak için anahtar kelimeler sabit ifadeler ve sabit değişkenlerdir. –

+0

@SotiriosDelimanolis Düzenlenmiş versiyona veya cevabıma bir göz atabilir misiniz? Ben kesinlikle Java uzmanı değilim, bu yüzden farkında olmadığım bazı basit ama önemli hataları yapabilirim:/ – Pshemo

+0

Yanlış bir şey olduğunu düşünmüyorum. Bu doğru cevap. –

0

Bu statik nihai alanları nedeniyle olur

public static final String x = new String("foo"); 

veya ilkel tipleri durumunda

yerine

public static final int x = 42; 

kullanım gibi kutudan çıkarma kullanmak deneyin ilkel veya St halka tipi derleme sırasında satır içi olsun. FLAG derleme zamanında gerçek değeri ile değiştirilir alır

public static void main(String... args) throws Exception { 
     System.out.printf("Everything is %s%n", 44); 
     setFinalStatic(Main.class, "FLAG", 33); 
     System.out.printf("Everything is %s%n", 44); 
    } 

çünkü ana yöntem irade derleme ve de-derleme sonra şuna benzer.

1
  1. İlkel türler satır içi olsun. Aslında, diğer sınıflara içe aktarıldığında, ilkel olmayan sabitlerin bile kopyalanacağı ve içe aktarılacağı unutulacaktır. Yani orada da işe yaramayacak. Yalnızca dize havuzu ve tamsayı (Integer.valueOf (13)) önbellekleri gibi sabit önbellekler için değerlerinin üzerine yazabilirsiniz.

İlgili konular