Java tricky questions

Java tricky questions
VD
  • Rejestracja:ponad 10 lat
  • Ostatnio:10 miesięcy
  • Postów:72
1

Cześć,

szukam fajnych rzeczy z Javy, które w pierwszej chwili nie wydają się intuicyjne. Core Java, bez bibliotek. W ramach quizu z ciekawostkami, a nie na potrzeby rekrutacji ;)
Przykład takiego pytania daję poniżej. Może macie jakieś zachowanie, które w pierwszej chwili Was zaskoczyło? Np. z testu OCP - tam jest chyba sporo smaczków?

Kopiuj
Will it compile?

switch(3) {
    case 3:
        String x = "abc";
        System.out.println(x);
        break;
    default: {
        String x = "bcd";
        System.out.println(x);
        break;
    }
}

Poziom oczywiście subiektywny, szukam inspiracji :)

edytowany 1x, ostatnio: VeloxDigitis
jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 9 godzin
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4708
5

Mało znany operator odwróconej lambdy ( ;-) ) - można tym komuś nieźle zamotać:

Kopiuj
var z = x <-- y;

jeden i pół terabajta powinno wystarczyć każdemu
Zobacz pozostałe 5 komentarzy
.andy
@Silv: Dragon Balla nie oglądałeś?🤔
Silv
Widziałem pewnie jakieś urywki, to wszystko.
wiciu
możesz napisać, o co chodzi w tym zapisie? serio pytam : )
Charles_Ray
var z = (x) < (—y);
wiciu
aha, ok : - )
damianem
  • Rejestracja:prawie 8 lat
  • Ostatnio:4 miesiące
  • Postów:205
2

Fun fact, to jest jak najbardziej poprawna klasa: class Hmmm {{will:{}}{it:{{compile:{}}}}}

Dużym zaskoczeniem było też dla mnie to, że można w metodzie robić zagnieżdżone bloki z własnymi scope a także fakt, że można zrobić break z if :)

Kopiuj
void method() {
    {
        int a;
    }
    foo: {
        int a;
    }
    bar: if (1 < 2) {
        break bar;
    }
}
edytowany 1x, ostatnio: damianem
jarekr000000
Z tej kategorii jest też całkiem przydatne (w dziwacznych warunkach) : var x = new HashMap<>(){{ put(1,2);}};
Charles_Ray
  • Rejestracja:około 17 lat
  • Ostatnio:około 13 godzin
  • Postów:1875
2

Z 10 lat temu kumple mi podsunal taki snippet i pytanie czy sie skompiluje:

Kopiuj
http://google.com
int x = 1;

(Moglem troche spalic, bo nie jestem przy kompie, zeby sprawdzic jak to dokladnie bylo, ale idea ta sama)


”Engineering is easy. People are hard.” Bill Coughran
edytowany 1x, ostatnio: Charles_Ray
Shalom
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
2

Klasyka gatunku to oczywiście:

Kopiuj
int x = 1;
// \u000a x=2;
System.out.println(x);

"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
Charles_Ray
  • Rejestracja:około 17 lat
  • Ostatnio:około 13 godzin
  • Postów:1875
2

Kiedys w ogole byla cala ksiazka o tym: http://www.javapuzzlers.com/java-puzzlers-sampler.pdf


”Engineering is easy. People are hard.” Bill Coughran
Wibowit
  • Rejestracja:około 20 lat
  • Ostatnio:około 2 godziny
5


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
Shalom
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
5

A no jak wchodzimy na terytoriów WTF bugów to:

Kopiuj
package deadlocks;

public class Deadlock1 {
    void method(String label) {
        Boolean x = true;
        synchronized (x) {
            while (true) {
                System.out.println("Running " + label);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Deadlock1 deadlock1 = new Deadlock1();
        new Thread(() -> deadlock1.method("1")).start();
        new Thread(() -> deadlock1.method("2")).start();
    }
}

Co się wypisze na ekranie? :) W końcu synchronizacja na lokalnej zmiennej powinna w ogóle nie mieć wpływu na nic? ;)
I analogiczny kod ale jeśli zmienimy Boolean x = true; na Boolean x = new Boolean(true); (które to IntelliJ oznacza jako WTF i sugeruje zamienić z powrotem)

