㈠ java問題,請問在java中什麼是直接量
直接量是指在程序中通過源代碼直接給出的值,代碼如下:
public static void main(String[] args)
{
// 在這行代碼中,為變數a所分配的初始值5就是一個直接量
int a = 5;
}
直接量的類型
並不是所有的數據類型都可以指定直接量,能指定直接量的通常只有三種類型,基本類型,字元串類型和null類型,具體而言,Java支持如下8種類型的直接量。
1),int類型的直接量:在程序中直接給出的整數數值
2),long類型的直接量:在整形數值後添加l或者L就變成了long類型的直接量
3),float類型的直接量:在一個浮點數後增加f或F就變成了float類型的直接量,這個浮點數可以是標準的小數形式,也可以是科學計數法形式
4),double類型的直接量:直接給出一個標准小數形式或者科學計數法形式的浮點數就是double類型的直接量
5),double類型的直接量:這個類型的直接量只有true和false
6),char類型的直接量:char類型的直接量有三種形式,分別是用單引號括起來的字元,轉義字元和Unicode值表示的字元
7),String類型的直接量:一個用雙引號括起來的字元序列就是String類型的直接量
8),null類型的直接量:這個類型的直接量只有一個值,即null
在上面的8種類型的直接量中,null類型是一種特殊類型,它只有一個值,null,而且這個直接量可以賦給任何引用類型的變數,用以表示這個引用類型變數中保存的地址為空,即
還未指向任何有效對象。
直接量的賦值
通常總是把一個直接量賦值給對應類型的變數,除此之外,還有兩點需要注意:
1),Java還支持數值之間的自動類型轉換,因此允許把一個數值直接量直接賦給另一種類型的變數,這種賦值必須是系統所支持的自動類型轉換。
比如把int類型的直接量賦給一個long類型的變數。
2),String類型的直接量不能賦給其他類型的變數,null類型的直接量可以直接賦給任何引用類型的變數,包括String類型。
boolean類型的直接量只能賦給boolean類型的變數,不能賦給其他任何類型的變數。
關於字元串補充
先補充一個概念,什麼是常量池?常量池(constant pool)值的是在編譯期被確定,並被保存在已編譯的.class文件中的一些數據,常量池包括了一些類,方法,介面中的常量
也包括字元串直接量。
當程序第一次使用某個字元串直接量時,Java會使用常量池來緩存該字元串直接量,如果程序後面的部分需要用到該字元串直接量時,Java會直接使用常量池中的字元串直接量。
String類是一個典型的不可變類,因此String對象創建出來就不可能被改變,所以無須擔心共享String對象會導致混亂。
Java會確保每個字元串常量只有一個,不會產生多個副本。代碼中使用一個字元串,他們在編譯期就被確定下來了,在使用的時候,直接從該常量池中拿出來就好了。
public static void main(String[] args)
{
String name1 = "LinkinPark";
String name2 = "LinkinPark";
String name3 = "Linkin" + "Park";
// 下面2行代碼輸出都為true
System.out.println(name1 == name2);
System.out.println(name1 == name3);
}
㈡ java中set<string>類型的東西是什麼如何將一個string類型的字元串增加到裡面
Set是集合的意思,是同種對象的集合,<String>說明這種對象都是String類型的對象。
可以這樣:
Set<String> set = new HashSet<String>();
Strings1= "hello";
String s2 = "world";
set.add(s1);
set.add(s2);
這樣就添加了兩個元素。
Java中String類學習總結
一、String是不可變對象
java.lang.String類使用了final修飾,不能被繼承。Java程序中的所有字面值,即雙引號括起的字元串,如"abc",都是作為String類的實例實現的。String是常量,其對象一旦構造就不能再被改變。
例:
public class Immutable {
public static String upcase(String s) {
return s.toUpperCase();
}
public static void main(String[ ] args) {
String str1= "Hello World";
System.out.println(str1); //Hello World
String str2 = upcase(str1);
System.out.println(str2); //HELLO WORLD
System.out.println(str1); //Hello World
}
}
二、String常量池
常量池(constant pool)指的是在編譯期被確定,並被保存在已編譯的.class文件中的一些數據。Java為了提高性能,靜態字元串在常量池中創建,並盡量使用同一個對象,重用靜態字元串。對於重復出現的字元串直接量,JVM會首先在常量池中查找,如果常量池中存在即返回該對象。
例:
public class test1 {
public static void main(String[] args){
String str1 = "Hello";
//不會創建新的String對象,而是使用常量池中已有的"Hello",
String str2 = "Hello";
System.out.println(str1 == str2); //true
//使用new關鍵字會創建新的String對象
String str3 = new String("Hello");
System.out.println(str1 == str3); //false
}
}
㈢ 什麼是Java位元組碼
它是程序的一種低級表示,可以運行於Java虛擬機上。將程序抽象成位元組碼可以保證Java程序在各種設備上的運行
Java號稱是一門「一次編譯到處運行」的語言,從我們寫的java文件到通過編譯器編譯成java位元組碼文件(.class文件),這個過程是java編譯過程;而我們的java虛擬機執行的就是位元組碼文件。不論該位元組碼文件來自何方,由哪種編譯器編譯,甚至是手寫位元組碼文件,只要符合java虛擬機的規范,那麼它就能夠執行該位元組碼文件。
JAVA程序的運行
因為Java具有跨平台特性,為了實現這個特性Java執行在一台虛擬機上,這台虛擬機也就是JVM,Java通過JVM屏蔽了不同平台之間的差異,從而做到一次編譯到處執行。JVM位於Java編譯器和OS平台之間,Java編譯器只需面向JVM,生成JVM能理解的代碼,這個代碼即位元組碼,JVM再將位元組碼翻譯成真實機器所能理解的二進制機器碼。
位元組碼是怎麼產生的?
我們所編寫的程序都是.java格式,通常在執行的時候也許點擊一下eclipse的運行鍵就可以在控制台看到運行結果,但是也可以更酷一些,如果你裝了JDK,那就可以直接在以命令行的方式編譯運行你的.java文件,編譯後會形成.class文件,這個.class文件即位元組碼。
位元組碼怎麼解讀?
上圖是編譯好的位元組碼文件,即一堆16進制的位元組,如果使用IDE去打開,也許看到的是已經被反編譯的我們所熟悉的java代碼,但這才是純正的位元組碼
這里只介紹位元組碼由哪些部分組成, 具體的意思自行網路或者看文尾的連接, 有較為詳細的講解
上圖即位元組碼文件的組成部分, Class文件的結構不像XML等描述語言那樣鬆散自由。由於它沒有任何分隔符號,
所以,以上數據項無論是順序還是數量都是被嚴格限定的。哪個位元組代表什麼含義,長度是多少,先後順序如何,都不允許改變, 如上圖左側即每一部分規定的長度
魔數(Magic Number)
魔數是用來區分文件類型的一種標志,一般都是用文件的前幾個位元組來表示。
比如0XCAFE BABE表示的是class文件,那麼有人會問,文件類型可以通過文件名後綴來判斷啊?是的,但是文件名是可以修改的(包括後綴),那麼為了保證文件的安全性,將文件類型寫在文件內部來保證不被篡改。
至於為什麼是CAFE BABE估計大家也能猜到, 程序員與咖啡的不解之緣
版本號(Version)
版本號含主版本號和次版本號,都是各佔2個位元組。在此Demo種為0X0000 0033。其中前面的0000是次版本號,後面的0033是主版本號。通過進制轉換得到的是次版本號為0,主版本號為51。高版本的JDK能向下兼容以前版本的Class文件,但不能運行以後版本的Class文件,即使文件格式未發生任何變化. 這就是target參數的用處,可以在使用JDK 1.7編譯時指定-target 1.5
常量池(Constant Pool)
常量池是Class文件中的資源倉庫, 量池中主要存儲2大類常量:字面量和符號引用。字面量如文本字元串,java中聲明為final的常量值等等,而符號引用如類和介面的全局限定名,欄位的名稱和描述符,方法的名稱和描述符。常量池是一個表結構,在表的內容前有一個類型的計數器,表示常量池的長度
上面的表中描述了11中數據類型的結構,其實在jdk1.7之後又增加了3種(CONSTANT_MethodHandle_info,CONSTANT_MethodType_info以及CONSTANT_InvokeDynamic_info)。這樣算起來一共是14種
訪問標志(Access_Flag)
訪問標志信息包括該Class文件是類還是介面,是否被定義成public,是否是abstract,如果是類,是否被聲明成final。通過上面的源代碼,我們知道該文件是類並且是public。
0x 00 21:是0×0020和0×0001的並集。其中0×0020這個標志值涉及到位元組碼指令
類索引(This Class Name)
類索引用於確定類的全限定名
0×00 03 表示引用第3個常量,同時第3個常量引用第19個常量,查找得」com/demo/Demo」。#3.#19
父類索引(Super Class Name)
0×00 04 同理:#4.#20(java/lang/Object)
介面索引(Interfaces)
通過上邊位元組碼圖可以看到,這個介面有2+n個位元組,前兩個位元組表示的是介面數量,後面跟著就是介面的表。我們這個類沒有任何介面,所以應該是0000。果不其然,查找位元組碼文件得到的就是0000。
欄位表集合(fields)
欄位表用於描述類和介面中聲明的變數。這里的欄位包含了類級別變數以及實例變數,但是不包括方法內部聲明的局部變數。接下來就是2+n個欄位屬性。我們只有一個屬性a,所以應該是0001。查找文件果不其然是0001。
該區域含有欄位的訪問標志, 訪問許可權, 欄位的名稱索引, 欄位的描述符索引, 屬性表
描述符的作用就是用來描述欄位的數據類型、方法的參數列表和返回值。而屬性表就是為欄位表和方法表提供額外信息的表結構。對於欄位來說,此處如果將欄位聲明為一個static final msg = "aaa"的常量,則欄位後就會跟著一個屬性表,其中存在一項名為ConstantValue,指向常量池中的一個常量,值為的"aaa"。
方法(methods)
包含訪問標志表, 方法名索引 , 方法描述符索引, 屬性表數量,等
Attribute
0×0001 :同樣的,表示有1個Attributes了。
0x000f : #15(「SourceFile」)
0×0000 0002 attribute_length=2
0×0010 : sourcefile_index = #16(「Demo.java」)
SourceFile屬性用來記錄生成該Class文件的源碼文件名稱。