程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java中一些基本概念的應用詳解

Java中一些基本概念的應用詳解

編輯:關於JAVA

Java中一些基本概念的應用詳解。本站提示廣大學習愛好者:(Java中一些基本概念的應用詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是Java中一些基本概念的應用詳解正文


  類的初始化次序
  在Java中,類外面能夠包括:靜態變量,靜態初始化塊,成員變量,初始化塊,結構函數。在類之間能夠存在著繼續關系,那末當我們實例化一個對象時,上述各部門的加載次序是如何的?

  起首來看代碼:

class Parent
 {
     public static StaticVarible staticVarible= new StaticVarible("父類-靜態變量1");   
     public StaticVarible instVarible= new StaticVarible("父類-成員變量1");

     static
     {
         System.out.println("父類-靜態塊");
     }

     {
         System.out.println("父類-初始化塊");
     }

     public static StaticVarible staticVarible2= new StaticVarible("父類-靜態變量2");   
     public StaticVarible instVarible2= new StaticVarible("父類-成員變量2");

     public Parent()
     {
         System.out.println("父類-實例結構函數");
     }
 }

 class Child extends Parent
 {
     public static StaticVarible staticVarible= new StaticVarible("子類-靜態變量1");   
     public StaticVarible instVarible= new StaticVarible("子類-成員變量1");

     static
     {
         System.out.println("子類-靜態塊");
     }

     public Child()
     {
         System.out.println("子類-實例結構函數");
     }

     {
         System.out.println("子類-初始化塊");
     }

     public static StaticVarible staticVarible2= new StaticVarible("子類-靜態變量2");   
     public StaticVarible instVarible2= new StaticVarible("子類-成員變量2");

    
 }

 class StaticVarible
 {
     public StaticVarible(String info)
     {
         System.out.println(info);
     }
 }

  然後履行上面的語句:

Child child = new Child();

輸入成果以下:

父類-靜態變量1
父類-靜態塊
父類-靜態變量2
子類-靜態變量1
子類-靜態塊
子類-靜態變量2
父類-成員變量1
父類-初始化塊
父類-成員變量2
父類-實例結構函數
子類-成員變量1
子類-初始化塊
子類-成員變量2
子類-實例結構函數

  結論  
  從上述成果可以看出,在實例化一個對象時,各部門的加載次序以下:

  父類靜態成員/父類靜態初始化塊 -> 子類靜態成員/子類初始化塊 -> 父類成員變量/父類初始化塊 -> 父類結構函數 -> 子類成員變量/子類初始化塊 -> 子類結構函數

  和String相干的一些事兒
  起首,我們聊一聊Java中堆和棧的事兒。

•棧:寄存根本類型,包含char/byte/short/int/long/float/double/boolean
•堆:寄存援用類型,同時普通會在棧中保存一個指向它的指針,渣滓收受接管斷定一個對象能否可以收受接管,就是斷定棧中能否有指針指向堆中的對象。
  String作為一種特別的數據類型,它不完整同等於根本類型,也不是全體的援用類型,很多面試題都有它的身影。

  String類型變量的存儲構造
  String的存儲構造分為兩部門,我們以String a = "abc";為例,描寫String類型的存儲方法:

  1)在棧中創立一個char數組,值分為是'a','b','c'。

  2)在堆中創立一個String對象。

  Java中的字符串池
  為了節儉空間和資本,JVM會保護一個字符串池,或許說會緩存一部門已經湧現過的字符串。

  例以下面的代碼:

String v1 = "ab";
String v2 = "ab";

  現實上,v1==v2,由於JVM在v1聲明後,曾經對“ab”停止了緩存。

  那末JVM對字符串停止緩存的根據是甚麼?我們來看上面的代碼,異常成心思:

public class StringTest {
     public static final String constValue = "ab";
     public static final String staticValue;

     static
     {
         staticValue="ab";
     }

     public static void main(String[] args)
     {
         String v1 = "ab";
         String v2 = "ab";
         System.out.println("v1 == v2 : " + (v1 == v2));
         String v3 = new String("ab");
         System.out.println("v1 == v3 : " + (v1 == v3));
         String v4 = "abcd";
         String v5 = "ab" + "cd";
         System.out.println("v4 == v5 : " + (v4 == v5));
         String v6 = v1 + "cd";
         System.out.println("v4 == v6 : " + (v4 == v6));
         String v7 = constValue + "cd";
         System.out.println("v4 == v7 : " + (v4 == v7));
         String v8 = staticValue + "cd";
         System.out.println("v4 == v8 : " + (v4 == v8));
         String v9 = v4.intern();
         System.out.println("v4 == v9 :" + (v4 == v9));
         String v10 = new String(new char[]{'a','b','c','d'});
         String v11 = v10.intern();
         System.out.println("v4 == v11 :" + (v4 == v11));
         System.out.println("v10 == v11 :" + (v10 == v11));
     }
 }

  請留意它的輸入成果:

