天天看點

常見Java錯誤程式題1.Atomic原子操作類2.子類不能重寫父類的靜态方法3. 構造方法和getset4.線程的interrupt5.switch順序6.三元表達式比較7.this關鍵字8.父子類的成員變量成員方法9.封裝類型比較10.數組和list的協變11.volatile12.getclass13.Integer

1.Atomic原子操作類

  • 題目
public class Atomic {
    public static void main(String[] args) {
        AtomicInteger atomicInteger = new AtomicInteger(1);
        System.out.println(atomicInteger.getAndIncrement());
        System.out.println(atomicInteger.get());
    }
}
           
  • 輸出
1
2
           
  • 掌握知識

1.對于Java中的運算操作,例如自增或自減,若沒有進行額外的同步操作,在多線程環境下就是線程不安全的。同步:多線程并發通路共享資料時,保證共享資料再同一時刻隻被一個或一些線程使用。

2.那什麼叫做非阻塞同步呢?在并發環境下,某個線程對共享變量先進行操作,如果沒有其他線程争用共享資料那操作就成功;如果存在資料的争用沖突,那就才去補償措施,比如不斷的重試機制,直到成功為止,因為這種樂觀的并發政策不需要把線程挂起,也就把這種同步操作稱為非阻塞同步(操作和沖突檢測具備原子性)

3.incrementAndGet()方法在一個無限循環體内,不斷嘗試将一個比目前值大1的新值賦給自己,如果失敗則說明在執行"擷取-設定"操作的時已經被其它線程修改過了,于是便再次進入循環下一次操作,直到成功為止.

4.參考連結:原子操作類AtomicInteger詳解

常見Java錯誤程式題1.Atomic原子操作類2.子類不能重寫父類的靜态方法3. 構造方法和getset4.線程的interrupt5.switch順序6.三元表達式比較7.this關鍵字8.父子類的成員變量成員方法9.封裝類型比較10.數組和list的協變11.volatile12.getclass13.Integer

2.子類不能重寫父類的靜态方法

  • 題目
public class Scratch {
    public static void main(String[] args) {
        Fruit apple = new Apple();
        apple.name();
        apple.realName();
    }

    static class Fruit {
        public static void name() {
            System.out.println("Fruit");
        }

        public void realName() {
            System.out.println("Fruit");
        }
    }
    static class Apple extends Fruit {
        public static void name() {
            System.out.println("Apple");
        }

        public void realName() {
            System.out.println("Apple");
        }
    }
}

           
  • 輸出
Fruit
Apple
           
  • 掌握知識

1.子類不能重寫父類的靜态方法

2. 注意編譯器也會進行告警

3. 構造方法和getset

  • 題目
public class Robin {
    public static void main(String[] args) {
        Map<Key, String> aa = new HashMap<>();
        Key c=new Key(30,10);
        aa.put(c, "Robin");
        System.out.println(aa.get(c)); // Robin
        c.setFst(30);
        System.out.println(aa.get(c)); // Robin
        c.setFst(10);
        System.out.println(aa.get(c)); // Robin
    }

    public static class Key {
        private int fst;
        private int scn;

        public Key(int fst, int scn) {
            this.fst = fst;
            this.scn = scn;
        }

        public int getFst() {
            return fst;
        }

        public void setFst(int fst) {
            this.fst = fst;
        }

        public int getScn() {
            return scn;
        }

        public void setScn(int scn) {
            this.scn = scn;
        }
    }
}
           
  • 輸出
Robin
Robin
Robin
           
  • 掌握知識

1.構造方法:給對象資料進行初始化

2.要注意:在靜态方法中沒有this關鍵字(靜态是随着類的加載而加載,this是随着對象的建立而存在,靜态比對象先存在) ; 靜态方法隻能通路靜态;非靜态方法都可以通路

4.線程的interrupt

  • 題目
public class Sys extends Thread{
    boolean stop = false;

    public static void main(String[] args) throws InterruptedException {
        Sys thread = new Sys();
        thread.start();
        Thread.sleep(3000);
        thread.interrupt();
        Thread.sleep(3000);
        System.out.println("Stopping application...");
    }

    public void run() {
        while (!stop) {
            System.out.println("Thread is running...");
        }
        System.out.println("Thread exiting under request...");
    }
}
           
  • 輸出
Thread is running...
Thread is running...
Thread is running...
Thread is running...
Thread is running...
Thread is running...
Thread is running...
Thread is running...
Thread is running...
Thread is running...
Thread is running...
...
           
  • 掌握知識

1.thread.interrupt() 給目标線程發送中斷信号,目标線程中斷标記置為true

2.thread.isInterrupted() 傳回目标線程的中斷标記

3.thread.interrupted() 傳回目标線程的中斷标記,并将其置為false

4.注意:該題将中斷标志置為false,但是沒有邏輯去處理該中斷,是以線程會一直執行。

5.switch順序

  • 題目
public class SwitchDemo {
    public static void main(String[] args) {
        switch (5) {
            default:
                System.out.println(5);
            case 0:
                System.out.println(0);
            case 1:
                System.out.println(1);
                break;
            case 2:
                System.out.println(2);
                break;
        }
    }
}
           
  • 輸出
5
0
1
           
  • 掌握知識

1.switch可以處理int、short、byte、char類型的值,但是不能處理long、String等類型

2.如果case後面沒有break或者return語句,會緊接着執行其後的語句

3.switch進來就會找對應的case,找不到找default。該題找到了default直接往後執行,在1跳出。

6.三元表達式比較

  • 題目
public class CompareDemo {
    public static void main(String[] args) {
        char alpha = 'A';
        int foo = 65;
        boolean trueExp = true;
        System.out.println(trueExp ? alpha : 0);
        System.out.println(trueExp ? alpha : foo);
    }
}
           
  • 輸出
A
65
           
  • 掌握知識
1.三元表達式中的表達式1和表達式2為同種類型。是以與char比較傳回char,與int比較傳回int。

7.this關鍵字

  • 題目
public class Point {
    private int x;
    private int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public void setLocation(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public static void main(String[] args) {
        Point p1 = new Point(0, 0);
        Point p2 = new Point(0, 0);
        modifyPoint(p1, p2);
        System.out.println("[" + p1.x + "," + p1.y + "],[" + p2.x + "," + p2.y + "]");
    }

    private static void modifyPoint(Point p1, Point p2) {
        Point tmpPoint = p1;
        p1 = p2;
        p2 = tmpPoint;
        p1.setLocation(5, 5);
        p2 = new Point(5, 5);
    }
}
           
  • 輸出
[0,0],[5,5]
           
  • 掌握知識

1.可以使用this關鍵字調用重載構造方法。避免相同的初始化代碼,隻能在構造方法中用,并且必須位于構造方法的第一句。并且,除了構造器之外,編譯器禁止在其他任何方法中調用構造器。

2.this代表目前對象的一個引用

3.this隻能在方法内部使用

4.this不能用于靜态方法

8.父子類的成員變量成員方法

  • 題目
class Parent {
    int a = 100;

    public int f() {
        return 10;
    }
}
public class Son extends Parent {
    int a = 200;

    public int f() {
        return 20;
    }

    public static void main(String[] args) {
        Parent parent = new Son();
        System.out.println(parent.f() + " " + parent.a);
    }
}
           
  • 輸出
20 100
           
  • 掌握知識
1.如果在多态,即Parent c = new Child(),子類重載父類方法,則c.方法( ) 調用的是子類的方法,改變的子類變量資料,c.變量 顯示的是父類資料,還是未改變的。

9.封裝類型比較

  • 題目
public class ComDemo {
    public static void main(String[] args) {
        Comparator<Integer> df = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 > o2 ? 1 : (o1 == o2) ? 0 : -1;
            }
        };
        System.out.println(df.compare(new Integer(1), new Integer(1)));
    }
}
           
  • 輸出
-1
           
  • 掌握知識
1.o1==o2比較的是是否為同一對象,即記憶體位址相同,是以輸出-1

10.數組和list的協變

  • 題目
public class ListDemo {
    public static void main(String[] args) {
        ArrayList<String> arrayList1 = new ArrayList<>();
        arrayList1.add(new String());
        ArrayList<Object> arrayList2 = arrayList1;
        System.out.println(arrayList2.size());
    }
}
           
  • 輸出
編譯錯誤
           
  • 掌握知識
1.數組是協變的,而集合不是協變的。

11.volatile

  • 題目
public class SysDemo extends Thread {
    private boolean isRunning = true;

    public boolean isRunning() {
        return isRunning;
    }

    public void setRunning(boolean isRunning) {
        this.isRunning = isRunning;
    }

    @Override
    public void run() {
        System.out.println("begin");
        while (isRunning) {
        }
        System.out.println("end");
    }
}

class Run {
    public static void main(String[] args) {
        try {
            SysDemo thread = new SysDemo();
            thread.start();
            Thread.sleep(1000);
            thread.setRunning(false);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

           
  • 輸出
begin
           
  • 掌握知識
1.因為isRunning不是volatile,導緻線程裡面的isRunning一直無法擷取最新的值,是以一直處理死循環内部。

12.getclass

  • 題目
public class ListDemo1 {
    public static void main(String[] args) {
        List<String> stringList = new ArrayList<String>();
        List<Integer> integerList = new ArrayList<Integer>();
        System.out.println(stringList.getClass().equals(integerList.getClass()));
    }
}
           
  • 輸出
true
           
  • 掌握知識
1.兩個都是class java.util.ArrayList.

13.Integer

  • 題目
public class InteDemo {
    public static void main(String[] args) {
        Integer fst = 1;
        Integer snd = new Integer(1);
        System.out.println(fst == snd);
        System.out.println(new Integer(1) == snd);
        System.out.println(fst == Integer.valueOf(1));
        Integer trd = 256;
        System.out.println(trd == Integer.valueOf(256));
    }
}

           
  • 輸出
false
false
true
false
           
  • 掌握知識
java8中,Integer緩存池的大小預設為-128~127。
  • 題目
  • 輸出
  • 掌握知識