導航:首頁 > 編程語言 > java泛型靜態屬性

java泛型靜態屬性

發布時間:2023-02-09 12:42:36

1. 麻煩給我詳細介紹下java中用了泛型的好處,是不是用了泛型就可以不用NEW去創建對象了

1. 泛型的卻很有用, 如果跟反射可以配合用好, 普通企業應用得代碼量可以減少非常多.
2. python之類type inference語言比java更適合做這種template抽象

舉個例子: 企業程序大部分程序是實體信息管理得, 真正涉及交易清算得只有極小一部分
對於所有得實體管理, 基本上都是增,刪, 改, 查看, 查找等等幾個功能
我現在用了幾個框架, 經典結合方式:webwork+spring+hibernate, 分析如下:

hibernate O/R Mapping沒什麼花頭, 為每個實體管理都要寫一個映射類, 一般跟實體得數目差不多, 有時候為了避免關聯, 建幾個視圖映射會多點. But, 這個能用hibernate自己寫得工具生成, 維護一個java類文件, 以及裡面得meta description.
或者自己寫個程序生成( 給定數據源,, 輸出java類文件, 以及hbm .xml文件 ), 這個只需要維護sql語句就興了, 我通常這么做.

1. 不用泛型, 不用反射
spring層要寫5個service(假設一個實體對應一個service), 分別實現讀實體, 加實體, 刪實體, 根據條件查找實體List這些功能.

要寫5個不同得實體類得Action, 然後Action裡面實現校驗, 增加, 修改, 刪除, 列表得功能, 每一個類要實現得功能同樣也類似.

這些都沒多少重構實質性得體現, 好處不明顯, 可以提取得公共代碼非常少.

2. 不用泛型, 用反射
在 1 得基礎之上, 可以重構提取出一個公共service, 將分散在5個service得公共代碼kill掉. 多出一個根據實體類參數操作得公共類, 但是類得數量增加一個.

同樣Action也可以提出一個baseaction來

重構消去了一部分代碼, 每個service得代碼還是存在重復代碼, 但是這個還可以通過反射合成一個service, 不過掉用者要用反射調用

對於action因為需要配置, 除非webwork支持類型得注入, 否則, 不好消去.
如果webwork spring 支持實體類型得注入, 那麼到此可以結束, 只寫一套邏輯, 代碼也沒有重復, 由於精力有限, 沒有去深入研究spring AOP跟webwork 得inteceptor機制, 不知道支持不支持.

3.用泛型, 用反射
在1得基礎上引入泛型, 寫一個泛型service, 寫一個泛型webwork action , 也沒有研究過xwork中泛型對象是怎麼配置產生得, 如果支持配置, 只需要寫一個action即可, 如果不支持, 需要為每個實體類寫一個webwork action

同樣頁面也是這個樣子

但是, java得泛型用了一把, 不說對很多東西支持得很差, 光寫法上來看, 跟C++ template一致, 仍然是一大堆得<>, 讓初學者吐血, 變成高手炫耀得奇技淫巧. 比起python之類動態類型安全語言type inference機制相差太遠, java泛型還有很長得路要走, 不過靜態語言走到type inference上來得話, 編譯類型檢查得好處就沒了, 所以java這方面永遠不可能~~~
通過上面考慮, 我覺得python更適合web管理程序, 對於很多entity management得程序完全可以寫出一個服務所有, 僅僅是O?Rmapping就沒辦法省. 不知道python有沒有類似java得反射, 如果有得話會更好, 可以寫出更通用, 量更少得代碼. 相信ruby on rails成功也有這方面得原因(我沒用過ruby, 錯了也別罵我), 畢竟代碼越少越好, 尤其是重復代碼

我得主張是kill掉all重復代碼, 只要能抽象統一得代碼重復就是罪過, 哈哈, 相信用python可以把這個做得更好, 越來越喜歡python語言得特性了, 可惜還沒拿他來做過web程序

2. 還是關於java泛型的問題:在靜態方法中為什麼不能引用類級別的類型參數

你好,我覺得最主要的原因是因為泛型擦除。
class Demo<T> {
public void add(T t) {

//...
}

}
編譯後通過反編譯:
D:\test>javap -s -p Demo
Compiled from "Demo.java"
public class Demo extends java.lang.Object{
public Demo();
Signature: ()V
public void add(java.lang.Object);
Signature: (Ljava/lang/Object;)V
}
所以,非靜態方法正是由於專需要先有對象,屬進而在使用泛型的時候可以確定安全檢查的限制條件。
Demo<String> d = new Demo<String>() ;
d.add("str") ; //這里你就只能添加String類型的。

而靜態方法不需要構件對象,所以他在調用方法是,根本沒有判斷參數的約束條件,所以虛擬機壓根就不希望這種事情發生,所以在編譯時就報錯了。

3. 大學剛畢業可以學Java嗎 Java如何學習

大學畢業是可以學習Java的,Java前景是很不錯的,像Java這樣的專業還是一線城市比較好,師資力量跟得上、就業的薪資也是可觀的,

0基礎學習Java是沒有問題的,關鍵是找到靠譜的Java培訓機構,你可以深度了解機構的口碑情況,問問周圍知道這家機構的人,除了口碑再了解機構的以下幾方面:

1. 師資力量雄厚

要想有1+1>2的實際效果,很關鍵的一點是師資隊伍,你接下來無論是找個工作還是工作中出任哪些的人物角色,都越來越愛你本身的技術專業java技術性,也許的技術專業java技術性則絕大多數來自你的技術專業java教師,一個好的java培訓機構必須具備雄厚的師資力量。

2. 就業保障完善

實現1+1>2效果的關鍵在於能夠為你提供良好的發展平台,即能夠為你提供良好的就業保障,讓學員能夠學到實在實在的知識,並向java學員提供一對一的就業指導,確保學員找到自己的心理工作。

3. 學費性價比高

一個好的Java培訓機構肯定能給你帶來1+1>2的效果,如果你在一個由專業的Java教師領導並由Java培訓機構自己提供的平台上工作,你將獲得比以往更多的投資。

希望你早日學有所成。

4. java泛型問題:我能理解為什麼類型參數不能用於靜態欄位,但不理解為何在靜態方法中也不能引用類型參數

這個原理是這樣的,靜態方法中所能引用的屬性必須是靜態的,而引用參專數是無法聲明為靜態的屬,因為靜態的屬性必須在聲明時赴值或者實例化,泛型引用變數在聲明的時候根本不知道是什麼類型,自然不可能實例化,當然也不能放進靜態方法了,手機碼字,求支持。不懂加qq詳說

5. Java中如何在無參構造方法中調用有參構造

一般正常的都是參數多的調用參數少的。有參數的調用無參數的居多。

當然你要無參調用的參的也可以。

你用無參,調用有參的。那你有參的參數你需要怎麼傳呢。當然如果換一個角度也可以。

我手寫下。沒經過IDE的。提供下思路。我有兩種思路,寫同一個功能。

public class Person{

private String name;

private int age;

//無參

public Person(){

this.name="張三";

this.age=20;

}

//有參

public Person(String name){

this.name=name;

}

//多參

public Person(String name,int age){

this(name);//調用一個參數的構造方法

this.age=age;

}

}

這是一種寫法比較常用的方法。寫第一種。用上面的例子直接寫

public Person(){

this("張三",20);//調用有參構造方法。設置默認值。和第一種方法功能一樣

}

public Person(String name,int age){

this.name=name;

this.age=age;

}

為了程序易讀性。一般。參數的擴展和構造方法的調用都是有一定的規律的。

有參調無參,多參調少參。。擴展參數的時候,最好保持原來的順序。

6. 請教關於java的泛型方法

Java泛型詳解

  1. 概述
    在引入范型之前,Java類型分為原始類型、復雜類型,其中復雜類型分為數組和類。引入范型後,一個復雜類型
    就可以在細分成更多的類型。
    例如原先的類型List,現在在細分成List<Object>, List<String>等更多的類型。
    注意,現在List<Object>, List<String>是兩種不同的類型,
    他們之間沒有繼承關系,即使String繼承了Object。下面的代碼是非法的
    List<String> ls = new ArrayList<String>();
    List<Object> lo = ls;
    這樣設計的原因在於,根據lo的聲明,編譯器允許你向lo中添加任意對象(例如Integer),但是此對象是
    List<String>,破壞了數據類型的完整性。
    在引入范型之前,要在類中的方法支持多個數據類型,就需要對方法進行重載,在引入范型後,可以解決此問題
    (多態),更進一步可以定義多個參數以及返回值之間的關系。
    例如
    public void write(Integer i, Integer[] ia);
    public void write(Double d, Double[] da);
    的范型版本
    public <T> void write(T t, T[] ta);

    2. 定義&使用
    類型參數的命名風格為:
    推薦你用簡練的名字作為形式類型參數的名字(如果可能,單個字元)。最好避免小寫字母,這使它和其他的普通
    的形式參數很容易被區分開來。
    使用T代表類型,無論何時都沒有比這更具體的類型來區分它。這經常見於泛型方法。如果有多個類型參數,我們
    可能使用字母表中T的臨近的字母,比如S。
    如果一個泛型函數在一個泛型類裡面出現,最好避免在方法的類型參數和類的類型參數中使用同樣的名字來避免混
    淆。對內部類也是同樣。

    2.1 定義帶類型參數的類
    在定義帶類型參數的類時,在緊跟類命之後的<>內,指定一個或多個類型參數的名字,同時也可以對類型參數的取
    值范圍進行限定,多個類型參數之間用,號分隔。
    定義完類型參數後,可以在定義位置之後的類的幾乎任意地方(靜態塊,靜態屬性,靜態方法除外)使用類型參數,
    就像使用普通的類型一樣。
    注意,父類定義的類型參數不能被子類繼承。
    public class TestClassDefine<T, S extends T> {
    ....
    }

    2.2 定義待類型參數方法
    在定義帶類型參數的方法時,在緊跟可見范圍修飾(例如public)之後的<>內,指定一個或多個類型參數的名字,同時也可以對類型參數的取值范圍進行限定,多個類型參數之間用,號分隔。
    定義完類型參數後,可以在定義位置之後的方法的任意地方使用類型參數,就像使用普通的類型一樣。
    例如:
    public <T, S extends T> T testGenericMethodDefine(T t, S s){
    ...
    }
    注意:定義帶類型參數的方法,騎主要目的是為了表達多個參數以及返回值之間的關系。例如本例子中T和S的繼承關系, 返回值的類型和第一個類型參數的值相同。
    如果僅僅是想實現多態,請優先使用通配符解決。通配符的內容見下面章節。
    public <T> void testGenericMethodDefine2(List<T> s){
    ...
    }
    應改為
    public void testGenericMethodDefine2(List<?> s){
    ...
    }

    3. 類型參數賦值
    當對類或方法的類型參數進行賦值時,要求對所有的類型參數進行賦值。否則,將得到一個編譯錯誤。

    3.1 對帶類型參數的類進行類型參數賦值
    對帶類型參數的類進行類型參數賦值有兩種方式
    第一聲明類變數或者實例化時。例如
    List<String> list;
    list = new ArrayList<String>;
    第二繼承類或者實現介面時。例如
    public class MyList<E> extends ArrayList<E> implements List<E> {...}

    3.2 對帶類型參數方法進行賦值
    當調用范型方法時,編譯器自動對類型參數進行賦值,當不能成功賦值時報編譯錯誤。例如
    public <T> T testGenericMethodDefine3(T t, List<T> list){
    ...
    }
    public <T> T testGenericMethodDefine4(List<T> list1, List<T> list2){
    ...
    }

    Number n = null;
    Integer i = null;
    Object o = null;
    testGenericMethodDefine(n, i);//此時T為Number, S為Integer
    testGenericMethodDefine(o, i);//T為Object, S為Integer

    List<Number> list1 = null;
    testGenericMethodDefine3(i, list1)//此時T為Number

    List<Integer> list2 = null;
    testGenericMethodDefine4(list1, list2)//編譯報錯

    3.3 通配符
    在上面兩小節中,對是類型參數賦予具體的值,除此,還可以對類型參數賦予不確定值。例如
    List<?> unknownList;
    List<? extends Number> unknownNumberList;
    List<? super Integer> unknownBaseLineIntgerList;
    注意: 在Java集合框架中,對於參數值是未知類型的容器類,只能讀取其中元素,不能像其中添加元素,因為,其類型是未知,所以編譯器無法識別添加元素的類型和容器的類型是否兼容,唯一的例外是NULL

    List<String> listString;
    List<?> unknownList2 = listString;
    unknownList = unknownList2;
    listString = unknownList;//編譯錯誤

    4. 數組范型
    可以使用帶范型參數值的類聲明數組,卻不可有創建數組
    List<Integer>[] iListArray;
    new ArrayList<Integer>[10];//編譯時錯誤

    5. 實現原理

    5.1. Java范型時編譯時技術,在運行時不包含范型信息,僅僅Class的實例中包含了類型參數的定義信息。
    泛型是通過java編譯器的稱為擦除(erasure)的前端處理來實現的。你可以(基本上就是)把它認為是一個從源碼到源碼的轉換,它把泛型版本轉換成非泛型版本。
    基本上,擦除去掉了所有的泛型類型信息。所有在尖括弧之間的類型信息都被扔掉了,因此,比如說一個List<String>類型被轉換為List。所有對類型變數的引用被替換成類型變數的上限(通常是Object)。而且,無論何時結果代碼類型不正確,會插入一個到合適類型的轉換。
    <T> T badCast(T t, Object o) {
    return (T) o; // unchecked warning
    }
    類型參數在運行時並不存在。這意味著它們不會添加任何的時間或者空間上的負擔,這很好。不幸的是,這也意味著你不能依靠他們進行類型轉換。

    5.2.一個泛型類被其所有調用共享
    下面的代碼列印的結果是什麼?
    List<String> l1 = new ArrayList<String>();
    List<Integer> l2 = new ArrayList<Integer>();
    System.out.println(l1.getClass() == l2.getClass());
    或許你會說false,但是你想錯了。它列印出true。因為一個泛型類的所有實例在運行時具有相同的運行時類(class),
    而不管他們的實際類型參數。
    事實上,泛型之所以叫泛型,就是因為它對所有其可能的類型參數,有同樣的行為;同樣的類可以被當作許多不同的類型。作為一個結果,類的靜態變數和方法也在所有的實例間共享。這就是為什麼在靜態方法或靜態初始化代碼中或者在靜態變數的聲明和初始化時使用類型參數(類型參數是屬於具體實例的)是不合法的原因。

    5.3. 轉型和instanceof
    泛型類被所有其實例(instances)共享的另一個暗示是檢查一個實例是不是一個特定類型的泛型類是沒有意義的。
    Collection cs = new ArrayList<String>();
    if (cs instanceof Collection<String>) { ...} // 非法
    類似的,如下的類型轉換
    Collection<String> cstr = (Collection<String>) cs;
    得到一個unchecked warning,因為運行時環境不會為你作這樣的檢查。

    6. Class的范型處理
    Java 5之後,Class變成范型化了。
    JDK1.5中一個變化是類 java.lang.Class是泛型化的。這是把泛型擴展到容器類之外的一個很有意思的例子。
    現在,Class有一個類型參數T, 你很可能會問,T 代表什麼?它代表Class對象代表的類型。比如說,
    String.class類型代表 Class<String>,Serializable.class代表 Class<Serializable>。
    這可以被用來提高你的反射代碼的類型安全。
    特別的,因為 Class的 newInstance() 方法現在返回一個T, 你可以在使用反射創建對象時得到更精確的類型。
    比如說,假定你要寫一個工具方法來進行一個資料庫查詢,給定一個SQL語句,並返回一個資料庫中符合查詢條件
    的對象集合(collection)。
    一個方法是顯式的傳遞一個工廠對象,像下面的代碼:
    interface Factory<T> {
    public T[] make();
    }
    public <T> Collection<T> select(Factory<T> factory, String statement) {
    Collection<T> result = new ArrayList<T>();
    /* run sql query using jdbc */
    for ( int i=0; i<10; i++ ) { /* iterate over jdbc results */
    T item = factory.make();
    /* use reflection and set all of item』s fields from sql results */
    result.add( item );
    }
    return result;
    }
    你可以這樣調用:
    select(new Factory<EmpInfo>(){
    public EmpInfo make() {
    return new EmpInfo();
    }
    } , 」selection string」);
    也可以聲明一個類 EmpInfoFactory 來支持介面 Factory:
    class EmpInfoFactory implements Factory<EmpInfo> { ...
    public EmpInfo make() { return new EmpInfo();}
    }
    然後調用:
    select(getMyEmpInfoFactory(), "selection string");
    這個解決方案的缺點是它需要下面的二者之一:
    調用處那冗長的匿名工廠類,或為每個要使用的類型聲明一個工廠類並傳遞其對象給調用的地方,這很不自然。
    使用class類型參數值是非常自然的,它可以被反射使用。沒有泛型的代碼可能是:
    Collection emps = sqlUtility.select(EmpInfo.class, 」select * from emps」); ...
    public static Collection select(Class c, String sqlStatement) {
    Collection result = new ArrayList();
    /* run sql query using jdbc */
    for ( /* iterate over jdbc results */ ) {
    Object item = c.newInstance();
    /* use reflection and set all of item』s fields from sql results */
    result.add(item);
    }
    return result;
    }
    但是這不能給我們返回一個我們要的精確類型的集合。現在Class是泛型的,我們可以寫:
    Collection<EmpInfo> emps=sqlUtility.select(EmpInfo.class, 」select * from emps」); ...
    public static <T> Collection<T> select(Class<T>c, String sqlStatement) {
    Collection<T> result = new ArrayList<T>();
    /* run sql query using jdbc */
    for ( /* iterate over jdbc results */ ) {
    T item = c.newInstance();
    /* use reflection and set all of item』s fields from sql results */
    result.add(item);
    }
    return result;
    }
    來通過一種類型安全的方式得到我們要的集合。
    這項技術是一個非常有用的技巧,它已成為一個在處理注釋(annotations)的新API中被廣泛使用的習慣用法。

    7. 新老代碼兼容

    7.1. 為了保證代碼的兼容性,下面的代碼編譯器(javac)允許,類型安全有你自己保證
    List l = new ArrayList<String>();
    List<String> l = new ArrayList();

    7.2. 在將你的類庫升級為范型版本時,慎用協變式返回值。
    例如,將代碼
    public class Foo {
    public Foo create(){
    return new Foo();
    }
    }

    public class Bar extends Foo {
    public Foo create(){
    return new Bar();
    }
    }
    採用協變式返回值風格,將Bar修改為
    public class Bar extends Foo {
    public Bar create(){
    return new Bar();
    }
    }
    要小心你類庫的客戶端。

閱讀全文

與java泛型靜態屬性相關的資料

熱點內容
震旦adc307掃描的文件在哪裡 瀏覽:999
圖片打開變成文件 瀏覽:194
松下微單電腦傳文件軟體 瀏覽:574
蘋果藍牙鍵盤surface 瀏覽:170
mindmaplinux 瀏覽:733
oppo手機怎麼連接電腦傳輸數據 瀏覽:624
word刪除章節附註分隔符 瀏覽:773
公告質疑需要哪些文件 瀏覽:608
資料庫模型是干什麼的 瀏覽:404
win10的驅動怎麼安裝驅動 瀏覽:320
word文件水印怎麼取消 瀏覽:443
rhel6的鏡像文件在哪裡下載 瀏覽:571
成功正能量微信頭像 瀏覽:848
wps表格如何恢復數據 瀏覽:264
linuxc靜態庫創建 瀏覽:838
u盤有微信文件但微信恢復不了 瀏覽:585
蘋果的網站數據是什麼 瀏覽:22
ps滾字教程 瀏覽:237
win7網路鄰居如何保存ftp 瀏覽:186
安卓客戶端代理伺服器 瀏覽:572

友情鏈接