mboost-dp1
Hvordan man kan fucke selv simple ting op [programmerings relateret]
- Forside
- ⟨
- Forum
- ⟨
- Tagwall
(inspireret af et spørgsmål på LinkedIn lavede jeg lidt reasearch)
Man skulle tro at det at lave 2 Integer variable og sammenligne dem med == var så simpelt at det ikke er muligt at lave ged i den.
Men intet er umuligt i Java. :-)
Kode:
Det er ikke avanceret kode.
Test:
C:\Work>java IntFun
new 100 100 : == gives false, equals give true
valueOf 100 100 : == gives true , equals give true
autoboxing 100 100 : == gives true , equals give true
new 200 200 : == gives false, equals give true
valueOf 200 200 : == gives false, equals give true
autoboxing 200 200 : == gives false, equals give true
C:\Work>java -XX:AutoBoxCacheMax=500 IntFun
new 100 100 : == gives false, equals give true
valueOf 100 100 : == gives true , equals give true
autoboxing 100 100 : == gives true , equals give true
new 200 200 : == gives false, equals give true
valueOf 200 200 : == gives true , equals give true
autoboxing 200 200 : == gives true , equals give true
C:\Work>java -Djava.lang.Integer.IntegerCache.high=500 IntFun
new 100 100 : == gives false, equals give true
valueOf 100 100 : == gives true , equals give true
autoboxing 100 100 : == gives true , equals give true
new 200 200 : == gives false, equals give true
valueOf 200 200 : == gives true , equals give true
autoboxing 200 200 : == gives true , equals give true
C:\Work>java -XX:AutoBoxCacheMax=50 IntFun
new 100 100 : == gives false, equals give true
valueOf 100 100 : == gives true , equals give true
autoboxing 100 100 : == gives true , equals give true
new 200 200 : == gives false, equals give true
valueOf 200 200 : == gives false, equals give true
autoboxing 200 200 : == gives false, equals give true
C:\Work>java -Djava.lang.Integer.IntegerCache.high=50 IntFun
new 100 100 : == gives false, equals give true
valueOf 100 100 : == gives true , equals give true
autoboxing 100 100 : == gives true , equals give true
new 200 200 : == gives false, equals give true
valueOf 200 200 : == gives false, equals give true
autoboxing 200 200 : == gives false, equals give true
WTF. Forklaring følger.
1) I Java er int en simpel value type, mens Integer er den tilsvarende objekt referance type.
2) I Java er test for lighed:
val == val : er værdierne ens
obj == obj : er referancerne ens
obj.equals(obj) : er værdierne ens
3) Visse objekt referance typer som wrapper simple data typer herunder Integer klassen har en lille intern cache så den kan genbruge objekter - i stedetfor at have 10 Integer objekter med værdien 1 så har man kun 1 Integer objekt med værdien 1.
[ja - Integer er immutable, så ikke noget problem med flere referancer]
4) Default cacher Integer kun værdier -128..127
5) Integer o = new Integer(v);
bruger ikke denne cache.
Integer o = Integer.valueOf(v);
og
Integer o = v;
bruger denne cache.
6) Den default kan ændres på 2 måder:
java -XX:AutoBoxCacheMax=n ...
java -Djava.lang.Integer.IntegerCache.high=n ...
7) Men den kan kun sættes op. Man kan ikke sætte værdien lavere en 127. Man kan godt angive en værdi lavere end 127 men de ignoreres og Java bruger 127.
Suk.
1-2 er vel OK sådan er Java defineret og andre sprog har også deres regler for den slags.
3-4 er grimt men har et fornuftigt formål (bedre performance)
5-7 er håbløst - hvad pokker tænker de på
Man skulle tro at det at lave 2 Integer variable og sammenligne dem med == var så simpelt at det ikke er muligt at lave ged i den.
Men intet er umuligt i Java. :-)
Kode:
public class IntFun
{
public static void test(String lbl, Integer v1, Integer v2) {
System.out.printf("%-10s %d %d : == gives %-5b, equals give %-5b\n", lbl, v1, v2, v1 == v2, v1.equals(v2));
}
public static void test(int v) {
test("new", new Integer(v), new Integer(v));
test("valueOf", Integer.valueOf(v), Integer.valueOf(v));
test("autoboxing", v, v);
}
public static void main(String[] args) {
test(100);
test(200);
}
}
Det er ikke avanceret kode.
Test:
C:\Work>java IntFun
new 100 100 : == gives false, equals give true
valueOf 100 100 : == gives true , equals give true
autoboxing 100 100 : == gives true , equals give true
new 200 200 : == gives false, equals give true
valueOf 200 200 : == gives false, equals give true
autoboxing 200 200 : == gives false, equals give true
C:\Work>java -XX:AutoBoxCacheMax=500 IntFun
new 100 100 : == gives false, equals give true
valueOf 100 100 : == gives true , equals give true
autoboxing 100 100 : == gives true , equals give true
new 200 200 : == gives false, equals give true
valueOf 200 200 : == gives true , equals give true
autoboxing 200 200 : == gives true , equals give true
C:\Work>java -Djava.lang.Integer.IntegerCache.high=500 IntFun
new 100 100 : == gives false, equals give true
valueOf 100 100 : == gives true , equals give true
autoboxing 100 100 : == gives true , equals give true
new 200 200 : == gives false, equals give true
valueOf 200 200 : == gives true , equals give true
autoboxing 200 200 : == gives true , equals give true
C:\Work>java -XX:AutoBoxCacheMax=50 IntFun
new 100 100 : == gives false, equals give true
valueOf 100 100 : == gives true , equals give true
autoboxing 100 100 : == gives true , equals give true
new 200 200 : == gives false, equals give true
valueOf 200 200 : == gives false, equals give true
autoboxing 200 200 : == gives false, equals give true
C:\Work>java -Djava.lang.Integer.IntegerCache.high=50 IntFun
new 100 100 : == gives false, equals give true
valueOf 100 100 : == gives true , equals give true
autoboxing 100 100 : == gives true , equals give true
new 200 200 : == gives false, equals give true
valueOf 200 200 : == gives false, equals give true
autoboxing 200 200 : == gives false, equals give true
WTF. Forklaring følger.
1) I Java er int en simpel value type, mens Integer er den tilsvarende objekt referance type.
2) I Java er test for lighed:
val == val : er værdierne ens
obj == obj : er referancerne ens
obj.equals(obj) : er værdierne ens
3) Visse objekt referance typer som wrapper simple data typer herunder Integer klassen har en lille intern cache så den kan genbruge objekter - i stedetfor at have 10 Integer objekter med værdien 1 så har man kun 1 Integer objekt med værdien 1.
[ja - Integer er immutable, så ikke noget problem med flere referancer]
4) Default cacher Integer kun værdier -128..127
5) Integer o = new Integer(v);
bruger ikke denne cache.
Integer o = Integer.valueOf(v);
og
Integer o = v;
bruger denne cache.
6) Den default kan ændres på 2 måder:
java -XX:AutoBoxCacheMax=n ...
java -Djava.lang.Integer.IntegerCache.high=n ...
7) Men den kan kun sættes op. Man kan ikke sætte værdien lavere en 127. Man kan godt angive en værdi lavere end 127 men de ignoreres og Java bruger 127.
Suk.
1-2 er vel OK sådan er Java defineret og andre sprog har også deres regler for den slags.
3-4 er grimt men har et fornuftigt formål (bedre performance)
5-7 er håbløst - hvad pokker tænker de på
Jeg er mere fan af Swift's model
Struct & Objects kan implementere en Equatable protokol, og så virker == altid
Og === kan sammenligne referencer (for objekter), e.g. pointer equality.
Det virker generelt lidt absurd at Java ikke har implementeret en moderne udgave af == operatoren
Struct & Objects kan implementere en Equatable protokol, og så virker == altid
Og === kan sammenligne referencer (for objekter), e.g. pointer equality.
Det virker generelt lidt absurd at Java ikke har implementeret en moderne udgave af == operatoren
og så ledes med Powershell :D
function Test-IntFun {
param (
[string]$lbl,
[int]$v1,
[int]$v2
)
$output = "{0,-10} {1,5} {2,5} : == gives {3,-5}, equals give {4,-5}" -f $lbl, $v1, $v2, ($v1 -eq $v2), ($v1 -eq $v2)
Write-Output $output
}
function Test {
param (
[int]$v
)
Test-IntFun "new" ([System.Int32]$v) ([System.Int32]$v)
Test-IntFun "valueOf" $v $v
Test-IntFun "autoboxing" $v $v
}
Test 100
Test 200
function Test-IntFun {
param (
[string]$lbl,
[int]$v1,
[int]$v2
)
$output = "{0,-10} {1,5} {2,5} : == gives {3,-5}, equals give {4,-5}" -f $lbl, $v1, $v2, ($v1 -eq $v2), ($v1 -eq $v2)
Write-Output $output
}
function Test {
param (
[int]$v
)
Test-IntFun "new" ([System.Int32]$v) ([System.Int32]$v)
Test-IntFun "valueOf" $v $v
Test-IntFun "autoboxing" $v $v
}
Test 100
Test 200
Python har også cachede int objekter for intervallet -5 til 256 og man kan ramme ind i lignende pudsigheder hvis man sammenligner ints med "is" i stedet for ==
Men hele denne idé er temmelig pervers for mig. En processor arbejder fundamentalt med heltal og nu kan man ikke engang håndtere et heltal uden at pakke det ind i et objekt, som så skal have et tilhørende cachesystem for at performance tålelig. Tal om at gå over åen efter vand :)
Kunne man ikke have lavet integer klassen helt statisk med statiske funktioner der tager integer værdien som parameter? Der er alligevel tale om special håndtering på dette niveau. Så kunne hele balladen i #1 have været skippet.
Men hele denne idé er temmelig pervers for mig. En processor arbejder fundamentalt med heltal og nu kan man ikke engang håndtere et heltal uden at pakke det ind i et objekt, som så skal have et tilhørende cachesystem for at performance tålelig. Tal om at gå over åen efter vand :)
Kunne man ikke have lavet integer klassen helt statisk med statiske funktioner der tager integer værdien som parameter? Der er alligevel tale om special håndtering på dette niveau. Så kunne hele balladen i #1 have været skippet.
Svaret på mig eget spørgsmål i #5 er selvfølgelig at et dynamisk sprog som Python har brug for at have metadata forbundet til alle værdier, for at kunne håndtere dem dynamisk. En integer skal pakkes ind på en eller anden måde og et objekt er en naturlig måde at gøre det på. Det giver mening.
Men for strongly typed languages som Java, er der både ints (som er rå, nøgne integers, ikke også?) og Integer objekter. Mit spørgsmål går så på hvorfor Integer overhovedet eksisterer i Java, hvad er formålet? Hvorfor ikke gøre det med statiske funktioner der gør arbejder på ints? Hvorfor allokere et objekt, og introducere hele cache problematikken?
Men for strongly typed languages som Java, er der både ints (som er rå, nøgne integers, ikke også?) og Integer objekter. Mit spørgsmål går så på hvorfor Integer overhovedet eksisterer i Java, hvad er formålet? Hvorfor ikke gøre det med statiske funktioner der gør arbejder på ints? Hvorfor allokere et objekt, og introducere hele cache problematikken?
larsp (6) skrev:
Men for strongly typed languages som Java, er der både ints (som er rå, nøgne integers, ikke også?) og Integer objekter.
Ja.
larsp (6) skrev:
Mit spørgsmål går så på hvorfor Integer overhovedet eksisterer i Java, hvad er formålet? Hvorfor ikke gøre det med statiske funktioner der gør arbejder på ints? Hvorfor allokere et objekt, og introducere hele cache problematikken?
Nogen gange er der brug for at betragte en værdi af en simpel data type som et objekt.
Eksempel:
public class ToBeAnObjectOrNot {
public static class Lars {
}
private static void test(Object o) {
System.out.println(o.getClass().getName());
}
public static void main(String[] args) {
test(123);
test(123.456);
test("ABC");
test(new Lars());
}
}
Eksemplet kan måske virke lidt ubetydeligt.
Men det sker overalt i Java inklusive i generics at simple data typer bliver behandlet som objekter.
#7 Aha. Integer kan inordne sig under "Object" og man kan opnå noget af den dynamiske natur fra f.eks. Python.
Er "test(123)" lovligt for en funktion der forventer Object o? Laver java selv et Integer object når det er nødvendigt?
Havde funktionen heddet: void test(int x) tænker jeg der ikke ville blive lavet et Integer object?
Er "test(123)" lovligt for en funktion der forventer Object o? Laver java selv et Integer object når det er nødvendigt?
Havde funktionen heddet: void test(int x) tænker jeg der ikke ville blive lavet et Integer object?
larsp (8) skrev:
Er "test(123)" lovligt for en funktion der forventer Object o?
Ja. Koden ovenfor virker,
larsp (8) skrev:
Laver java selv et Integer object når det er nødvendigt?
Ja. Det er kendt som auto-boxing.
larsp (8) skrev:
Havde funktionen heddet: void test(int x) tænker jeg der ikke ville blive lavet et Integer object?
Korrekt.
Opret dig som bruger i dag
Det er gratis, og du binder dig ikke til noget.
Når du er oprettet som bruger, får du adgang til en lang række af sidens andre muligheder, såsom at udforme siden efter eget ønske og deltage i diskussionerne.