edit: i druga ciekawostka z życia wzięta:

Kopiuj
package deadlocks;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class Deadlock2 {
    public static void main(String[] args) {
        List<Integer> values = IntStream.range(0, 100).boxed().collect(Collectors.toList());
        List<Integer> results = values.parallelStream() // paralell czyli szybciej? ;)
                .map(Deadlock2::process)
                .collect(Collectors.toList());
        System.out.println(results);
    }

    private static Integer process(int x) {
        System.out.println(Thread.currentThread() + " Entered " + x);
        CompletableFuture<Integer> async = CompletableFuture.supplyAsync(() -> slowFunction(x)); // puszczamy w tle, a my cośtam dalej możemy sobie robić bo kiedyś nam sie to policzy...
        while (!async.isDone()) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return async.join();
    }

    private static int slowFunction(int x) {
        return x + 1;
    }
}

Jak zadziała ten kod i czemu? I co się stanie jak zamienimy parallelStream na stream. W końcu paralell to powinien zadziałać szybciej, prawda? ;)


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
edytowany 4x, ostatnio: Shalom
Zobacz pozostałe 3 komentarze
Shalom
Tak właśnie jest. A jestem sobie w stanie wyobrazić kod gdzie ktoś synchronizuje się na booleanie, potencjalnie blokując jakiś zupełnie inny wątek w aplikacji albo robiąc deadlock.
damianem
W pierwszym przy Boolean x = true mamy w bytcode INVOKESTATIC java/lang/Boolean.valueOf (Z)Ljava/lang/Boolean które zwraca jeden z dwóch obiektów z cache :) Jeśli tworzymy nowy obiekt to mamy rzeczywiście nową instancję INVOKESPECIAL java/lang/Boolean.<init> (Z)V.
damianem
Jeszcze lepszym WTF byłoby Integer x = 100; vs Integer x = 1000; :)
Shalom
@damianem: to też kiedyś debugowalem bo ktoś użył == i kod działał ale tylko dla małych wartości. Ale to łatwo zauważyć bo == to bardzo niecodzienny widok. Z tym boolem i z paralellsreamem już tak łatwo nie jest...
damianem
@Shalom: No w drugim przykładzie ForkJoinPool sam siebie wysyca ale to już nie jest takie oczywiste - trzeba pamiętać że defaultowo parallelStream i CompletableFuture go używają. Dziwię się twórcom języka że w ogóle ten thread pool wprowadzili, bo to trochę proszenie się o kłopoty :)
p_agon
  • Rejestracja:ponad 9 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:96-230
  • Postów:953
0
Kopiuj
int n = 0;
n--;
System.out.println(n++);

Jak bedzie wynik bez sprawdzania w IDE :P


Reasumując wszystkie aspekty kwintesencji tematu, dochodzę do fundamentalnej konkluzji: To by nic nie dało, nie dałoby nic! Przez 10 minut można, przy 2h to już jakaś zemsta pagona.
p_agon
  • Rejestracja:ponad 9 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:96-230
  • Postów:953
1

@Wibowit: w nagrode kolejne pytanie:

Kopiuj
int a = -1;
System.out.println(1 - a++);

Reasumując wszystkie aspekty kwintesencji tematu, dochodzę do fundamentalnej konkluzji: To by nic nie dało, nie dałoby nic! Przez 10 minut można, przy 2h to już jakaś zemsta pagona.
p_agon
:D oddawaj fartucha!
Wibowit
w c czy c++ jest chyba bardziej powszechny WTFowy problem. jak robiłem wywołanie method(readInt(), readInt(), readInt()) to mi wczytywało odwrotnie niż chciałem. po pewnym czasie znalazłem przyczynę - gcc oblicza parametry od końca, a clang od początku. w standardach c i c++ nie ma wymuszonej kolejności obliczania argumentów.
Wibowit
:facepalm: @Afish faktycznie :)
aolo23
  • Rejestracja:ponad 7 lat
  • Ostatnio:2 miesiące
  • Postów:186
1
Kopiuj
final ArrayList<Integer> ints = new ArrayList<>();
ints.add(1);

