学习路线
本文是Java高级编程精华笔记,是对菜鸟教程中Java面向对象和Java高级编程的重要章节进行了学习,整理形成的学习笔记,知识图谱如下图所示:

如果想对Java深入学习,可以参考阿里巴巴的技术图谱:
https://developer.aliyun.com/graph/java

继承
Java使用extends关键字来声明继承:
class 父类 {}class 子类 extends 父类 {}
示例,子类企鹅和子类老鼠继承父类动物:
//父类:动物public class Animal {private String name;private int id;public Animal(String myName, int myid) {name = myName;id = myid;}public void eat() {System.out.println(name + "正在吃");}public void sleep() {System.out.println(name + "正在睡");}public void introduction() {System.out.println("大家好!我是" + id + "号" + name + ".");}}
//子类:企鹅public class Penguin extends Animal {public Penguin(String myName, int myid) {super(myName, myid);}}
//子类:老鼠public class Mouse extends Animal {public Mouse(String myName, int myid) {super(myName, myid);}}
Java只支持单继承,不支持多继承,但可以多重继承:

- 子类会继承父类的非private属性、方法。
- 子类可以扩展自己的属性、方法。
- 子类可以覆盖父类的方法,用自己的方式实现。
也就是,你的是我的,我的还是我的,我还可以改变你的。
- 构造器,子类不会继承父类,而且如果父类的构造器有参数,子类必须通过
super关键字显式调用。
也就是,你老子始终是你老子。
implements关键字
前面说到了Java使用extends声明继承类,而implements用来声明实现接口,并且可以同时实现多个接口。
public interface A {public void eat();public void sleep();}public interface B {public void show();}public class C implements A,B {}
super和this关键字
super:用来实现对父类成员的访问。
this:指向自己的引用。
示例:
class Animal {void eat() {System.out.println("animal : eat");}}class Dog extends Animal {void eat() {System.out.println("dog : eat");}void eatTest() {this.eat(); // this 调用自己的方法super.eat(); // super 调用父类方法}}public class Test {public static void main(String[] args) {Animal a = new Animal();a.eat();Dog d = new Dog();d.eatTest();}}
final关键字
如果修饰类,则表示类不能被继承。如果修饰方法,则表示方法不能被子类重写。
重写与重载
重写与重载的区别可以通过下面这张图来看:

重写就是子类覆盖父类,方法名和参数都一样:

重载就是在一个类里面的多个方法,方法名相同,参数不同。调用时根据入参匹配到不同的方法:

多态
多态是同一个行为具有多个不同表现形式或形态的能力。重写可以看做是父类和子类之间多态性的一种表现(重载可以理解成多态的具体表现形式),如图所示:

class Shape {void draw() {}}class Circle extends Shape {void draw() {System.out.println("Circle.draw()");}}class Square extends Shape {void draw() {System.out.println("Square.draw()");}}class Triangle extends Shape {void draw() {System.out.println("Triangle.draw()");}}
多态存在有三个必要条件:
- 继承
- 重写
- 父类引用指向子类对象:
Parent p = new Child();
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
多态有三种实现方式:
- 重写
- 接口
- 抽象类和抽象方法
抽象类
抽象类更普通类的区别在于,它不能实例化对象,只能被继承使用。抽象类使用abstract关键字定义:
public abstract class Employee{private String name;private String address;private int number;public Employee(String name, String address, int number){System.out.println("Constructing an Employee");this.name = name;this.address = address;this.number = number;}public double computePay(){System.out.println("Inside Employee computePay");return 0.0;}public void mailCheck(){System.out.println("Mailing a check to " + this.name+ " " + this.address);}public String toString(){return name + " " + address + " " + number;}public String getName(){return name;}public String getAddress(){return address;}public void setAddress(String newAddress){address = newAddress;}public int getNumber(){return number;}}
抽象方法
抽象类里面既可以定义普通方法,也可以定义抽象方法:
public abstract class Employee{private String name;private String address;private int number;public abstract double computePay();}
抽象方法也是通过abstract关键字定义,只有方法名,没有方法体(方法名后面是分号而不是花括号),具体实现由它的子类确定。
抽象方法最终必须被重写了才能在实例化对象中使用。如果一个类继承了带有抽象方法的抽象类,那么这个类要么也是抽象类,要么就必须重写抽象方法。
接口
接口不是类,它们属于不同的概念。接口通过interface关键字来定义:
public interface Animal {public void eat();public void travel();}
- 接口和接口中的方法是隐式抽象的,不必使用
abstract关键字。 - 接口中的方法都是
public。
类使用implements关键字实现接口:
public class MammalInt implements Animal{public void eat(){System.out.println("Mammal eats");}public void travel(){System.out.println("Mammal travels");}public int noOfLegs(){return 0;}public static void main(String args[]){MammalInt m = new MammalInt();m.eat();m.travel();}}
类必须实现接口里面的所有方法,否则会编译失败。只有抽象类才可以不实现接口的方法。
一个接口能继承另一个接口,接口的继承也是使用extends关键字:
// 文件名: Sports.javapublic interface Sports{public void setHomeTeam(String name);public void setVisitingTeam(String name);}// 文件名: Football.javapublic interface Football extends Sports{public void homeTeamScored(int points);public void visitingTeamScored(int points);public void endOfQuarter(int quarter);}// 文件名: Hockey.javapublic interface Hockey extends Sports{public void homeGoalScored();public void visitingGoalScored();public void endOfPeriod(int period);public void overtimePeriod(int ot);}
并且接口支持多继承:
public interface Hockey extends Sports, Event
实现了子接口的类,需要同时实现所有父接口中的方法。
接口里面也可以没有方法:
package java.util;public interface EventListener{}
它的主要目的是:
- 建立一个公共的父接口。
- 让实现它的类属于一个特定的类型。
枚举
枚举是一种特殊的类,一般用来表示一组常量。枚举使用enum关键字来定义,常量使用逗号,分隔:
enum Color{RED, GREEN, BLUE;}public class Test{// 执行输出结果public static void main(String[] args){Color c1 = Color.RED;System.out.println(c1);}}
枚举也可以声明在内部类中:
public class Test{enum Color{RED, GREEN, BLUE;}// 执行输出结果public static void main(String[] args){Color c1 = Color.RED;System.out.println(c1);}}
枚举可以使用for语句遍历:
enum Color{RED, GREEN, BLUE;}public class MyClass {public static void main(String[] args) {for (Color myVar : Color.values()) {System.out.println(myVar);}}}
也可以用在switch语句中:
enum Color{RED, GREEN, BLUE;}public class MyClass {public static void main(String[] args) {Color myVar = Color.BLUE;switch(myVar) {case RED:System.out.println("红色");break;case GREEN:System.out.println("绿色");break;case BLUE:System.out.println("蓝色");break;}}}
enum定义的枚举默认继承了java.lang.Enum类,具有3个方法:
values(),返回枚举中所有常量。ordinal(),返回常量的索引。valueOf(),返回指定字符串值的常量。
enum Color{RED, GREEN, BLUE;}public class Test{public static void main(String[] args){// 调用 values()Color[] arr = Color.values();// 迭代枚举for (Color col : arr){// 查看索引System.out.println(col + " at index " + col.ordinal());}// 使用 valueOf() 返回枚举常量,不存在的会报错 IllegalArgumentExceptionSystem.out.println(Color.valueOf("RED"));}}
枚举跟普通类一样可以定义变量、方法和构造函数:
enum Color{RED, GREEN, BLUE;// 构造函数private Color(){System.out.println("Constructor called for : " + this.toString());}public void colorInfo(){System.out.println("Universal Color");}}public class Test{// 输出public static void main(String[] args){Color c1 = Color.RED;System.out.println(c1);c1.colorInfo();}}
输出:
Constructor called for : REDConstructor called for : GREENConstructor called for : BLUEREDUniversal Color
包
包可以理解为类的目录,使用package关键字定义:
package com.runoob;public class Runoob {}
一个公司一般使用它互联网域名的倒序形式来作为它的包名,比如runoob.com,所有的包名都以com.runoob开头。
同一个包中的类可以直接访问,而访问不同的包需要先import。
//导入包下所有类import payroll.*;//导入包下某个类import payroll.Employee;
集合

集合(Collections)和数组(Arrays)的区别:
- 长度区别:数组固定;集合可变。
- 内容区别:数组既可以是基本类型,也可以是引用类型;集合只能是引用类型。
- 存储类型:数组只能存储一种类型;集合可以存储不同类型(但一般也只存储一种类型)
集合中只能使用基本类型的包装类:
集合主要包括两种类型的容器:Collection和Map,Collection是元素集合,Map是键值对。
集合有3个层次:

接口代表集合的抽象数据类型,我们重点关注实现类和算法,尤其是4种常用实现类:ArrayList、LinkedList、HashSet、HashMap。
ArrayList
ArrayList相当于可以动态修改的数组。它继承了AbstractList,并实现了List接口:

定义
import java.util.ArrayList; // 引入 ArrayList 类ArrayList<E> objectName = new ArrayList<>(); // 初始化
添加元素
使用add()方法:
import java.util.ArrayList;public class RunoobTest {public static void main(String[] args) {ArrayList<String> sites = new ArrayList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");System.out.println(sites);}}
访问元素
使用get()方法:
import java.util.ArrayList;public class RunoobTest {public static void main(String[] args) {ArrayList<String> sites = new ArrayList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");System.out.println(sites.get(1)); // 访问第二个元素}}
修改元素
使用set()方法:
import java.util.ArrayList;public class RunoobTest {public static void main(String[] args) {ArrayList<String> sites = new ArrayList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");sites.set(2, "Wiki"); // 第一个参数为索引位置,第二个为要修改的值System.out.println(sites);}}
删除元素
使用remove()方法:
import java.util.ArrayList;public class RunoobTest {public static void main(String[] args) {ArrayList<String> sites = new ArrayList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");sites.remove(3); // 删除第四个元素System.out.println(sites);}}
计算大小
使用size()方法:
import java.util.ArrayList;public class RunoobTest {public static void main(String[] args) {ArrayList<String> sites = new ArrayList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");System.out.println(sites.size());}}
迭代遍历
for循环:
import java.util.ArrayList;public class RunoobTest {public static void main(String[] args) {ArrayList<String> sites = new ArrayList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");for (int i = 0; i < sites.size(); i++) {System.out.println(sites.get(i));}}}
for-each语句:
import java.util.ArrayList;public class RunoobTest {public static void main(String[] args) {ArrayList<String> sites = new ArrayList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");for (String i : sites) {System.out.println(i);}}}
排序
使用Collections.sort()方法:
import java.util.ArrayList;import java.util.Collections; // 引入 Collections 类public class RunoobTest {public static void main(String[] args) {ArrayList<String> sites = new ArrayList<String>();sites.add("Taobao");sites.add("Wiki");sites.add("Runoob");sites.add("Weibo");sites.add("Google");Collections.sort(sites); // 字母排序for (String i : sites) {System.out.println(i);}}}
LinkedList
LinkedList是链表,分为单向链表和双向链表。
单向链表包含2个值,①当前节点的值,②下一个节点的链接:

双向链表包含3个值,①当前节点的值,②向前的节点链接,③向后的节点链接:

与ArrayList相比,LinkedList的增加和删除的效率更高,而修改和查找的效率更低。
快速记忆法:
增删:LinkedList
改查:ArrayList
LinkedList继承了AbstractSequentialList,实现了很多接口:

定义
// 引入 LinkedList 类import java.util.LinkedList;LinkedList<E> list = new LinkedList<E>(); // 普通创建方法或者LinkedList<E> list = new LinkedList(Collection<? extends E> c); // 使用集合创建链表
添加元素
import java.util.LinkedList;public class RunoobTest {public static void main(String[] args) {LinkedList<String> sites = new LinkedList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");System.out.println(sites);}}
在列表开头添加元素
使用addFirst()方法:
// 引入 LinkedList 类import java.util.LinkedList;public class RunoobTest {public static void main(String[] args) {LinkedList<String> sites = new LinkedList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");// 使用 addFirst() 在头部添加元素sites.addFirst("Wiki");System.out.println(sites);}}
在列表结尾添加元素
使用addLast()方法:
// 引入 LinkedList 类import java.util.LinkedList;public class RunoobTest {public static void main(String[] args) {LinkedList<String> sites = new LinkedList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");// 使用 addLast() 在尾部添加元素sites.addLast("Wiki");System.out.println(sites);}}
在列表开头移除元素
使用removeFirst()方法:
// 引入 LinkedList 类import java.util.LinkedList;public class RunoobTest {public static void main(String[] args) {LinkedList<String> sites = new LinkedList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");// 使用 removeFirst() 移除头部元素sites.removeFirst();System.out.println(sites);}}
在列表结果移除元素
使用removeLast()方法:
// 引入 LinkedList 类import java.util.LinkedList;public class RunoobTest {public static void main(String[] args) {LinkedList<String> sites = new LinkedList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");// 使用 removeLast() 移除尾部元素sites.removeLast();System.out.println(sites);}}
获取列表开头的元素
使用getFirst()方法:
// 引入 LinkedList 类import java.util.LinkedList;public class RunoobTest {public static void main(String[] args) {LinkedList<String> sites = new LinkedList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");// 使用 getFirst() 获取头部元素System.out.println(sites.getFirst());}}
获取列表结尾的元素
使用getLast()方法:
// 引入 LinkedList 类import java.util.LinkedList;public class RunoobTest {public static void main(String[] args) {LinkedList<String> sites = new LinkedList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");// 使用 getLast() 获取尾部元素System.out.println(sites.getLast());}}
迭代元素
可以使用for循环:
// 引入 LinkedList 类import java.util.LinkedList;public class RunoobTest {public static void main(String[] args) {LinkedList<String> sites = new LinkedList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");for (int size = sites.size(), i = 0; i < size; i++) {System.out.println(sites.get(i));}}}
也可以使用for-each语句:
// 引入 LinkedList 类import java.util.LinkedList;public class RunoobTest {public static void main(String[] args) {LinkedList<String> sites = new LinkedList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");for (String i : sites) {System.out.println(i);}}}
HashMap
HashMap叫做哈希表,相当于键值对(key-value)的字典。它继承于AbstractMap,实现了Map、Cloneable、java.io.Serializable接口:

定义
import java.util.HashMap; // 引入 HashMap 类HashMap<Integer, String> Sites = new HashMap<>();
HashMap中只能使用基本类型的包装类,因为HashMap也是集合一种,在集合中只能使用包装类。
添加元素
使用put()方法:
// 引入 HashMap 类import java.util.HashMap;public class RunoobTest {public static void main(String[] args) {// 创建 HashMap 对象 SitesHashMap<Integer, String> Sites = new HashMap<Integer, String>();// 添加键值对Sites.put(1, "Google");Sites.put(2, "Runoob");Sites.put(3, "Taobao");Sites.put(4, "Zhihu");System.out.println(Sites);}}
访问元素
使用get()方法:
// 引入 HashMap 类import java.util.HashMap;public class RunoobTest {public static void main(String[] args) {// 创建 HashMap 对象 SitesHashMap<Integer, String> Sites = new HashMap<Integer, String>();// 添加键值对Sites.put(1, "Google");Sites.put(2, "Runoob");Sites.put(3, "Taobao");Sites.put(4, "Zhihu");System.out.println(Sites.get(3));}}
删除元素
使用remove()方法:
// 引入 HashMap 类import java.util.HashMap;public class RunoobTest {public static void main(String[] args) {// 创建 HashMap 对象 SitesHashMap<Integer, String> Sites = new HashMap<Integer, String>();// 添加键值对Sites.put(1, "Google");Sites.put(2, "Runoob");Sites.put(3, "Taobao");Sites.put(4, "Zhihu");Sites.remove(4);System.out.println(Sites);}}
删除所有键值对
使用clear()方法:
// 引入 HashMap 类import java.util.HashMap;public class RunoobTest {public static void main(String[] args) {// 创建 HashMap 对象 SitesHashMap<Integer, String> Sites = new HashMap<Integer, String>();// 添加键值对Sites.put(1, "Google");Sites.put(2, "Runoob");Sites.put(3, "Taobao");Sites.put(4, "Zhihu");Sites.clear();System.out.println(Sites);}}
计算大小
使用size()方法:
// 引入 HashMap 类import java.util.HashMap;public class RunoobTest {public static void main(String[] args) {// 创建 HashMap 对象 SitesHashMap<Integer, String> Sites = new HashMap<Integer, String>();// 添加键值对Sites.put(1, "Google");Sites.put(2, "Runoob");Sites.put(3, "Taobao");Sites.put(4, "Zhihu");System.out.println(Sites.size());}}
迭代
推荐使用entrySet:
Map<Integer, Integer> map = new HashMap<Integer, Integer>();for(Map.Entry<Integer, Integer> entry : map.entrySet()){System.out.println("key = " + entry.getKey() + ", value = " + entry.getValue())}
也可以用其他方式:
// 引入 HashMap 类import java.util.HashMap;public class RunoobTest {public static void main(String[] args) {// 创建 HashMap 对象 SitesHashMap<Integer, String> Sites = new HashMap<Integer, String>();// 添加键值对Sites.put(1, "Google");Sites.put(2, "Runoob");Sites.put(3, "Taobao");Sites.put(4, "Zhihu");// 输出 key 和 valuefor (Integer i : Sites.keySet()) {System.out.println("key: " + i + " value: " + Sites.get(i));}// 返回所有 value 值for(String value: Sites.values()) {// 输出每一个valueSystem.out.print(value + ", ");}}}
HashSet
HashSet是一个不允许有重复元素的集合。它实现了Set接口:

定义
import java.util.HashSet; // 引入 HashSet 类HashSet<String> sites = new HashSet<String>();
添加元素
// 引入 HashSet 类import java.util.HashSet;public class RunoobTest {public static void main(String[] args) {HashSet<String> sites = new HashSet<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Zhihu");sites.add("Runoob"); // 重复的元素不会被添加System.out.println(sites);}}
判断元素是否存在
使用contains()方法:
// 引入 HashSet 类import java.util.HashSet;public class RunoobTest {public static void main(String[] args) {HashSet<String> sites = new HashSet<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Zhihu");sites.add("Runoob"); // 重复的元素不会被添加System.out.println(sites.contains("Taobao"));}}
删除元素
使用remove()方法:
// 引入 HashSet 类import java.util.HashSet;public class RunoobTest {public static void main(String[] args) {HashSet<String> sites = new HashSet<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Zhihu");sites.add("Runoob"); // 重复的元素不会被添加sites.remove("Taobao"); // 删除元素,删除成功返回 true,否则为 falseSystem.out.println(sites);}}
删除所有元素
使用clear()方法:
// 引入 HashSet 类import java.util.HashSet;public class RunoobTest {public static void main(String[] args) {HashSet<String> sites = new HashSet<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Zhihu");sites.add("Runoob"); // 重复的元素不会被添加sites.clear();System.out.println(sites);}}
计算大小
使用size()方法:
// 引入 HashSet 类import java.util.HashSet;public class RunoobTest {public static void main(String[] args) {HashSet<String> sites = new HashSet<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Zhihu");sites.add("Runoob"); // 重复的元素不会被添加System.out.println(sites.size());}}
迭代
使用for-each语句:
// 引入 HashSet 类import java.util.HashSet;public class RunoobTest {public static void main(String[] args) {HashSet<String> sites = new HashSet<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Zhihu");sites.add("Runoob"); // 重复的元素不会被添加for (String i : sites) {System.out.println(i);}}}
Iterator
Iterator是迭代器,可以用来迭代ArrayList等集合。迭代器主要有3个方法:
- next():返回下一个元素,并更新迭代器状态。
- hasNext():检查是否还有元素。
- remove():删除元素。
获取集合的迭代器
// 引入 ArrayList 和 Iterator 类import java.util.ArrayList;import java.util.Iterator;public class RunoobTest {public static void main(String[] args) {// 创建集合ArrayList<String> sites = new ArrayList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Zhihu");// 获取迭代器Iterator<String> it = sites.iterator();// 输出集合中的第一个元素System.out.println(it.next());}}
迭代器遍历集合
// 引入 ArrayList 和 Iterator 类import java.util.ArrayList;import java.util.Iterator;public class RunoobTest {public static void main(String[] args) {// 创建集合ArrayList<String> sites = new ArrayList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Zhihu");// 获取迭代器Iterator<String> it = sites.iterator();// 输出集合中的所有元素while(it.hasNext()) {System.out.println(it.next());}}}
删除元素
// 引入 ArrayList 和 Iterator 类import java.util.ArrayList;import java.util.Iterator;public class RunoobTest {public static void main(String[] args) {ArrayList<Integer> numbers = new ArrayList<Integer>();numbers.add(12);numbers.add(8);numbers.add(2);numbers.add(23);Iterator<Integer> it = numbers.iterator();while(it.hasNext()) {Integer i = it.next();if(i < 10) {it.remove(); // 删除小于 10 的元素}}System.out.println(numbers);}}
泛型
泛型可以理解为通用类型,不是具体某个类型,而是泛指某些类型。
Java中的泛型标记符如下所示:
- E - Element (在集合中使用,因为集合中存放的是元素)
- T - Type(Java 类)
- K - Key(键)
- V - Value(值)
- N - Number(数值类型)
- ? - 表示不确定的 java 类型
示例:
public class GenericMethodTest {// 泛型方法 printArraypublic static <E> void printArray(E[] inputArray) {// 输出数组元素for (E element : inputArray) {System.out.printf("%s ", element);}System.out.println();}public static void main(String args[]) {// 创建不同类型数组: Integer, Double 和 CharacterInteger[] intArray = {1, 2, 3, 4, 5};Double[] doubleArray = {1.1, 2.2, 3.3, 4.4};Character[] charArray = {'H', 'E', 'L', 'L', 'O'};System.out.println("整型数组元素为:");printArray(intArray); // 传递一个整型数组System.out.println("\n双精度型数组元素为:");printArray(doubleArray); // 传递一个双精度型数组System.out.println("\n字符型数组元素为:");printArray(charArray); // 传递一个字符型数组}}
其中<E>放在方法前表明这是一个泛型方法。可以通过extends限制类型的范围:
public class MaximumTest{// 比较三个值并返回最大值//java.lang.Comparable是个接口,包含一个compareTo()方法public static <T extends Comparable<T>> T maximum(T x, T y, T z){T max = x; // 假设x是初始最大值if ( y.compareTo( max ) > 0 ){max = y; //y 更大}if ( z.compareTo( max ) > 0 ){max = z; // 现在 z 更大}return max; // 返回最大对象}public static void main( String args[] ){System.out.printf( "%d, %d 和 %d 中最大的数为 %d\n\n",3, 4, 5, maximum( 3, 4, 5 ) );System.out.printf( "%.1f, %.1f 和 %.1f 中最大的数为 %.1f\n\n",6.6, 8.8, 7.7, maximum( 6.6, 8.8, 7.7 ) );System.out.printf( "%s, %s 和 %s 中最大的数为 %s\n","pear","apple", "orange", maximum( "pear", "apple", "orange" ) );}}
除了泛型、泛型方法,还可以定义泛型类:
public class Box<T> {private T t;public void add(T t) {this.t = t;}public T get() {return t;}public static void main(String[] args) {Box<Integer> integerBox = new Box<Integer>();Box<String> stringBox = new Box<String>();integerBox.add(new Integer(10));stringBox.add(new String("菜鸟教程"));System.out.printf("整型值为 :%d\n\n", integerBox.get());System.out.printf("字符串为 :%s\n", stringBox.get());}}
?是类型通配符,比如List<?>在逻辑上是List<String>、List<Integer>等的父类:
import java.util.*;public class GenericTest {public static void main(String[] args) {List<String> name = new ArrayList<String>();List<Integer> age = new ArrayList<Integer>();List<Number> number = new ArrayList<Number>();name.add("icon");age.add(18);number.add(314);getData(name);getData(age);getData(number);}public static void getData(List<?> data) {System.out.println("data :" + data.get(0));}}
?也可以通过extends关键字来限定类型范围:
import java.util.*;public class GenericTest {public static void main(String[] args) {List<String> name = new ArrayList<String>();List<Integer> age = new ArrayList<Integer>();List<Number> number = new ArrayList<Number>();name.add("icon");age.add(18);number.add(314);//getUperNumber(name);//1getUperNumber(age);//2getUperNumber(number);//3}public static void getData(List<?> data) {System.out.println("data :" + data.get(0));}//只接受Number及其子类public static void getUperNumber(List<? extends Number> data) {System.out.println("data :" + data.get(0));}}
List<? extends Number表示只接受Number及其子类(指定上限)。此外还能通过List<? super Number>来表示只能接受Number及其父类(指定下限)。
参考资料:
Java面向对象 https://www.runoob.com/java/java-inheritance.html
Java高级编程 https://www.runoob.com/java/java-data-structures.html
Java集合超详解 https://blog.csdn.net/feiyanaffection/article/details/81394745

