java基礎部分程式碼相關題

張超帥發表於2017-08-05
public class SendValue{
    public String str="6";
    public static void main(String[] args) {
        SendValue sv=new SendValue();
        sv.change(sv.str);
        System.out.println(sv.str);
    }
    public void change(String str) {
        str="10";
    }
}

Java中String型別變數是immutable(不可變的)。
儘管 change()方法中的str與sv.str都是新的物件例項成員變數值”6”的引用, 由於String型別的 不可變 性,change()方法中的str=”10”語句實際上是將傳入的str副本引用指向了一個值為“10”的新的記憶體地址,但 原資料引用 sv.str的引用值(也就是“6”的記憶體地址) 並沒有發生改變,因此sv.str指向的值仍舊為6.


System.out.println(“is ”+ 100 + 5);
System.out.println(100 + 5 +“ is”);
System.out.println(“is ”+ (100 + 5));

1.”is”說明後面的內容都會被強制轉換為string,所以是最後結果是拼接起來的
2.100+5先得到105,然後與is拼接
3.先算括號內的


public class Test
{
    public static Test t1 = new Test();
    {
         System.out.println("blockA");
    }
    static
    {
        System.out.println("blockB");
    }
    public static void main(String[] args)
    {
        Test t2 = new Test();
    }
 }

靜態塊:用static申明,JVM載入類時執行,僅執行一次
構造塊:類中直接用{}定義,每一次建立物件時執行
執行順序優先順序:靜態塊>main()>構造塊>構造方法
靜態塊按照申明順序執行,先執行Test t1 = new Test();
所有先輸出blockA,然後執行靜態塊,輸出blockB,最後執行main
方法中的Test t2 = new Test();輸出blockA。


int i=0;
Integer j = new Integer(0);
System.out.println(i==j);
System.out.println(j.equals(i));

1、基本型和基本型封裝型進行“==”運算子的比較,基本型封裝型將會自動拆箱變為基本型後再進行比較,因此Integer(0)會自動拆箱為int型別再進行比較,顯然返回true;
2、兩個Integer型別進行“==”比較,如果其值在-128至127,那麼返回true,否則返回false, 這跟Integer.valueOf()的緩衝物件有關,這裡不進行贅述。
3、兩個基本型的封裝型進行equals()比較,首先equals()會比較型別,如果型別相同,則繼續比較值,如果值也相同,返回true
4、基本型封裝型別呼叫equals(),但是引數是基本型別,這時候,先會進行自動裝箱,基本型轉換為其封裝型別,再進行3中的比較。


class CompareReference{
   public static void main(String [] args){
   float f=42.0f;
   float f1[]=new float[2];
   long x=42;
   f1[0]=42.0f;
  }
}
判斷x==f1[0]

java核心卷I中43頁有如下表述:兩個數值進行二元操作時,會有如下的轉換操作:
如果兩個運算元其中有一個是double型別,另一個操作就會轉換為double型別。
否則,如果其中一個運算元是float型別,另一個將會轉換為float型別。
否則,如果其中一個運算元是long型別,另一個會轉換為long型別。
否則,兩個運算元都轉換為int型別。
故,x==f1[0]中,x將會轉換為float型別。

public  static void main(String[] args){
    String s;
    System.out.print("s="+s);
}

由於String s沒有初始化,程式碼不能編譯通過。
成員變數有初始值,而區域性變數沒有初始值得。本體中的s定義在方法中所以為區域性變數-沒有初始值。變數沒有初始值就使用了,編譯通不過


public class TestClass {
   private static void testMethod(){
        System.out.println("testMethod");
   }
   public static void main(String[] args) {
        ((TestClass)null).testMethod();
   }
}

靜態的方法也是可以通過物件.來訪問的,其次,null可以被強制型別轉換成任意型別的物件,於是通過它來執行靜態方法,就可以理解了。


public class Base
{
    private String baseName = "base";
    public Base()
    {
        callName();
    }

    public void callName()
    {
        System. out. println(baseName);
    }

    static class Sub extends Base
    {
        private String baseName = "sub";
        public void callName()
        {
            System. out. println (baseName) ;
        }
    }
    public static void main(String[] args)
    {
        Base b = new Sub();
    }
}