final ArrayList<Integer> ints2 = new ArrayList(){{
	add(1);
}};

System.out.println(ints);
System.out.println(ints2);

2ga para nawiasów dobiera się do "mięsa" klasy

więc można sobie "inline" coś tam pozmieniać i odpalić metody

Kopiuj
final ArrayList<Integer> ints2 = new ArrayList<>() {
	@Override
	public boolean add(Integer o) {
		return super.add(o);
	}

	{add(1);}
};

Exception oznacza więcej niż tysiąc słów.
Shalom
W ogóle List<Integer> to jest trochę hardkor jak chcesz zrobić remove() ( ͡° ͜ʖ ͡°)
PI
@Shalom: why?
Shalom
Bo remove(int) usuwa element pod daym indexem w liście a remove(T) czy tam remove(Object) usuwa dany obiekt. Tylko co jeśli T==int? ;)
PI
Aaa widzisz :D
VD
  • Rejestracja:ponad 10 lat
  • Ostatnio:10 miesięcy
  • Postów:72
0

Dzięki za odpowiedzi! Wrzucam jeszcze moje, które wymyśliłem:

Jaki będzie wynik?

Kopiuj
int a = 1, b = 2;
System.out.println(a+++--b*++a);

Jaki będzie wynik?

Kopiuj
public static void main(String[] args) {
    boolean a;
    if(smartThings()) {
        a = true;
    }
    System.out.println(a);
}

static boolean smartThings() {
    return true;
}
Charles_Ray
  • Rejestracja:około 17 lat
  • Ostatnio:około 13 godzin
  • Postów:1875
0

2 przyklady z SCJP, ale pouczające.

Klasyka 1. Ile elementów będzie Secie?

Kopiuj
class Person {
  String name;

  Person(String name){
    this.name=name;
  }
  
  public boolean equals(Person p){
     return name.equals(p.name);
  }

  public int hashCode() {
    return name.hashCode();
  }
}

//…
Person p1 = new Person(A),
       p2 = new Person(A);

Set<Person> ppl = new HashSet<>();
ppl.add(p1);
ppl.add(p2);
System.out.println(ppl.size());

Klasyka 2. Skompiluje sie?

Kopiuj
class Base {
  Base(int x) {}
}

class Sub extends Base {}


”Engineering is easy. People are hard.” Bill Coughran
edytowany 3x, ostatnio: Charles_Ray
Zobacz pozostałe 7 komentarzy
Wibowit
właśnie jest przeciążanie (overloading). nie ma za to nadpisywania (overriding).
Wibowit
uprościłem trochę przykład, na potrzeby zmieszczenia w komentarzu :) ten kod wypisuje true (bo zadziałało przeciążanie): public class Main { public static void main(String[] args) { class Person { boolean equals(Person p) { return true; } } Person p1 = new Person(), p2 = new Person(); System.out.println(p1.equals(p2)); } } ale jak zmienimy typ referencji z Person na Object to już wypisuje false
Charles_Ray
@Wibowit: Oddaję honor, poprawiam przykład, żeby był bug. Z głowy pisałem, you know ;) Chodziło oczywiście o: https://stackoverflow.com/questions/185937/overriding-the-java-equals-method-not-working
Wibowit
zdarza się. ja z głowy odpowiadałem pod wcześniejszym postem i też się pomyliłem.
Charles_Ray
IntelliJ zdaje się podkreśla takie coś na żółto, poza tym nie skompiluje się z @Override
PdP
  • Rejestracja:ponad 6 lat
  • Ostatnio:7 miesięcy
  • Lokalizacja:W-wa
  • Postów:189
1
p_agon napisał(a):
Kopiuj
int n = 0;
n--;
System.out.println(n++);

Jak bedzie wynik bez sprawdzania w IDE :P

@p_agon:

Kopiuj
int n=0;
n=n--;
System.out.println(n);
p_agon
Easy peasy: 0 :]
Grzyboo
  • Rejestracja:ponad 9 lat
  • Ostatnio:5 miesięcy
  • Postów:206
1

To może taki klasyczek - jaki będzie wynik?

Kopiuj
Integer x1 = 50;
Integer x2 = 50;
System.out.println(x1 == x2);
Integer y1 = 500;
Integer y2 = 500;
System.out.println(y1 == y2);
p_agon
Dla 127 true dla 128 false, ciekawe :]
jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 9 godzin
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4708
3

To jeszcze takie gówienko, można się naciąć w praktyce.

Kopiuj
class A {
    public static final int X = B.Y + 1;   
}
class B {
    public static final int Y = A.X + 1;
}
public class C {
    public static void main(String []args){
        System.out.println("X = "+A.X+", Y = "+B.Y);
     }
}

Skompiluje się? Jeśli tak, to jaki będzie wynik?


jeden i pół terabajta powinno wystarczyć każdemu
edytowany 3x, ostatnio: jarekr000000
Zobacz pozostałe 3 komentarze
WhiteLightning
@Charles_Ray: @jarekr000000 i teraz mam przez Was zagwozdke: czy w Javie kolejnosc deklaracji pol albo class moze wplynac na wydajnosc apki czy nie. W C++ potrafi, za to Java robi rozne dziwne optymalizacje...
Charles_Ray
Dodanie „final” może mieć wpływ - kwestie dotyczące memory model i jakie sztuczki jest w stanie wykonać JIT. To już jednak trochę chore ;) https://www.baeldung.com/java-final-performance . Odnośnie kolejności to w sumie nie wiem czy ona jest zachowywana
jarekr000000
czy w Javie kolejnosc deklaracji pol albo class moze wplynac na wydajnosc apki czy nie? - kolejność deklaracji pól może, ale jest to niejako poza specyfikacją - zależy jak dana maszyna (implementacja) je układa w fizycznej pamięci i co z tego wyniknie. Kolejność deklaracji klas raczej nie może (!!!), bo nie ma czegoś takiego jak kolejność klas na poziomie JVM - każda klasa to osobny "plik" (bajtocode).
FE
Hmm, X = 2 i Y = 1? Kolejność ładowania klas i default pól, czy cos czego nie rozumiem?
jarekr000000
WTF polega na tym, że to się w ogóle kompiluje. (Ze względu jednak na fundamenty javy trudno by to zmienić).
WhiteLightning
  • Rejestracja:prawie 14 lat
  • Ostatnio:około 4 godziny
  • Postów:3183
1

cokolwiek zwiazanego z performance i mikrooptymalizacjami + proby przewidzenia jak sie to zachowa razem. Jeden z moich ulubionych artykulow: https://shipilev.net/blog/2014/nanotrusting-nanotime/

To jeden z moich ulubionych drobiazgow:

double a=6/4.
System.out.println(a);

@jarekr000000: a to myslalem ze tylko w C++ takie cudo, bo tam dlugoscia strzalki mogles kontrolowac predkosc zmeirzania do 0:

int x = 10;

while( 0 <---- x )
{
printf("%d ", x);
}

albo:

int x = 100;

while( 0 <-------------------- x )
{
printf("%d ", x);
}

aolo23
:o grubo, aż sprawdziłem bo nie mogłem uwierzyć
wiciu
  • Rejestracja:ponad 11 lat
  • Ostatnio:8 dni
  • Postów:1205
1
Kopiuj
int i = 0;
i = i++ - ++i;
KamilAdam
Operatora ++ to powinni zakazać XD
99xmarcin
  • Rejestracja:około 5 lat
  • Ostatnio:6 miesięcy
  • Postów:2420
2

Stara książka Java Puzzlers jest pełna tego typu zagadek i.... jest strasznie nudna po pierwszych 5 stronach!

Większość z tych cudów zostanie wyłapana i zatrzymana na etapie statycznej analizy kodu.

Dla tych co chcą zrozumieć dlaczego tak a nie inaczej, cmd line'owy util: javap daje odpowiedź - wystarczy zrzucić wygenerowany bytecode i przeanalizować co wypluł kompilator. Na poziomie bytecodu kolejność operacji (nie wielowatkowych) jest dobrze zdefiniowana.


Holy sh*t, with every month serenityos.org gets better & better...
obscurity
cały ten wątek i tego typu zagadki to dla festiwal sp*******nia

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.