Java tricky questions

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?

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 :)

5

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

var z = x <-- y;
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 :)

void method() {
    {
        int a;
    }
    foo: {
        int a;
    }
    bar: if (1 < 2) {
        break bar;
    }
}
2

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

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

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

2

Klasyka gatunku to oczywiście:

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

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

5

5

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

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:

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? ;)

0
int n = 0;
n--;
System.out.println(n++);

Jak bedzie wynik bez sprawdzania w IDE :P

1

@Wibowit: w nagrode kolejne pytanie:

int a = -1;
System.out.println(1 - a++);
1
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

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

	{add(1);}
};
0

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

Jaki będzie wynik?

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

Jaki będzie wynik?

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

static boolean smartThings() {
    return true;
}
0

2 przyklady z SCJP, ale pouczające.

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

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?

class Base {
  Base(int x) {}
}

class Sub extends Base {}

1
p_agon napisał(a):
int n = 0;
n--;
System.out.println(n++);

Jak bedzie wynik bez sprawdzania w IDE :P

@p_agon:

int n=0;
n=n--;
System.out.println(n);
1

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

Integer x1 = 50;
Integer x2 = 50;
System.out.println(x1 == x2);
Integer y1 = 500;
Integer y2 = 500;
System.out.println(y1 == y2);
3

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

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?

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);
}

1
int i = 0;
i = i++ - ++i;
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.

1 użytkowników online, w tym zalogowanych: 0, gości: 1