❶ JAVA中不可變類的應用
其實所謂的不變類只不過是在有更改值到操作時new一個新的實例並返回而已。
你的表述很不清楚,看程序字面,我估計你要的是這3個類。
/**TestClass.java**/
public interface TestClass {
public TestClass plus(int i);
public int getValue();
}
/**MutableClass.java**/
public class MutableClass implements TestClass {
int value;
public MutableClass(int i){
value=i;
}
public int getValue() {
return value;
}
public MutableClass plus(int i) {
value+=i;
return this;
}
}
/**ImmutableClass.java**/
public final class ImmutableClass implements TestClass{
int value;
public ImmutableClass(int i){
value=i;
}
public int getValue() {
return value;
}
public ImmutableClass plus(int i) {
ImmutableClass newtable=new ImmutableClass(value+i);
return newtable;
}
}
❷ java編程 這個類是不可變類嗎如果不是,給出修改代碼(審題)
A是可變類
不可變類特徵:
1:所有成員都是 private final 標識
2:不提供對成員的改變方法
3:確保所有的方法不會被重載
4:如果某一個類成員不是基本類型(primitive type)或不可變類,必須通過在成員初始化(in)或者getter方法(out)時通過深度拷貝(即復制一個該類的新實例而非引用)方法,來確保類的不可變。
❸ 學習java se注重的只是點是哪些,最難學的知識點有哪些呢
1. 基本數據類型
整形:
byte 1 個位元組
short 2 個位元組
int 4個位元組
long 8個位元組
字元:
char 2個位元組
浮點數:
float 4個位元組
double 8個位元組
布爾:
boolean 1個位元組
2.java 7 新增二進制整數
以0b或者0B開頭
3.java中字元時16位的Unicode編碼方式,格式是'\uXXXX',其中xxxx代表一個十六進制整數
4.java中規定了正無窮大、負無窮大和零
正無窮大= 一個正數除以0
負無窮大= 一個負數除以零
0.0 除以0.0 或者 對一個負數開方 得到一個非數
5. 在java中布爾類型只能是true和false
6. 在java中沒有多維數組
看似像c語言中的多維數組不是真正的數組,比如 a[3][4] , a[0] a[1] a[2] 是真實存在的,裝的是地址,和c語言中動態分配為的數組一樣
int [][] b = new int[3][4]
7. Java中帶包的編譯方法
javac -d . Hello.java 會在當前目錄下生成目錄樹
運行 java 包名字.類名字
8. Java多態中的對象的filed 不具有多態性,如 父類 對象 = new 子類(), 對象.field 是調用的父類的,即使子類中覆蓋了該欄位。
9. instanceof 運算符
格式: 引用變數名 instanceof 類名(或者介面) 他用於判斷前面的對象是否是後面對象的類,子類、實現類的實例,是返回true,否者返回false
10. Java 中基本數據類型和對應封裝類之間的轉化
int a = 1;
Integer A = new Integer(a);
a = A.intValue();
其他的類型也是這樣的。
11.單例(singleton)類 例子
復制代碼 代碼如下:
class Singleton
{
private static Singleton instance;
private Singleton(){}
public static Singleton getInstance()
{
if(instance == null)
{
instance = new Singleton();
}
return instance;
}
public static void main(String[] args)
{
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
System.out.println(s1 == s2);
}
}
12.final修飾的成員變數初始化問題
類Field: 必須在靜態初始塊中或聲明該FIeld時指定初始值
實例Field:必須在非靜態初始塊中或聲明該FIeld時指定初始值或構造器中聲明
13.Final 變數必須顯式初始化,系統不會對final變數進行隱式初始化
14.java會使用常量池來管理曾經用過的字元串直接常量,例如:String a = "java"; ,系統把常量字元串「java」存在常量池,當再次執行 String b = "java"; a == b 是true
15.final 方法不可以重寫,final類不能被繼承
如果用private 方法 和 final private 是一樣的
若果是用final修飾的方法在子類中出現,那是子類新定義的,與父類沒有關系
16.不可變類:創建後該類的Field是不可改變的。java提供了8個基本變數的包裝類和string都是不可改變類。
17.緩存實例的不可改變類
復制代碼 代碼如下:
class CacheImmutale
{
private static int MAX_SIZE = 10;
private static CacheImmutale[] cache = new CacheImmutale[MAX_SIZE];
private static int pos = 0;
private final String name;
private CacheImmutale(String name)
{
this. name = name;
}
public String getName()
{
return name;
}
public static CacheImmutale valueOf(String name)
{
for(int i = 0; i < MAX_SIZE; ++i)
{
if(cache[i] != null && cache[i].getName().equals(name))
return cache[i];
}
if(pos == MAX_SIZE)
{
cache[0] = new CacheImmutale(name);
pos = 1;
}
else
{
cache[pos++] = new CacheImmutale(name);
}
return cache[pos -1];
}
public boolean equals(Object obj)
{
if(this == obj)
return true;
if(obj != null && obj.getClass() == CacheImmutale.class)
{
CacheImmutale ci = (CacheImmutale)obj;
return name.equals(ci.getName());
}
return false;
}
public int hashCode()
{
return name.hashCode();
}
}
public class CacheImmuteTest
{
public static void main(String[] args)
{
CacheImmutale c1 = CacheImmutale.valueOf("Hello");
CacheImmutale c2 = CacheImmutale.valueOf("Hello");
System.out.println(c1 == c2);
}
}
用緩存實例要看某個對象的使用頻率,若重復使用那就利大於弊,若不經常使用那弊就大於利
還有java提供的java.lang.Integer 創建數值在-128-127之間的數採用緩存機制的
Integer in2 = Integer.valueOf(6);
Integer in3= Integer.valueOf(6);
in2 == in3 is true;
18. static 和 abstract 不能同時修飾一個方法,沒有類抽象方法
19.一個類可以又一個父類,實現多個介面,介面中Filed是public 、static、final的,方法是public abstract的
20.非靜態內部類的方法訪問某個變數,搜索順序為:先內部類中方法內-> 內部類 -> 外部類中如果都找不到則出現編譯錯誤
復制代碼 代碼如下:
import java.util.*;
public class DiscernVariable
{
private String prop = "外部類的實例變數";
private class InClass
{
private String prop = "內部類的實例變數";
public void info()
{
String prop = "局部變數";
System.out.println("外部類的field值:" + DiscernVariable.this.prop);
System.out.println("內部類的field值:" + this.prop);
System.out.println("局部變數的值:" + prop);
}
}
public void test()
{
InClass in = new InClass();
in.info();
}
public static void main(String[] args)
{
new DiscernVariable().test();
}
}
21.非靜態內部類不能有靜態方法、靜態Field、靜態初始化塊
22.在外部類之外訪問內部類
訪問非靜態內部類:outclass.Inclass varname = new outclass().new InClass();
訪問靜態內部類: outclass.Inclass varname = new outclass.Inclass();
復制代碼 代碼如下:
import java.util.*;
class Out
{
class In
{
public In()
{
System.out.println("非靜態內部類構造器");
}
}
}
public class CreatInnerInstance
{
public static void main(String[] args)
{
Out.In in = new Out().new In();
/*
以上的代碼可分開寫為:
Out.In in;
Out out = new Out();
in = out.new In();
*/
}
}
class SubClass extends Out.In
{
//顯示定義SubClass的構造器
public SubClass(Out out)
{
//通過轉入的Out對象顯示調用In的構造器
out.super();
}
}
復制代碼 代碼如下:
import java.util.*;
class StaticOut
{
static class StaticIn
{
public StaticIn()
{
System.out.println("靜態內部類構造器");
}
}
}
public class CreatStaticInnerInstance
{
public static void main(String[] args)
{
StaticOut.StaticIn in = new StaticOut.StaticIn();
/*
以上的代碼可分開寫為:
StaticOut.StaticIn in;
in = new StaticOut.StaticIn();
*/
}
}
class SubClass extends StaticOut.StaticIn
{
//無須創建內部類實例
}
❹ Java緩存實例中的不可變類
max_size 是定義一個常量,這里是數組的最大長度
當pos達到最大長度之後,仍沒有找到, 則新建這個實例,放在0位置上,pos賦值為1,,
pos對應的數據,在數組中偏移為1 (pos++導致),返回的時候需要減1,
判斷兩個實例相等部分,如果類型相同並且名稱也相同,則認定這兩個對象相等。
❺ 如何創建不可變的Java類或對象
immutable Objects就是那些一旦被創建,它們的狀態就不能被改變的Objects,每次對他們的改變都是產生了新的immutable的對象,而mutable Objects就是那些創建後,狀態可以被改變的Objects.
舉個例子:String和StringBuilder,String是immutable的,每次對於String對象的修改都將產生一個新的String對象,而原來的對象保持不變,而StringBuilder是mutable,因為每次對於它的對象的修改都作用於該對象本身,並沒有產生新的對象。
但有的時候String的immutable特性也會引起安全問題,這就是密碼應該存放在字元數組中而不是String中的原因!
immutable objects 比傳統的mutable對象在多線程應用中更具有優勢,它不僅能夠保證對象的狀態不被改變,而且還可以不使用鎖機制就能被其他線程共享。
實際上JDK本身就自帶了一些immutable類,比如String,Integer以及其他包裝類。為什麼說String是immutable的呢?比如:java.lang.String 的trim,uppercase,substring等方法,它們返回的都是新的String對象,而並不是直接修改原來的對象。
如何在Java中寫出Immutable的類?
要寫出這樣的類,需要遵循以下幾個原則:
1)immutable對象的狀態在創建之後就不能發生改變,任何對它的改變都應該產生一個新的對象。
2)Immutable類的所有的屬性都應該是final的。
3)對象必須被正確的創建,比如:對象引用在對象創建過程中不能泄露(leak)。
4)對象應該是final的,以此來限制子類繼承父類,以避免子類改變了父類的immutable特性。
5)如果類中包含mutable類對象,那麼返回給客戶端的時候,返回該對象的一個拷貝,而不是該對象本身(該條可以歸為第一條中的一個特例)
當然不完全遵守上面的原則也能夠創建immutable的類,比如String的hashcode就不是final的,但它能保證每次調用它的值都是一致的,無論你多少次計算這個值,它都是一致的,因為這些值的是通過計算final的屬性得來的!
❻ java中,什麼叫不可更改的類(immutable class)
從字面意思來理解就是不會發生變化的類,那麼是什麼不會發生變化呢,其實就是類的狀態,也就是不變類的實例一旦被創建,其狀態就不會發生變化,舉個例子:如果人是一個class,那麼我們中的每一個都是人這個類的具體的instance,如果人這個類只有一個狀態就是生身父母,那麼它就是一個不變類,因為每一個人在出生的那一剎那,生身父母就已經被設置了值,而且終生都不會發生變化。
不變類有什麼好處呢?
1) 不變類是線程安全的,由於不變類的狀態在創建以後不再發生變化,所以它可以在線程之間共享,而不需要同步。
2) 不變類的instance可以被reuse
創建類的實例需要耗費CPU的時間,當這個實例不再被引用時,將會被垃圾回收掉,這時候,又需要耗費CPU的時間。對於不變類而言,一個好處就是可以將常用的實例進行緩存,從而減少了對象的創建。舉個例子,對於布爾型,最常用的便是true and false。JDK中的Boolean類就是一個不變類,並且對這兩個實例進行了緩沖。
public final class Boolean implements java.io.Serializable{
/**
* The <code>Boolean</code> object corresponding to the primitive
* value <code>true</code>.
*/
public static final Boolean TRUE = new Boolean(true);
/**
* The <code>Boolean</code> object corresponding to the primitive
* value <code>false</code>.
*/
public static final Boolean FALSE = new Boolean(false);
// 這個方法不會創建新的對象,而是重用已經創建好的instance
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
}
3) 不變類的某些方法可以緩存計算的結果
hashCode這個方法來自於Object這個類,這個方法用來返回對象的hashCode,主要用於將對象放置到hashtable中時,來確定這個對象的存儲位置。對於一個不變類的實例,它的hashCode也是不變的,所以就可以緩存這個計算的結果,來提高性能,避免不必要的運算,JDK中的String類就是一個例子。
public final class String{
/** Cache the hash code for the string */
private int hash; // Default to 0
public int hashCode() {
int h = hash;
if (h == 0) {
// compute the value
hash = h; // cache the value
}
return h;
}
}
在JDK中, String, the primitive wrapper classes, and BigInteger and BigDecimal都是不變類。
如果一個類是不變類,這個類是不是就不能有改變狀態的方法呢?
答案當然是否定的,String是一個不變類,仍然有replace,replaceAll這樣的方法,而String仍然是一個不變類,那是因為在這些改變狀態的方法中,每次都是新創建一個String對象。
如果大家理解了不變類,那也就不難理解為什麼在做String的concatenate時,應當用StringBuffer而不是用+的操作符。
如何正確使用String呢?
1) 不要用new去創建String對象。
如果使用new去創建String,那麼每次都會創建一個新對象。
public static void main(String[] args) {
String A1 = "A";
String A2 = "A"; // It won't create a new object
checkInstance(A1, A2); // Result: They are same instances
String B1 = new String("A"); // create a new object
String B2 = new String("A"); // creat a new object
checkInstance(B1, B2); // Result: They are different instances
}
private static void checkInstance(String a1, String a2) {
if (a1 == a2) {
System.out.println("They are same instances");
} else {
System.out.println("They are different instances");
}
}
2) 應當用StringBuffer來做連接操作
因為String是一個不變類,那麼在做連接操作時,就會創建臨時對象來保存中間的運算結果,而StringBuffer是一個mutable class,這樣就不需要創建臨時的對象來保存結果,從而提高了性能。
我抄來的自己也學到東西了,以前這個都沒接觸過的說。
❼ java中一個類是不可變類的條件是什麼求詳細解答。
不可變類的唯一判斷條件是:
「 不可變類的實例在實例的整個生命周期中永遠保持初始化的狀態」
比如一個類裡面有個屬性是private List list,然後只提供了getList()方法,但是你還是可以通過getList().add(XXX)來修改list的內容。即是,它沒有保持「初始化」狀態,它是個可變類。
來自網路:
可變類和不可變類(Mutable and Immutable Objects)的初步定義:
可變類:當你獲得這個類的一個實例引用時,你可以改變這個實例的內容。
不可變類:當你獲得這個類的一個實例引用時,你不可以改變這個實例的內容。不可變類的實例一但創建,其內在成員變數的值就不能被修改。
如何創建一個自己的不可變類:
.所有成員都是private
.不提供對成員的改變方法,例如:setXXXX
.確保所有的方法不會被重載。手段有兩種:使用final Class(強不可變類),或者將所有類方法加上final(弱不可變類)。
.如果某一個類成員不是原始變數(primitive)或者不可變類,必須通過在成員初始化(in)或者get方法(out)時通過深度clone方法,來確保類的不可變。
❽ 為什麼 java 中的 string 是不可變的
個人理解:因為string在java的編程當中比較普遍,以下的回答比較全面一些:
Java中String為什麼是不可變的
1、在Java中,String類是不可變類,一個不可變類是一個簡單的類,並且這個的實例也不能被修改,
這個類的實例創建的時候初始化所有的信息,並且這些信息不能夠被修改
2、字元串常量池
字元串常量池是方法區中一塊特殊的存儲區域,當創建一個字元串常量的時候,判斷該字元串字在符串字元串常量池中是否已經存在
如果存在,返回已經存在的字元串的引用;如果不存在,則創建一個新的字元串常量,並返回其引用
String string1 = "abcd";
String string2 = "abcd";
變數string1,string2指向常量池中的同一個字元串常量對象;如果String是可變的,給一個變數重新賦值一個引用,將會指向錯誤的值
3、緩存哈希值
在Java中字元串的哈希值會經常被使用到。例如在HashMap中,String的不可變總能保證哈希值總是相等的,並且緩存起來,不用擔心會改變,
那意味著不需要每次都計算哈希值,這樣會提高效率。在String類中有以下的代碼:
private int hash; //用來緩存哈希值
3、促進其他對象的使用
HahSet<String> set = new HashSet<String>();
set.add(new String("a"));
set.add(new String("b"));
set.add(new String("c"));
❾ java不可變類有哪些
java不可變類是fina的,常用的有以下幾種:
String
,Comparable<String>,CharSequence
Integer (以及其它基本類型的包裝類)
<Integer>
❿ JAVASE不可變類
fianl修飾類 則這個類的是最終類,不可被繼承
final修飾成員方法,則子類不能重寫(覆蓋)父類的這個方法
final修飾成員變數,則子類不能改變這個變數的值
你這個程序沒用到繼承,當然看不出不同了。
如果一個大的工程,團隊合作來完成的,而且子類很多,並且不想子類改變這個值,就很有必要用final限制了。