new Sub();在創造派生類的過程中首先建立基類物件,然後才能建立派生類。
建立基類即預設呼叫Base()方法,在方法中呼叫callName()方法,由於派生類中存在此方法,則被呼叫的callName()方法是派生類中的方法,此時派生類還未構造,所以變數baseName的值為null


Integer i01 = 59;
int i02 = 59;
Integer i03 =Integer.valueOf(59);
Integer i04 = new Integer(59)。

JVM中一個位元組以下的整型資料會在JVM啟動的時候載入進記憶體,除非用new Integer()顯式的建立物件,否則都是同一個物件
所有隻有i04是一個新物件,其他都是同一個物件。


boolean b=true?false:true==true?false:true;
System.out.println(b);

== 優先順序高於 三目運算子,先判斷 true == true,此時返回為 true,
這時表示式為 boolean b = true?false:true?false:true
此時三目運算子從右向左執行,true?false:true,返回false
這時表示式為 boolean b = true?false:false;
結果為:boolean b = false ;


public abstract class MyClass {
     public int constInt = 5;
     //add code here
     public void method() {
     }
}

public abstract void method(int a);
constInt = constInt + 5;
public int method();
public abstract void anotherMethod() {}

A是抽象方法,抽象類可以包含抽象方法,也可以不包含,雖然A 方法名是method,與題目中的方法同名,但是引數不同,是過載方法
B 在類中不能constInt = constInt + 5; 方法中可以
C 的方法名與題目中的方法名相同,返回值不能作為過載的依據
D 抽象方法沒有方法體


class A {
    public int func1(int a, int b) {
        return a - b;
    }
}
class B extends A {
    public int func1(int a, int b) {
        return a + b;
    }
}
public class ChildClass {
    public static void main(String[] args) {
    A a = new B();
    B b = new B();
    System.out.println("Result=" + a.func1(100, 50));
    System.out.println("Result=" + b.func1(100, 50));
    }
}

也就是編譯時候,會看左邊引用型別是否能正確編譯通過,執行的時候是呼叫右邊的物件的方法。編譯時候會發現左邊滿足條件所以編譯通過,執行時候又會呼叫右邊也就是 class B 的方法,所以答案都是150。

向上轉型: Person p = new Man() ; //向上轉型不需要強制型別轉化
向下轉型: Man man = (Man)new Person() ; //必須強制型別轉化


public class Spike
{
    public static void main(String[] args)
    {
        Counter a = new Counter();
        System.out.println(a.increment());
        System.out.println(a.anotherIncrement());
        Counter b = new Counter();
        System.out.println(b.increment());
    }
}
class Counter
{
    private static int count = 0;
    public int increment()
    {
        return count++;
    }
    public int anotherIncrement()
    {
        return ++count;
    }
}

return count++是先return再+1
return ++count是先+1再return


class A {
    private String a = “aa”;
    public boolean methodB() {
        String b = “bb”;
        final String c = “cc”;
    }
}

a是類中的成員變數,存放在堆區
b、c都是方法中的區域性變數,存放在棧區


陣列的定義:
宣告一個陣列時,不能直接限定陣列長度,只有在建立例項化物件時,才能對給定陣列長度.。


public class Example{
    String str=new String("hello");
    char[]ch={'a','b'};
    public static void main(String args[]){
        Example ex=new Example();
        ex.change(ex.str,ex.ch);
        System.out.print(ex.str+" and ");
        System.out.print(ex.ch);
    }
    public void change(String str,char ch[]){
        str="test ok";
        ch[0]='c';
    }
}
//求運算結果

因為String是被final修飾的類,所以本身的內容是不會改變的,相當於基本資料型別的值傳遞,在changge方法中給str賦值了“test”,相當於重新建立了一個string型別的變數


public class Test {
    public int aMethod(){
        static int i = 0;
        i++;
        return i;
    }
public static void main(String args[]){
    Test test = new Test();
    test.aMethod();
    int j = test.aMethod();
    System.out.println(j);
    }
}
//執行的結果是什麼?答案:編譯失敗

Java中靜態變數只能在類主體中定義,不能在方法中定義。 靜態變數屬於類所有而不屬於方法。


巢狀內部類

import EnclosingOne.InsideOne
1.public class Enclosingone
2.{
3.    public class InsideOne {}
4.
5.}
6.public class inertest
7.{
8.    public static void main(string[]args)
9.    {
10.        EnclosingOne eo = new EnclosingOne();
11.        //insert code here
12.    }
13.
14.}
答案:EnclosingOne.InsideOne ei=eo.new InsideOne();
    InsideOne ei=eo.new InsideOne();

內部類其實和類的屬性沒什麼區別,只是在宣告的時候必須是Outer.Inner a,就像int a 一樣,至於靜態內部類和非靜態內部類new的時候有點區別,
Outer.Inner a=new Outer().new Inner()(非靜態,先有Outer物件才能有屬性)

Outer.Inner a=new Outer.Inner()要把Outer.Inner看成一部分,就像類變數一樣


class Value{
    public int i=15;
}
public class Test{
    public static void main(String argv[]){
        Test t=new Test( );
        t.first( );
    }

public void first( ){
    int i=5;
    Value v=new Value( );
    v.i=25;
    second(v,i);
    System.out.println(v.i);
}

public void second(Value v,int i){
    i = 0;
    v.i = 20;
    Value val = new Value( );
    v = val;
    System.out.println(v.i+" "+i);
   }
}

Object 中euqals的原始碼如上。沒有重寫equals時,是直接用==判斷的,而String中重寫了equals方法。

   public boolean equals(Object obj) {
        return (this == obj);
    }  
equals沒重寫時候和==一樣,比較的是物件的地址,題中new 了兩個物件,所以各自地址不一樣,使用equals比較為false,但是string型別中的equals方法Java預設重寫了,可以比較物件裡的值;兩個物件指向的同一個string成員變數裡的值相同,所以eqauals比較也相同。

public class Square {  
    long width;  
    public Square(long l) {   
        width = l;  
    }  
    public static void main(String arg[]) {   
        Square a, b, c;  
        a = new Square(42L);   
        b = new Square(42L);   
        c = b;   
        long s = 42L;  
    } 
}

a = new Square(42L);
b = new Square(42L);
這裡new了兩個物件,所以a,b不是同一個引用a!=b
s的型別跟a,b不同型別,所以s!=a,s!=b
c = b;
這裡b,c是同一個物件的引用,所以b==c是true


連結:https://www.nowcoder.com/questionTerminal/88ff9e9553334637bb35e78871f5b640
來源:牛客網

public class Test {
public static void main(String[] args) {
    StringBuffer a = new StringBuffer("A"); 
    StringBuffer b = new StringBuffer("B"); 
    operator(a, b); 
    System.out.println(a + "," + b); 
} 
public static void operator(StringBuffer x, StringBuffer y) { 
    x.append(y); y = x; 
}
}
答案 AB  B

public class Test2
{
    public void add(Byte b)
    {
        b = b++;
    }
    public void test()
    {
        Byte a = 127;
        Byte b = 127;
        add(++a);
        System.out.print(a + " ");
        add(b);
        System.out.print(b + "");
    }
}
答案:a=-128  b=127

public void add(Byte b){ b=b++; } 這裡涉及java的自動裝包/自動拆包 Byte的首字母為大寫,是類,看似是引用傳遞,但是在add函式內實現++操作,會自動拆包成byte值傳遞型別,所以add函式還是不能實現自增功能。也就是說add函式只是個擺設,沒有任何作用。 Byte型別值大小為-128~127之間。 add(++a);這裡++a會越界,a的值變為-128 add(b); 前面說了,add不起任何作用,b還是127


public static void main(String[]args)throws Exception {
    final Object obj = new Object();
    Thread t1 = new Thread() {
        public void run() {
            synchronized (obj) {
                try {
                    obj.wait();
                    System.out.println("Thread 1 wake up.");
                } catch (InterruptedException e) {
                }
            }
        }
    };
    t1.start();
    Thread.sleep(1000);//We assume thread 1 must start up within 1 sec.
    Thread t2 = new Thread() {
        public void run() {
            synchronized (obj) {
                obj.notifyAll();
                System.out.println("Thread 2 sent notify.");
            }
        }
    };
    t2.start();
}
答案:Thread 2 sent notify.
Thread 1 wake up

執行obj.wait();時已釋放了鎖,所以t2可以再次獲得鎖,然後發訊息通知t1執行,但這時t2還沒有釋放鎖,所以肯定是執行t2,然後釋放鎖,之後t1才有機會執行。