v1 == v2 : true
v1 == v3 : false
v4 == v5 : true
v4 == v6 : false
v4 == v7 : true
v4 == v8 : false
v4 == v9 :true
v4 == v11 :true
v10 == v11 :false

  我們會發明,其實不是一切的斷定都前往true,這仿佛和我們下面的說法有抵觸了。其實否則,由於

  結論
  1. JVM只能緩存那些在編譯時可以肯定的常量,而非運轉經常量。

    上述代碼中的constValue屬於編譯經常量,而staticValue則屬於運轉經常量。

  2. 經由過程應用 new方法創立出來的字符串,JVM緩存的方法是紛歧樣的。

    所以上述代碼中,v1不同等於v3。

  String的這類設計屬於享元形式嗎?
  這個話題比擬成心思,年夜部門講設計形式的文章,在談到享元時,普通就會拿String來做例子,但它屬於享元形式嗎?

  字符串與享元的關系,年夜家可以參考上面的文章:深刻C#字符串和享元(Flyweight)形式的應用剖析
  字符串的反轉輸入
  這類情形下,普通會將字符串看作是字符數組,然後應用反轉數組的方法來反轉字符串。

  目眩紛亂的辦法挪用
  有繼續關系構造中的辦法挪用
  繼續是面向對象設計中的罕見方法,它可以有用的完成”代碼復用“,同時子類也有重寫父類辦法的自在,這就對究竟是挪用父類辦法照樣子類辦法帶來了費事。

  來看上面的代碼:

public class PropertyTest {

     public static void main(String[] args)
     {
         ParentDef v1 = new ParentDef();
         ParentDef v2 = new ChildDef();
         ChildDef v3 = new ChildDef();
         System.out.println("=====v1=====");
         System.out.println("staticValue:" + v1.staticValue);
         System.out.println("value:" + v1.value);
         System.out.println("=====v2=====");
         System.out.println("staticValue:" + v2.staticValue);
         System.out.println("value:" + v2.value);
         System.out.println("=====v3=====");
         System.out.println("staticValue:" + v3.staticValue);
         System.out.println("value:" + v3.value);
     }
 }

 class ParentDef
 {
     public static final String staticValue = "父類靜態變量";
     public String value = "父類實例變量";
 }

 class ChildDef extends ParentDef
 {
     public static final String staticValue = "子類靜態變量";
     public String value = "子類實例變量";
 }

  輸入成果以下:

=====v1=====
staticValue:父類靜態變量
value:父類實例變量
=====v2=====
staticValue:父類靜態變量
value:父類實例變量
=====v3=====
staticValue:子類靜態變量
value:子類實例變量

  結論
  關於挪用父類辦法照樣子類辦法,只與變量的聲明類型有關系,與實例化的類型沒有關系。

  究竟是值傳遞照樣援用傳遞
  關於這個話題,我的不雅點是值傳遞,由於傳遞的都是存儲在棧中的內容,不管是根本類型的值,照樣指向堆中對象的指針,都是值而非援用。而且在值傳遞的進程中,JVM會將值復制一份,然後將復制後的值傳遞給挪用辦法。

  依照這類方法,我們來看上面的代碼:

public class ParamTest {

     public void change(int value)
     {
         value = 10;
     }

     public void change(Value value)
     {
         Value temp = new Value();
         temp.value = 10;
         value = temp;
     }

     public void add(int value)
     {
         value += 10;
     }

     public void add(Value value)
     {
         value.value += 10;
     }

     public static void main(String[] args)
     {
         ParamTest test = new ParamTest();
         Value value = new Value();
         int v = 0;
         System.out.println("v:" + v);
         System.out.println("value.value:" + value.value);
         System.out.println("=====change=====");
         test.change(v);
         test.change(value);
         System.out.println("v:" + v);
         System.out.println("value.value:" + value.value);
         value = new Value();
         v = 0;
         System.out.println("=====add=====");
         test.add(v);
         test.add(value);
         System.out.println("v:" + v);
         System.out.println("value.value:" + value.value);
     }
 }

 class Value
 {
     public int value;
 }

  它的輸入成果:

v:0
value.value:0
=====change=====
v:0
value.value:0
=====add=====
v:0
value.value:10

  我們看到,在挪用change辦法時,即便我們傳遞出來的是指向對象的指針,但終究對象的屬性也沒有變,這是由於在change辦法體內,我們新建了一個對象,然後將”復制過的指向原對象的指針“指向了“新對象”,而且對新對象的屬性停止了調劑。然則“復制前的指向原對象的指針”仍然是指向“原對象”,而且屬性沒有任何變更。

  final/finally/finalize的差別
  final可以潤飾類、成員變量、辦法和辦法參數。應用final潤飾的類是弗成以被繼續的,應用final潤飾的辦法是弗成以被重寫的,應用final潤飾的變量,只能被賦值一次。

  應用final聲明變量的賦值機會:

  1)界說聲明時賦值

  2)初始化塊或靜態初始化塊中

  3)結構函數

  來看上面的代碼:

class FinalTest
 {
     public static final String staticValue1 = "靜態變量1";
     public static final String staticValue2;

     static
     {
         staticValue2 = "靜態變量2";
     }

     public final String value1 = "實例變量1";
     public final String value2;
     public final String value3;

     {
         value2 = "實例變量2";
     }

     public FinalTest()
     {
         value3 = "實例變量3";
     }
 }

  finally普通是和try...catch放在一路應用,重要用來釋放一些資本。

  我們來看上面的代碼:

public class FinallyTest {

     public static void main(String[] args)
     {
         finallyTest1();
         finallyTest2();
         finallyTest3();
     }

     private static String finallyTest1()
     {
         try
         {
             throw new RuntimeException();
         }
         catch(Exception ex)
         {
             ex.printStackTrace();
         }
         finally
         {
             System.out.println("Finally語句被履行");
         }
         try
         {
             System.out.println("Hello World");
             return "Hello World";
         }
         catch(Exception ex)
         {
             ex.printStackTrace();
         }
         finally
         {
             System.out.println("Finally語句被履行");
         }
         return null;
     }

     private static void finallyTest2()
     {
         int i = 0;
         for (i = 0; i < 3; i++)
         {
             try
             {
                 if (i == 2) break;
                 System.out.println(i);
             }
             finally
             {
                 System.out.println("Finally語句被履行");
             }
         }
     }

     private static Test finallyTest3()
     {
         try
         {
             return new Test();
         }
         finally
         {
             System.out.println("Finally語句被履行");
         }
     }
 }

  履行成果以下:

java.lang.RuntimeException
    at sample.interview.FinallyTest.finallyTest1(FinallyTest.java:16)
    at sample.interview.FinallyTest.main(FinallyTest.java:7)
Finally語句被履行
Hello World
Finally語句被履行

Finally語句被履行

Finally語句被履行
Finally語句被履行
Test實例被創立
Finally語句被履行

  留意在輪回的進程中,關於某一次輪回,即便挪用了break或許continue,finally也會履行。

  finalize則重要用於釋放資本,在挪用GC辦法時,該辦法就會被挪用。

  來看上面的示例:

class FinalizeTest
 {
     protected void finalize()
     {
         System.out.println("finalize辦法被挪用");
     }

     public static void main(String[] args)
     {
         FinalizeTest test = new FinalizeTest();
         test = null;
         Runtime.getRuntime().gc();
     }
 }

  履行成果以下:

finalize辦法被挪用

  關於根本類型的一些事兒
  根本類型供分為9種,包含byte/short/int/long/float/double/boolean/void,每種根本類型都對應一個“包裝類”,其他一些根本信息以下:

. 根本類型:byte 二進制位數:8
. 包裝類:java.lang.Byte
. 最小值:Byte.MIN_VALUE=-128
. 最年夜值:Byte.MAX_VALUE=127
. 根本類型:short 二進制位數:16
. 包裝類:java.lang.Short
. 最小值:Short.MIN_VALUE=-32768
. 最年夜值:Short.MAX_VALUE=32767
. 根本類型:int 二進制位數:32
. 包裝類:java.lang.Integer
. 最小值:Integer.MIN_VALUE=-2147483648
. 最年夜值:Integer.MAX_VALUE=2147483647
. 根本類型:long 二進制位數:64
. 包裝類:java.lang.Long
. 最小值:Long.MIN_VALUE=-9223372036854775808
. 最年夜值:Long.MAX_VALUE=9223372036854775807
. 根本類型:float 二進制位數:32
. 包裝類:java.lang.Float
. 最小值:Float.MIN_VALUE=1.4E-45
. 最年夜值:Float.MAX_VALUE=3.4028235E38
. 根本類型:double 二進制位數:64
. 包裝類:java.lang.Double
. 最小值:Double.MIN_VALUE=4.9E-324
. 最年夜值:Double.MAX_VALUE=1.7976931348623157E308
. 根本類型:char 二進制位數:16
. 包裝類:java.lang.Character
. 最小值:Character.MIN_VALUE=0
. 最年夜值:Character.MAX_VALUE=65535

  關於根本類型的一些結論(來自《Java面試解惑》)
