为什么射不出来| 宫外孕是什么症状| 蝉长什么样| 雪白雪白的什么| 血小板压积偏低是什么意思| 什么对眼睛好| 990金是什么金| 知了为什么要叫| 高反是什么意思| 热鸡蛋滚脸有什么作用| 今年流行什么发型女| 姐姐的孩子叫我什么| 螯合剂是什么| 跖疣是什么东西| 喝什么解酒最快最有效| 喉咙嘶哑是什么原因| 一什么冰箱| 恨嫁什么意思| 抄送和密送是什么意思| 染色体xy代表什么| 什么食物利尿效果最好| 3.1号是什么星座| 汧是什么意思| 58年属什么生肖| 盛世美颜是什么意思| 飞机杯有什么用| 小腹痛挂什么科| 姐姐的儿子叫什么| 慈禧为什么要毒死光绪| 肠镜什么情况下取活检| 鲜卑人是现在的什么人| 条件致病菌是什么意思| 慢性非萎缩性胃炎吃什么药| 标新立异是什么意思| 1221是什么星座| 检查心脏做什么检查| 计数单位是什么意思| 出挑是什么意思| 卡介苗是什么| 女性胃火旺吃什么药| 湿气重吃什么药| 六月份适合种什么菜| 鸟死在家里是什么征兆| 阳气是什么意思| 有机磷是什么| 风热感冒吃什么药最快| 螳螂是什么生肖| 斑斓是什么意思| 开眼镜店需要什么条件| 什么叫佛| 4.6什么星座| 证候是什么意思| 66年属马是什么命| 脚麻看什么科室最好| 双向是什么意思| 怀孕第一个月吃什么对胎儿好| chick什么意思| 筋头巴脑是什么东西| 锻炼是什么意思| 黄占读什么| 泡饭为什么对胃不好| 酸菜是什么菜做的| 大便很粗是什么原因| 何乐而不为是什么意思| 鸭子喜欢吃什么| 胃癌早期有什么症状| qn医学上是什么意思| 吃东西没有味道是什么原因| 安是什么意思| 27虚岁属什么生肖| 肾素高说明什么| 全蛋液是什么意思| 血压低是什么原因引起的| 蹲久了站起来头晕是什么原因| 眼睛痒吃什么药| 日本天皇叫什么名字| 没有美瞳护理液用什么代替| 私处长痘痘是什么原因| 综合是什么意思| 4月13号是什么星座| 严重脱发是什么原因| 吃茶油对身体有什么好处| 头疼吃什么药| 小ck属于什么档次| 吃什么补血贫血| 正方体体积公式是什么| 什么病会吐血| 女上位是什么意思| 奇脉见于什么病| 提高免疫力吃什么维生素| 食管挂什么科| 女生肚子疼是什么原因| 白带发黄什么原因| 大蒜有什么功效| 宫内早孕什么意思| 今年什么时候进伏天| 少叙痣是什么意思| 什么血型最稀有| 什么是甲母痣| 氮是什么| 西沙必利片治什么病| 一生一世是什么生肖| 梦见捡钱是什么预兆| 喝红枣水有什么好处和坏处| 受凉胃疼吃什么药| 庚是什么意思| 胸腔疼痛是什么原因| 梦见戴手表是什么意思| 阴道放屁是什么原因| 经常打哈欠是什么原因| 貘是什么| 语塞是什么意思| 东方蝾螈吃什么| 什么的朝霞| 沙金是什么| 明前茶和明后茶有什么区别| rng是什么意思| 今年为什么有两个6月| 为什么要做试管婴儿| 什么是碳水食物| 9.1什么星座| 宫颈管短有什么症状| 莼菜是什么菜| 什么食物不能一起吃| 颈椎应该挂什么科| 骨折不能吃什么东西| 2017年属鸡火命缺什么| 2001年属什么生肖| 为什么会长脂肪粒| 肿瘤患者不能吃什么| 阴囊湿疹用什么药| 什么的蔷薇| 农历10月22日是什么星座| 清明节是什么时候| 什么治疗咽炎效果好| 孕妇为什么怕热| 摩羯女和什么星座最配| 64年出生属什么| 松鼠桂鱼是什么鱼| 总胆红素偏高什么意思| 双氧水是什么东西| 八月十日是什么星座| penguin是什么意思| 子宫有积液是什么原因引起的| 史努比是什么品牌| 经常喝蜂蜜水有什么好处和坏处| 门口放什么植物好风水| 什么叫五官| 本来无一物何处惹尘埃什么意思| poct是什么意思| 腐女是什么意思| 有利有弊是什么意思| 十余载是什么意思| u盾是什么| 胃绞痛吃什么药| 唉声叹气是什么意思| 心存芥蒂是什么意思| 脸油是什么原因导致的| 投诉护士找什么部门| 低血压吃什么好| 什么什么自如| 朔望月是什么意思| tag什么意思| 肉桂属于什么茶| 争辩的近义词是什么| 甘油三酯是什么| phoebe是什么意思| 河南有什么特色美食| 二丁颗粒主要治什么病| 羊膜束带是什么意思| 蚂蚁最怕什么东西| chanel是什么牌子| 网罗是什么意思| 什么是宫腔镜检查| 鹦鹉为什么会说话| 心愿是什么意思| 血管变窄吃什么能改善| 胃不好吃什么好| 甲醛闻多了有什么症状| 腰椎间盘突出压迫神经吃什么药| 什么是功德| 前列腺在什么位置| 世界第一大河是什么河| 吃猪腰子有什么好处和坏处| 干疮是什么样子的图片| 什么的尾巴长不了歇后语| 爱是什么词| 手心痒是什么原因| 淮山和山药有什么区别| 冠状动脉ct检查什么| 头皮发麻是什么病的前兆| 牟利什么意思| 胡萝卜与什么食物相克| 面膜什么时候敷效果最好| 梦见活人死了是什么意思| 菠菜不能与什么一起吃| 中午十二点是什么时辰| 步后尘是什么意思| 糖类抗原CA125高是什么意思| 吃生姜对身体有什么好处和坏处| 尚书是什么官职| 3月19是什么星座| 用什么消肿最快| ar技术是什么意思| 为什么睡觉磨牙| 子宫切除有什么影响| 什么是糙米| 一点半是什么时辰| 白细胞低吃什么补得快| 4月25号是什么星座| 高级别上皮内瘤变是什么意思| 代理是什么| 重症肌无力是什么原因引起的| 随便你是什么意思| 梦见抓蝎子是什么意思| 生性凉薄什么意思| 夜莺是什么鸟| 黄色裤子配什么上衣好看| 副主任医师什么级别| 7月4号是什么节日| 紫花地丁有什么功效| 同房后小腹疼痛是什么原因| orange是什么颜色| 35岁属什么的| 怀孕会有什么反应| 肖像是什么意思| 疾厄宫是什么意思| 孕激素高是什么原因| 甘草泡水喝有什么好处和坏处| 树叶又什么又什么| 三个女是什么字| 性功能减退吃什么药| 消化不良吃什么药最好| 女生真空是什么意思| 图腾是什么意思| 香奈儿是什么牌子| 长的像蛇的鱼是什么鱼| 男人左眼下有痣代表什么| va是什么车牌| 拍证件照穿什么衣服| 树叶为什么是绿色的| 老司机是什么意思| 什么病可以申请低保| 大洋马是什么意思| 微凉是什么意思| abi医学上是什么意思| 空调滴水什么原因| 澳大利亚的国宝是什么| 喝醋对身体有什么好处| 赖氨酸是什么| 老是掉头发什么原因| 康复治疗是做什么的| 额窦炎吃什么药管用| 胎毒是什么样子的图片| 男生小便尿道刺痛什么原因| 1954年属什么| 蛇喜欢吃什么| 版记是什么| 亦字五行属什么| 仰望是什么意思| 感冒咳嗽可以吃什么水果| 眼睛周围长脂肪粒是什么原因| 艾灰有什么作用和功效| 蓝天白云是什么意思| 百度Zum Inhalt springen

影视著作鉴定委员会成立 离伸张正义还有多远?

aus Wikipedia, der freien Enzyklop?die
百度 现经核实,刘初道烈士应为刘道初烈士。

Generische Programmierung in Java wird durch sog. Generics seit Java 1.5 erm?glicht. Der Begriff steht synonym für ?parametrisierte Typen“. Die Idee dahinter ist, zus?tzliche Variablen für Typen einzuführen. Diese Typ-Variablen repr?sentieren zum Zeitpunkt der Implementierung unbekannte Typen. Erst bei der Verwendung der Klassen, Schnittstellen und Methoden werden diese Typ-Variablen durch konkrete Typen ersetzt. Damit kann typsichere Programmierung meistens gew?hrleistet werden. Jedoch nicht immer.[1]

Ab Version 5.0 (?Tiger“, 2004 ver?ffentlicht) steht auch in der Programmiersprache Java mit den Generics ein syntaktisches Mittel für die generische Programmierung zur Verfügung. Damit lassen sich Klassen und Methoden (Methoden auch unabh?ngig von ihren Klassen) mit Typen parametrisieren. Damit werden der Sprache einige ?hnliche M?glichkeiten er?ffnet, die sich vergleichbar bei den Templates in C++ bieten.

Prinzipiell gibt es aber durchaus wesentliche Unterschiede. W?hrend in Java über die Schnittstelle der Typparameter parametrisiert wird, wird in C++ direkt über den Typ des Typparameters selbst parametrisiert. Der Quelltext eines C++-Templates muss für den Anwender (d. h. beim Einsetzen des Typparameters) verfügbar sein, w?hrend ein generischer Java-Typ auch als übersetzter Bytecode ver?ffentlicht werden kann. Für verschiedene konkret verwendete Typparameter produziert der Compiler duplizierten Zielcode.

Beispielsweise bietet die Funktion std::sort in C++ die M?glichkeit, alle Container zu sortieren, die bestimmte Methoden anbieten (hier speziell begin() und end(), die jeweils einen Iterator liefern) und deren Typparameter den 'operator<' implementiert (oder explizit eine andere Vergleichsfunktion angegeben wurde). Ein Nachteil, der sich durch dieses System ergibt, ist die (für den Programmierer!) schwierigere übersetzung. Der Compiler hat keine andere M?glichkeit, als den Typparameter in jedem Fall durch den geforderten konkreten Typ zu ersetzen und den ganzen Code erneut zu kompilieren.

Sehr leicht k?nnen bei unpassenden Typparametern und anderen Problemen komplizierte und unverst?ndliche Compiler-Meldungen entstehen, was einfach mit der Tatsache zusammenh?ngt, dass die konkreten Anforderungen an die Typparameter unbekannt sind. Die Arbeit mit C++-Templates erfordert deshalb eine lückenlose Dokumentation der Anforderungen an einen Typparameter. Durch Template-Metaprogrammierung k?nnen die meisten Anforderungen (Basisklasse, Vorhandensein von Methoden, Kopierbarkeit, Zuweisbarkeit etc.) auch in speziellen Konstrukten abgefragt werden, wodurch sich lesbarere Fehlermeldungen ergeben. Obgleich sie standardkonform sind, werden diese Konstrukte jedoch nicht von allen Compilern unterstützt.

Dagegen sind den generischen Klassen und Methoden in Java die Anforderungen (engl. constraints) an ihre eigenen Typparameter bekannt. Um eine Collection (ohne Comparator) zu sortieren, müssen die enthaltenen Elemente vom Typ Comparable sein, also dieses Interface implementiert haben. Der Compiler muss lediglich prüfen, ob der Typparameter ein Untertyp von Comparable ist, und kann damit schon sicherstellen, dass der Code korrekt ist (d. h. die erforderliche Methode compareTo verfügbar ist). Weiterhin wird ein und derselbe Code für alle konkreten Typen verwendet und nicht jedes Mal dupliziert.

Praktische Beispiele

[Bearbeiten | Quelltext bearbeiten]

Ein Programm verwendet eine ArrayList, um eine Liste von JButtons zu speichern.

Bisher war die ArrayList auf den Typ Object fixiert:

List list = new ArrayList();
list.add(new JButton("Button 1"));
list.add(new JButton("Button 2"));
list.add(new JButton("Button 3"));
list.add(new JButton("Button 4"));
list.add(new JButton("Button 5"));

for (int i = 0; i < list.size(); i++) {
    JButton button = (JButton) list.get(i);
    button.setBackground(Color.white);
}

Man beachte die notwendige explizite Typumwandlung (auch ?Cast“ genannt) sowie die Typunsicherheit, die damit verbunden ist. Man k?nnte versehentlich ein Objekt in der ArrayList speichern, das keine Instanz der Klasse JButton ist. Die Information über den genauen Typ geht beim Einfügen in die Liste verloren, der Compiler kann also nicht verhindern, dass zur Laufzeit bei der expliziten Typumwandlung von JButton eine ClassCastException auftritt.

Mit generischen Typen ist in Java Folgendes m?glich:

List<JButton> list = new ArrayList<JButton>();
list.add(new JButton("Button 1"));
list.add(new JButton("Button 2"));
list.add(new JButton("Button 3"));
list.add(new JButton("Button 4"));
list.add(new JButton("Button 5"));

for (int i = 0; i < list.size(); i++)
    list.get(i).setBackground(Color.white);

Beim Auslesen ist nun keine explizite Typumwandlung mehr notwendig, beim Speichern ist es nur noch m?glich, JButtons in der ArrayList list abzulegen.

Ab Java7 ist die Instanzierung generischer Typen vereinfacht worden. Die erste Zeile in obigem Beispiel kann seit Java 7 folgenderma?en geschrieben werden:

List<JButton> list = new ArrayList<>();

Die beiden leeren spitzen Klammern werden aufgrund ihrer Form auch als Diamant-Operator (englisch Diamond-Operator) bezeichnet.[2][3]

Durch Kombination von generischen Typen mit den erweiterten For-Schleifen l?sst sich obiges Beispiel kürzer fassen:

List<JButton> list = new ArrayList<>();
list.add(new JButton("Button 1"));
list.add(new JButton("Button 2"));
list.add(new JButton("Button 3"));
list.add(new JButton("Button 4"));
list.add(new JButton("Button 5"));

for (JButton b: list)
    b.setBackground(Color.white);

Ein Beispiel für eine generische Klasse, die zwei Objekte von beliebigem, aber einander gleichem Typ beinhaltet, liefert der folgende Beispielcode:

public class DoubleObject<T> {
    private T object1;
    private T object2;

    public DoubleObject(T object1, T object2) {
        this.object1 = object1;
        this.object2 = object2;
    }

    public String toString() {
        return this.object1 + ", " + this.object2;
    }

    public static void main(String[] args) {
        DoubleObject<String> s = new DoubleObject<>("abc", "def");
        DoubleObject<Integer> i = new DoubleObject<>(123, 456);
        System.out.println("DoubleObject<String> s=" + s.toString());
        System.out.println("DoubleObject<Integer> i=" + i.toString());
    }
}

In Java k?nnen die nachfolgenden Varianzf?lle unterschieden werden. Sie bieten jeweils eine v?llig eigenst?ndige Flexibilit?t beim Umgang mit generischen Typen und sind jeweils absolut statisch typsicher.

Bei Invarianz ist der Typparameter eindeutig. Damit bietet Invarianz die gr??tm?gliche Freiheit bei der Benutzung des Typparameters. Beispielsweise sind für die Elemente einer ArrayList<Integer> alle Aktionen erlaubt, die auch bei der direkten Benutzung eines einzelnen Integers erlaubt sind (inklusive Autoboxing). Beispiel:

List<Integer> list = new ArrayList<Integer>();
// ...
Integer x = list.get(index);
list.get(index).methodeVonInteger();
list.set(index, 98347); // Autoboxing, entspricht Integer.valueOf(98347)
int y = list.get(index); // Auto-Unboxing

Diese M?glichkeiten werden mit wenig Flexibilit?t bei der Zuweisung von Objekten der generischen Klasse selbst erkauft. Beispielsweise ist Folgendes nicht erlaubt:

List<Number> list = new ArrayList<Integer>();

und das, obwohl Integer von Number abgeleitet ist. Der Grund liegt darin, dass der Compiler hier nicht mehr sicherstellen kann, dass keine Typfehler auftreten. Mit Arrays, die eine solche Zuweisung erlauben, hat man schlechte Erfahrungen gemacht:

// OK, Integer[] ist abgeleitet von Number[]
Number[] array = new Integer[10];

// ArrayStoreException zur Laufzeit: Double -> Integer sind nicht
// zuweisungskompatibel
array[0] = new Double(5.0);

Man bezeichnet Arrays als kovariant, was besagt:

Aus T extends V folgt: T[] extends V[]

oder allgemeiner:

Aus T extends V folgt: GenerischerTyp<T> extends GenerischerTyp<V>

Es verh?lt sich also der Array-Typ bzgl. der Vererbungshierarchie genauso wie der Typparameter. Kovarianz ist auch mit generischen Typen m?glich, allerdings nur mit Einschr?nkungen, so dass Typfehler zur Kompilierzeit ausgeschlossen werden k?nnen.

Referenzen müssen mit der Syntax ? extends T explizit als kovariant gekennzeichnet werden. T hei?t upper typebound, also der allgemeinste Typparameter, der erlaubt ist.

List<? extends Number> list;
list = new ArrayList<Double>();
list = new ArrayList<Long>();
list = new ArrayList<Integer>();

// Typfehler vom Compiler
list.set(index, myInteger);

// OK aber Warnung vom Compiler: unchecked cast
((List<Integer>) list).set(index, myInteger);

Das Ablegen von Elementen in diesen Listen ist nicht m?glich, da dies, wie oben beschrieben, nicht typsicher ist (Ausnahme: null kann abgelegt werden). Bereits zur Kompilierzeit tritt ein Fehler auf. Allgemeiner gesagt, ist die Zuweisung

?? extends T

nicht erlaubt.

M?glich dagegen ist das Auslesen von Elementen:

Number n = list.get(index); // OK
Integer i = list.get(index); // Typfehler: Es muss sich bei '? extends Number'
                             // nicht um ein Integer handeln.
Integer j = (Integer) list.get(index); // OK

Die Zuweisung

? extends TT (oder Basisklasse)

ist also erlaubt, nicht aber die Zuweisung

? extends Tabgeleitet von T

Generics bieten also wie Arrays kovariantes Verhalten, verbieten aber alle Operationen, die typunsicher sind.

Kontravarianz bezeichnet das Verhalten der Vererbungshierarchie des generischen Typs entgegen der Hierarchie seines Typparameters. übertragen auf das obige Beispiel würde das bedeuten: Eine Liste<Number> w?re zuweisungskompatibel zu einer Liste<Double>. Dies wird folgenderma?en bewerkstelligt:

List<? super Double> list;
list = new ArrayList<Number>();
list = new ArrayList<Double>();
list = new ArrayList<Object>();

Ein Objekt, das sich kontravariant verh?lt, darf keine Annahmen darüber machen, inwiefern ein Element vom Typ V von T abgeleitet ist, wobei T der lower Typebound ist (im Beispiel von ? super Double ist T Double). Deshalb kann aus den obigen Listen nicht gelesen werden:

// Fehler: 'list' k?nnte vom Typ List<Object> sein
Number x = list.get(index);

// Fehler: 'list' k?nnte List<Object> oder List<Number> sein
Double x = list.get(index);

// Die einzige Ausnahme: Objects sind auf jeden Fall in der Liste
Object x = list.get(index);

Nicht erlaubt, da nicht typsicher, ist also die Zuweisung ? super T → (abgeleitet von Object)

Unschwer zu erraten: Im Gegenzug kann in eine solche Liste ein Element abgelegt werden:

List<? super Number> list;
list.add(new Double(3.0)); // OK: 'list' hat immer den Typ List<Number>
                           // oder List<Basisklasse von Number>. Damit
                           // ist die Zuweisung Double -> T immer erlaubt.

Uneingeschr?nkte parametrische Polymorphie

[Bearbeiten | Quelltext bearbeiten]

Zu guter Letzt bieten Generics noch g?nzlich polymorphes Verhalten an. Hierbei kann keinerlei Aussage über die Typparameter gemacht werden, denn es wird in beide Richtungen keine Grenze angegeben. Dafür wurde die Wildcard definiert. Sie wird durch ein Fragezeichen repr?sentiert.

List<?> list;
list = new ArrayList<Integer>();
list = new ArrayList<Object>();
list = new ArrayList<String>();
// ...

Der Typparameter selbst kann hierbei nicht genutzt werden, da keine Aussage m?glich ist. Lediglich die Zuweisung T → Object ist erlaubt, da T auf jeden Fall ein Object ist. Im Gegenzug ist garantiert, dass der Code mit allen Ts arbeiten kann.

Nützlich kann so etwas sein, wenn man nur mit dem generischen Typ arbeitet:

// Keine Informationen über den Typparameter n?tig, kann ''beliebige'' Listen
// aufnehmen.
int readSize(List<?> list) {
    return list.size();
}

Zur Verdeutlichung, dass hier Wildcards unn?tig sind, und es eigentlich gar nicht um irgendeine Varianz geht, sei folgende Implementierung der obigen Funktion angegeben:

<T> int readSize(List<T> list) {
    return list.size();
}

Einzelnachweise

[Bearbeiten | Quelltext bearbeiten]
  1. Nada Amin, Ross Tate: Java and Scala’s Type Systems are Unsound: The Existential Crisis of Null Pointers. In: ACM (Hrsg.): OOPSLA 2016. New York 2016, ISBN 978-1-4503-4444-9, S. 838–848 (englisch, githubusercontent.com [PDF; 215 kB; abgerufen am 31. M?rz 2017]).
  2. Joachim Goll, Cornelia Heinisch: Java als erste Programmiersprache: Grundkurs für Hochschulen. 8. Auflage. Springer, Wiesbaden 2016, ISBN 978-3-658-12117-4, S. 725.
  3. Reinhard Schiedermeier: Programmieren mit Java. 2. Auflage. Pearson Studium, München 2010, ISBN 978-3-86894-031-2, S. 375.
黄精为什么要九蒸九晒 px是什么意思 什么是化合物 1938年属什么生肖属相 为什么叫五七干校
区间放量是什么意思 耐力是什么意思 气是什么意思 孔雀的尾巴像什么 有什么花
梅毒的病原体是什么 晒伤擦什么药 海水倒灌是什么意思 3p什么意思 csf是什么意思
什么人容易得脑梗 中耳炎用什么药最好 夏天吃什么水果比较好 什么茶女人长期喝最好 人参果不能和什么一起吃
肠胃不舒服挂什么科hcv7jop9ns5r.cn 微创手术是什么意思hcv9jop6ns7r.cn 喜悦之情溢于言表什么意思hcv8jop3ns3r.cn 低血钾吃什么补上来的快hcv8jop3ns4r.cn 做宫颈筛查能查出什么hcv9jop0ns8r.cn
10015是什么电话hcv9jop5ns6r.cn ls是什么牌子hcv9jop2ns5r.cn 端午节安康是什么意思shenchushe.com 什么是热辐射hcv9jop3ns1r.cn 三观是什么hcv8jop7ns6r.cn
罗汉果泡水喝有什么作用hcv9jop8ns1r.cn 为什么眼睛会红hcv9jop5ns8r.cn 什么什么不得hcv8jop8ns2r.cn 蛋白粉什么时候吃hcv8jop2ns7r.cn 古灵精怪是什么意思hcv8jop7ns0r.cn
买盘和卖盘是什么意思hcv9jop0ns9r.cn 看食道挂什么科室hcv8jop5ns1r.cn 4月9号是什么星座hcv9jop0ns3r.cn 乙肝表面抗体高是什么意思hcv7jop4ns7r.cn 乳糖醇是什么hcv8jop3ns4r.cn
百度