public class StringDemo{
  private static final String MESSAGE="taobao";
  public static void main(String [] args) {
    String a ="tao"+"bao";
    String b="tao";
    String c="bao";
    System.out.println(a==MESSAGE);
    System.out.println((b+c)==MESSAGE);
  }
}
答案:true false

要注意兩個問題:
1,字串在java中儲存在字串常量區中
2,==判斷的是物件引用是否是同一個引用,判斷字串相等要用equals方法
首先判斷a==MESSAGE 同一份字串常量在記憶體中只有一份,因此是同一地址,返回true
再次比較(b+c)==MESSAGE 這相當於 new String(b+c)==MESSAGE 這裡new了一個String物件,所以返回false


class Base{
    public Base(String s){
        System.out.print("B");
    }
}
public class Derived extends Base{
    public Derived (String s) {
        System.out.print("D");
    }
    public static void main(String[] args){
        new Derived("C");
    }
}
答案:編譯出錯

子類構造方法在呼叫時必須先呼叫父類的,由於父類沒有無參構造,必須在子類中顯式呼叫,修改子類構造方法如下即可:
public Derived(String s){
super(“s”);
System.out.print(“D”);
}


Boolean flag = false;
if (flag = true)
{
    System.out.println(“true”);
}
else
{
    System.out.println(“false”);
}

Boolean修飾的變數為包裝型別,初始化值為false,進行賦值時會呼叫Boolean.valueOf(boolean b)方法自動拆箱為基本資料型別,因此賦值後flag值為true,輸出文字true。 flag=true,這裡賦值並沒有錯,被自己誤導了


public class Bground extends Thread{
    public static void main(String argv[]){
        Bground b = new Bground();
        b.run();
    }
    public void start(){
        for(int i=0;i<10;i++){
            System.out.println("Value of i = "+i);
        }
    }
}
答案:編譯通過,但無輸出

首先繼承Thread,然後呼叫run方法,bgroud並沒有重寫run方法,那麼就是呼叫父類Thread的run方法,所以無輸出。


public class TestObj{
    public static void main(String[] args){
        Object o=new Object(){
            public boolean equals(Object obj){
                return true;
            }
        };
        System.out.println(o.equals(“Fred”));
    }
}

//重寫了equals(),不管引數是什麼,都是返回true


String str1 = "hello";
String str2 = "he" + new String("llo");
System.err.println(str1 == str2);
答案:false

String str1 = “hello”;這裡的str1指的是方法區的字串常量池中的“hello”,編譯時期就知道的; String str2 = “he” + new String(“llo”);這裡的str2必須在執行時才知道str2是什麼,所以它是指向的是堆裡定義的字串“hello”,所以這兩個引用是不一樣的。


public static void main(String args[]) {
      List  Listlist1 = new ArrayList();
      Listlist1.add(0);
      List Listlist2 = Listlist1;
        System.out.println(Listlist1.get(0) instanceof Integer);
        System.out.println(Listlist2.get(0) instanceof Integer);
}
答案:true true

collection型別的集合(ArrayList,LinkedList)只能裝入物件型別的資料,該題中裝入了0,是一個基本型別,但是JDK5以後提供了自動裝箱與自動拆箱,所以int型別自動裝箱變為了Integer型別。編譯能夠正常通過。
將list1的引用賦值給了list2,那麼list1和list2都將指向同一個堆記憶體空間。instanceof是Java中關鍵字,用於判斷一個物件是否屬於某個特定類的例項,並且返回boolean型別的返回值。顯然,list1.get(0)和list2.get(0)都屬於Integer的例項


class Two{
    Byte x;
}
class PassO{
    public static void main(String[] args){
        PassO p=new PassO();
        p.start();
    }
    void start(){
        Two t=new Two();
        System.out.print(t.x+””);
        Two t2=fix(t);
        System.out.print(t.x+” ” +t2.x);
    }
    Two fix(Two tt){
        tt.x=42;
        return tt;
    }
}
答案:null 42 42

注意x是Byte型別,也就是byte的包裝型別,屬於引用型別。例項該類物件時,如果成員變數沒有顯示初始化那麼Java預設初始化為null.
該題中引用型別t作為形參進行傳遞,形參的改變會改變實參的值,所以再次列印t.x時已經變為42了。

相關文章