•未帶有字符後綴標識的整數默許為int類型;未帶有字符後綴標識的浮點數默許為double類型。
•假如一個整數的值超越了int類型可以或許表現的規模,則必需增長後綴“L”(不辨別年夜小寫,建議用年夜寫,由於小寫的L與阿拉伯數字1很輕易混雜),表現為long型。
•帶有“F”(不辨別年夜小寫)後綴的整數和浮點數都是float類型的;帶有“D”(不辨別年夜小寫)後綴的整數和浮點數都是double類型的。
•編譯器會在編譯期對byte、short、int、long、float、double、char型變量的值停止檢討,假如超越了它們的取值規模就會報錯。
•int型值可以賦給一切數值類型的變量;long型值可以賦給long、float、double類型的變量;float型值可以賦給float、double類型的變量;double型值只能賦給double類型變量。
  關於根本類型之間的轉換
  上面的轉換是無損精度的轉換:

•byte->short
•short->int
•char->int
•int->long
•float->double
  上面的轉換是會喪失精度的:

•int->float
•long->float
•long->double
  除此以外的轉換,長短法的。

  和日期相干的一些事兒
  Java中,有兩個類和日期相干,一個是Date,一個是Calendar。我們來看上面的示例:

public class DateTest {

     public static void main(String[] args) throws ParseException
     {
         test1();
         test2();
         test3();
     }

     private static void test1() throws ParseException
     {
         Date date = new Date();
         System.out.println(date);
         DateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
         System.out.println(sf.format(date));
         String formatString = "2013-05-12";
         System.out.println(sf.parse(formatString));
     }

     private static void test2()
     {
         Date date = new Date();
         System.out.println("Year:" + date.getYear());
         System.out.println("Month:" + date.getMonth());
         System.out.println("Day:" + date.getDate());
         System.out.println("Hour:" + date.getHours());
         System.out.println("Minute:" + date.getMinutes());
         System.out.println("Second:" + date.getSeconds());
         System.out.println("DayOfWeek:" + date.getDay());
     }

     private static void test3()
     {
         Calendar c = Calendar.getInstance();
         System.out.println(c.getTime());
         System.out.println(c.getTimeZone());
         System.out.println("Year:" + c.get(Calendar.YEAR));
         System.out.println("Month:" + c.get(Calendar.MONTH));
         System.out.println("Day:" + c.get(Calendar.DATE));
         System.out.println("Hour:" + c.get(Calendar.HOUR));
         System.out.println("HourOfDay:" + c.get(Calendar.HOUR_OF_DAY));
         System.out.println("Minute:" + c.get(Calendar.MINUTE));
         System.out.println("Second:" + c.get(Calendar.SECOND));
         System.out.println("DayOfWeek:" + c.get(Calendar.DAY_OF_WEEK));
         System.out.println("DayOfMonth:" + c.get(Calendar.DAY_OF_MONTH));
         System.out.println("DayOfYear:" + c.get(Calendar.DAY_OF_YEAR));
     }
 }

  輸入成果以下:

Sat May 11 13:44:34 CST 2013
-05-11
Sun May 12 00:00:00 CST 2013
Year:113
Month:4
Day:11
Hour:13
Minute:44
Second:35
DayOfWeek:6
Sat May 11 13:44:35 CST 2013
sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=19,lastRule=null]
Year:2013
Month:4
Day:11
Hour:1
HourOfDay:13
Minute:44
Second:35
DayOfWeek:7
DayOfMonth:11
DayOfYear:131

  須要留意的是,Date中的getxxx辦法曾經釀成deprecated了,是以我們盡可能應用calendar.get辦法來獲得日期的細節信息。
  別的,留意DateFormat,它不只可以對日期的輸入停止格局化,並且可以逆向操作,將相符Format的字符串轉換為日期類型。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved