zoukankan      html  css  js  c++  java
  • Java基础笔记

    对象基本要素

    状态

    数据成员

    行为

    • 方法成员
    • 访问控制(封装):public,private,protected

    类型

    • 对象是某个类(型)的
    • 通过之前的类型定义新的类型
      组合 : has-a
      继承 : is
    • 不同类型间的关系
    • 基本类型之间的转换关系
    • Autoboxing, unboxing
    • Upcasting, downcasting

    Java类型

    基本类型

    int double ...

    数组

    • 静态初始化
      int []a = {1,2};
      直接赋值
    • 动态初始化
      int []a = new int[5];
      元素初始化为0
    • 不规则数组
      int [][]a = {{1,2},{3,4,5},{7,8,9,10}};
      ——>a.lenth为3,且a[0][2]为空(未被初始化
    • 未知错误 int [] a = new int[3]{1,2,3};
    • 使用
      输出数组时,int []a = {1,2};
      System.out.println(a);出现乱码
      System.out.println(a[0]);输出1

    引用

    • 同一对象不同名字。不管使用哪个名字对 对象 进行修改,其他名字访问到的对象都是修改后的那个
    • 引用首先要初始化 new
    • 类class中的数据成员的引用:默认初始化为null

    不可变类型

    • 一旦创建不能改变
    • 不可变类型 String,Integer,Float等
      对比:可变类型:MyType,数组

    final 关键字

    不可变对象

    final 数据

    • 编译时为常数;一旦被赋值就不能被修改
    • static final仅有一个不可变的存储空间
    • final 成员在定义时可以不给初值
      必须在构造函数中初始化

    final 参数

    函数不能修改参数的引用

    final method

    不能被重写

    final class

    不能被继承

    Java控制结构

    Java操作符

    移位

    • 带符号 >>
    • 不带符号 >>>

    等于

    “==” 与 equals()

    字符串连接操作 +=

    Java控制语句

    循环 for each

    	int []a = {1, 2, 3, 4, 5};
    	for (int i : a)
    		System.out.println(i);
    

    静态成员

    静态方法

    static method() {}

    • 不用创建对象就可以调用
    • 不能使用需要 实例化 后才分配空间的变量/函数
    • 比如:main函数
    	class hi {
    		double d;
    		static void display() {
    			System.out.println(d);
    		}
    
    		public static void main(String []args) {
    			display();
    			hi.display();
    			hi s = new hi();
    			s.display();
    		}
    	}
    

    静态数据

    所有对象共享数据

    • static int i = 1;
      可以对i重新赋值,函数中使用到i的地方i值会全部改变,但是i的引用a,(如int a = i;) 值不变(为原来的i)
    • static int i; 初始化为0,可以重新赋值,等同于int i;
    • 不管何时引用,在什么对象后 .引用,都获得不变的值

    类的数据成员

    this关键字

    • 含义:在类的非静态方法中 , 返回调用该方法的对象的引用
    • 作用:
      区分参数名称与数据成员名称
      返回当前对象return this;
      作为其他方法的参数return OneClass.OneMethod(this)
    • 在构造函数中调用构造函数
      形式:this(...)
      出现在构造函数第一行
      只能调用一个构造函数
    • 静态方法无法使用this
      解决办法:传入this类型的参数
    public static void set(MyType t, double x) { t.d = x; }
    //对比
    void set(double x) { this.d = x; }
    

    super关键字

    • 每个子类对象都包含一个隐藏的父类对象
    • 在子类中 , super 用来指代父类对象的引用

    数据成员的初始化

    • 初始化的值
    • 初始化的顺序
    • 静态成员 / 非静态成员
    • 子类成员 / 父类成员
    • 构造函数
    • 所有数据成员初始化在构造函数调用前完成
    • 按照成员定义的顺序初始化

    类的方法

    构造函数

    • 名称与类名称相同
    • 无返回值
    • 为类的静态方法
    • 在子类构造函数调用前 , 首先调用父类构造函数
    • 带参数的构造函数,调用前依然先调用父类构造函数
    • 构造函数中不能重写
    public class MySubType extends MyType {
    	 public MySubType () {
    		super(1.0);//注意
    		System.out.println("In sub class");
    	}
    	public static void main(String [ ]args) {
    		MySubType ms = new MySubType();
    	}
    }
    

    重载 (overload)

    • 方法名相同 , 参数类型 / 数量不同
    • 区分:函数名 + 参数列表
    • 函数重载与基本类型的转换
      当转换不损失精度 (up-casting)
      调用参数类型 '' 最近 '' 的函数
      例如 : charint, byteshort, shortint, intlong, long
      float, floatdouble
    • 当转换损失精度 (down-casting)
      需要强制转换
    • 函数重载与 autoboxing/unboxing

    int and Integer 装箱/拆箱

    重写 (override)

    子类重新实现父类的方法 ( 同一个函数 )
    相同函数名 , 不同参数列表

    类的销毁

    • 对象占有的资源
    • 系统自动分配:
      new 操作时系统分配的内存
    • 程序显式分配:
      r.open();
    • 销毁对象占有的资源
      • 系统自动回收 ( 垃圾回收 ):
        new 操作时系统分配的内存
    • 程序显式回收
      r.colse();
    • 垃圾回收
      System.gc()
      通知JVM可以进行回收

    Java包

    • 创建包
    • package mypackage;在.java 文件首行
    • javac mypackage/MyType.java
      java mypackage.MyType
    • 使用包
      import mypackage.MyType;
    • 包内 名字空间 共享
    • jar包
    • 打包 包(packed package)
    • 将包 ( 目录 ) 变成文件c: create f: output to file
      (如:jar cf restaurant.jar restaurant

    访问控制

    package access

    • 同一个包中的类可以访问
      其他包中的类不能访问
    • 如果没有 package 语句 , java 默认当前目录中的
      java 文件属于同一个包

    public

    • 每个 .java 文件包含一个 public class, 且该 class 的名字等于 .java 文件名
    • 每个 .java 文件中除去 public class 外 , 其他的 class
      为 package access

    private

    • private 构造函数 : 统计该类有多少对象
    private MyType(int i1, double d1, char c1) {
    	i = i1; d = d1; c = c1;
    }
    public static int count= 0;
    public static MyType makeMyType(int i1, double d1, char c1) {
    	count++;
    	return new MyType(i1, d1, c1);
    }
    
    • private 构造函数 : 该类只有一个对象
    private static MyType mytype = new MyType(1, 1.0, 'a');
    public static MyType access() { return mytype; }
    

    protected

    • 可以被子类 / 同一包中的类访问 , 不能被其他类访问
    • 弱化的 private
    • 同时赋予 package access
      protected void set(double x) { d = x;}

    封装

    • 将易变的与稳定的部分区分开
    • 在满足需求的情况下 , 接口尽量简单

    类的复用

    组合 has-a

    将已有类作为新类的数据成员

    class Person {
         Name name;
         Age age;
         ...
    }
    class Name{...}
    class Age{...}
    

    继承 is-a

    新类 包含已有类 的所有数据与方法 , 并能增添修改(重写)

    extends关键字

    • 子类可以使用父类所有方法和数据成员
    • 子类可以定义新的方法和数据
    • 子类可以重写父类的方法
    class A {//父类 基类
    ...
    }
    public class B extends A {//子类
    ...
    }
    

    protected关键字

    super关键字

    Object class

    所有类都是它的子类

    Upcasting和多态

    Upcasting

    • 类型转换 : 父类的引用可以指向子类对象
    • 同一基类的不同子类可以被视为同一类型 ( 基类 )
    class A{ …}
    class B extends A{ …}
    A a = new A();
    B b = new B();
    A a = new B(); // upcasting
    //对比
    class A{ …}
    class B{ …}
    A a = new A();
    B b = new B();
    // A a = new B();compile error
    
    class Instrument {
    	public void play() {}
    	static void tune(Instrument i) {
    		i.play();
    	}
    }
    public class Wind extends Instrument {
    	public static void main(String[] args) {
    		Wind flute = new Wind();
    		Instrument.tune(flute);
    	}
    }
    

    多态

    • 参数可以代表不同的子类 , 并能
      正确调用它们的方法 ( 即 , 有多种表现形态 )
    • 子类重写了父类方法f()
    • 当使用父类引用访问子类对象时 , 调用 f() 将绑定到子类的方法

    动态绑定

    • 函数的调用在运行时才能确定
    • Java 中的所有方法都采用动态绑定 , 除了final static
    • 数据成员不动态绑定

    接口与抽象类

    抽象

    抽象方法

    • 仅提供方法的名称 , 参数和返回值
    • 没有具体实现
    • 需要子类重写后才有意义
    • 使用 abstract 关键字
    abstract class Instrument {
    	public abstract void play(int note) ;
    }
    public class Wind extends Instrument {
    	public void play (int note) {
    		System.out.println ("Wind.play()"+ n);
    	}
    }
    public class Stringed extends Instrument {
    	public void play(int note) {
    		System.out.println("Stringed.play()"+ n);
    	}
    }
    

    抽象类

    • 包含抽象方法的类
    • 不能创建对象(实例化),必须被继承
    • 是不完整的类

    接口

    相当于一个功能列表

    特点

    • 所有方法都是抽象方法,且默认为public(没有方法的实现)
    • 所有数据默认为final static
    • 没有代码重用 , 仅仅保留 upcasting 和多态
    • 所有实现该接口的类都具有接口提供的方法
    • 任何使用该接口类型的方法 , 都可以使用他的任何一种实现
    • 某种协议 (protocol)

    实现

    关键字interfaceimplements

    interface Instrument {
    	void play(int note) ;
    	String what();
    }
    class Stringed implements Instrument {
    	public void play(int note) {
    		System.out.println("Stringed.play()"+ n);
    	}
    	public String what() {return "Stringed";}
    }
    

    一个类实现多个接口

    class Seaplane implements Plane, Boat {...}
    对比
    error:class C extends A, B {...} //继承: 只能有一个父类

    扩展接口

    interface A {…}
    interface B extends A{…}
    interface D {…}
    interface D extends A,C{…}
    

    接口适配器

    没有深入接触

    内部类

    普通内部类

    关系

    • 定义在一个类的内部
    • 返回内部类的引用OutClassName.InnerClassName
    • 在内部类中访问外部类对象的引用
      OuterClassName.this
    public class Outer{
    	void f() { System.out.println(“Outer.f()”);}
    	class Inner{
    		public Outer g() {return Ourter.this;}
    	}
    	public Inner inner() { return new Inner(); }
    	public static void main(String []args){
    		Outer o = new Outer();
    		Outer.Inner i = o.inner();
    		i.g().f();
    	}
    }
    

    创建内部类的对象

    • 在外部类的方法中 : 直接创建
    • 其他地方 : OuterClassObject.new
    • 内部类的对象隐含了一个引用 , 指向包含它的外部类对象
    • 创建内部类对象前 , 需要有包含它的外部类对象
    • 内部类对象能够访问该外部对象的所有成员 / 方法
    public class Outer{
    	class Inner{}
    	public static void main(String []args){
    		Outer o = new Outer();
    		Outer.Inner i = o.new Inner();
    	}
    }
    

    匿名内部类

    • 没有名字
    • 没有构造函数
    • 同时定义和创建
    • 必须继承另一个类或者实现一个接口(不出现implements等关键词)
    • return new oneClassName() {...}(在{}中定义)
    public class Parcel{
    	public Contents contents(){
    		return new Contents() {
    			private int i = 11;
    			public int value() {return i;}
    		};//注意分号
    	}
    }
    interface Contents{
    	int value();
    }
    
    • 使用外部变量对匿名类数据成员初始化
      外部变量需要 final
    public class Parcel{
    	public Contents contents(final int v){
    		return new Contents() {
    			private int i = v;
    			public int value() {return i;}
    		}
    	}
    }
    

    嵌套类(不考)

    • 静态的内部类(无法访问外部类的非静态成员)
    • 不需要外部的对象就可创建(不包含指向外部类对象的引用)
    • 可以放入接口中

    内部类的作用

    • 多继承
      父类只能是一个普通类 / 抽象类
      可以通过多个内部类继承多个类 / 抽象类 / 接口
    • 闭包 (closure)
      带有自由变量的函数 + 被绑定的自由变量
    • 回调函数 (callbacks)
      函数指针

    容器

    • 动态添加/删除
    • import java.util.*;

    类型安全的

    • 泛型 (generic)
    • 定义容器为只能存放某种类型的对象,编译时才确定类型
    • 容器可以存放的类型为Object,这样任何类型的对象都能放入容器
    • 在确定了容器类型后 , Upcasting适用
    • 不能指定基本类型
    • 使用基本类型的wrapper(包装)
    • Autoboxing and unboxing
      compile error: ArrayList<int> a = new ArrayList<int>();
      ArrayList<Integer> a = new ArrayList<Integer>();

    输出容器

    容器重写了 toString() 方法 , 可以帮助可视化容器的内容

    Collection

    Collection is an interface
    用于存放一组对象

    List

    • List is an interface
    • 按照插入顺序排列(数组、链表)

    ArrayList

    • 可扩展数组
    • 适用于随机访问,插入删除较慢,浪费空间
    • 每次扩张或缩减数组长度时 , 保证新的数组有一半的可用空间
    • 构造函数
      ArrayList<E>();
      ArrayList<E>(int initialCapacity);
      ArrayList<E>(Collection<E> c);

    LinkedList

    • 双向链表
    • 适用于顺序访问,插入删除较快,无空间浪费
    • 实现List接口
    • 实现Queue接口
    • add(), remove(), element()
    • offer(), poll(), peek()
    • 构造函数
      LinkedList<E>();
      LinkedList<E>(Collection<E> c);
    • 方法
    • 返回链表首元素,若链表为空则抛出异常a.getFirst(); a.element();
    • 返回链表首元素,若链表为空则返回 nulla.peek();
    • 删除并返回链表首元素,若链表为空则抛出异常String s = a.remove(); String s = a.removeFirst();
    • 删除并返回链表首元素,若链表为空则返回 nullString s = a.poll();
    • 在链表头添加对象a.addFirst(“tiger”);
    • 在链表尾添加对象a.add(“cow”); a.addLast(“cow”); a.offer("cow")
    • 应用:Stack
    • 后进先出 (Last In First Out, LIFO)
    • push: 将一个对象入栈
    • pop: 从栈中取出一个元素

    接口

    • add()添加元素
    • remove()删除元素
    • get()返回第 i 个位置的元素
    • size()返回元素数量
    • contains()查询
    • indexOf()序号
    • subList()子表
    • isEmpty()是否为空
    • iterator()返回迭代器
    • listIterator()返回List迭代器
    • toArray()转为数组

    迭代器

    Iterable 接口
    • 提供 iterator() 返回迭代器
    • Collection 扩展了 Iterable 接口
    • foreach 语句
    • 对所有实现Iterable接口的类
    • 数组
    ListIterator
    • List 接口提供
    • 扩展了 Iterator
    • 双向遍历
    • hasNext(), hasPrevious()
    • next(), previous()

    Set

    • 集合(没有重复元素)
    • 没有对Collection接口扩展
    • 方法
    • put()
    • add(Object o), addAll(Collection<E> c)
    • remove(Object o), removeAll(Collection<E> c)
    • contains(Object o)
    • iterator()
    • size()
    • toArray()

    HashSet

    实现为 hash 表,查询较快(无序)

    TreeSet

    实现为查询树,较慢,按顺序排列(自动字典排序

    LinkedHashSet

    速度快,按照插入顺序排列

    Queue

    • 队列->先进先出
    • enqueue进队 ,dequeue出队
    • 应用:任务调度

    LinkedList

    PriorityQueue - 优先级队列

    • 每次出队时 , 选择优先级最高的对象
    • 队列中的对象可以比较优先级
    • 普通队列也可看成优先级队列 : 优先级为加入队列的时间
    • 自定义优先级
    • 构造函数
      PriorityQueue<E>(int initialCapacity, Comparator<E> comparator)
    • Comparator接口——定义两个元素的优先级关系
      包含方法compare(E e1,E e2)
      返回负数: 当 e1 优先级低于 e2
      返回正数: 当 e1 优先级高于 e2
      返回 0: 当 e1 优先级等于 e2
    • 方法
    • offer(Object o),add(Object o)将对象加入队列尾部
    • poll(),remove()弹出位于队首的对象
    • peek(),element()返回位于队首的对象 , 并不删除

    Map

    dictionary, associative array

    • HashMap a = new HashMap<T,T>();
    • Key-value对应
    • Key不重复,value可以重复
    • Map is an interface
    • 方法
    • 存入键值对put(K key, V value)
    • 返回键对应的值get(K key)
    • 是否包含键keycontainsKey(Object key)
    • 是否包含值 valuecontainsValue(Object value)
    • 返回键组成的 SetkeySet()
    • 返回值组成的 Collectionvalues()
    • 应用:单词出现次数

    HashMap

    实现为 hash 表 , 查询较块

    TreeMap

    实现为查询树 , 按顺序排列

    LinkedHashMap

    按照插入顺序排列

    异常处理

    错误处理场景

    1. 某方法中发现错误
    2. 中断当前执行路径
    3. 创建 / 捕捉 Exception 类对象
    4. 跳转到相应的异常处理代码段
    5. 在代码段中处理该异常

    语法

    抛出异常 : throw

    If (t == null) throw new NullPointerException();

    • 检查错误条件
    • 含义
    • 发生了一个异常 , 请找到合适的异常处理模块处理
    • 该异常的具体信息存储在一个 Exception 对象中 .

    处理异常 : try, catch

    try{ // 可能会抛出异常的代码 } catch(Type1Exception e){ // 处理类型为 "Type1Exception" 的异常 } catch(Type2Exception e){ // 处理类型为 "Type2Exception" 的异常 }

    • 处理对应异常
    • 一旦发生异常立即跳转 , 不是
      等到所有的异常都发生
    • On error goto

    异常对象 : Exception 类的子类

    • 方法:
      toString()
      printStackTrace()
    • 直接写 catch(Exception e)简单
    • 可以只抛出异常(只有throw),将异常交给该方法调用者(可能是另一个方法)处理

    类方法的异常说明

    throws关键字

     bar() throws Type1Exception, Type2Exception{
    …
    throw (Type1Exceptione);
    …
    throw (Type2Exceptione);
    }
    
    • 标识该方法可能会抛出何种类型的异常
    • compile error if no throws
    • 包含throws关键字 , 但函数本身并不抛出相应
      异常
    • 用于 interface, abstract method
    • 保证重写的方法必须考虑所列出的异常
    • 不包含 throws 关键字,默认会抛出RuntimeException 类型的异常
    • 重新抛出异常
      调用函数可以将 catch 到的异常重新抛出,交给调用者的调用者来处理(可以一直抛到嵌套函数最外层)
    • 举例(现成异常)
      • 当数组越界时 , 自动抛出 ArrayOutOfBoundsException
    • 当访问 null 的成员时 , 自动抛出 NullPointerException
    • 当除以 0 时 , 自动抛出ArithmaticException

    finally关键字

    • 无论try 语句中是否有异常抛出 , 都会执行
    • 作用:帮助保证一致性,简化代码
    • return;->统一执行finally

    继承 , 接口与异常

    • 父类 / 接口的方法有异常说明 (throws关键字 )
    • 子类 / 实现重写该方法时,应满足
    • 有同样的异常说明
    • 有 " 更少 " 的异常说明
    • 抛出(相对于父类异常的)子类异常
    • 原因 upcasting

    I/O

    介绍

    • I/O流
    • 字节 (01 串 ): ByteArrayStream
    • 文件 : FileStream
    • 字符串 : StringStream
    • 对象 : ObjectStream
    • 最重要的操作
    • InputStream: read()
    • OutputStream: write()
    • close()
    • 便利操作
    • 从文件读取一行 : readLine()
    • 读取一个基本类型 : readInt(), readDouble()
    • 读取对象

    Path接口

    • java.nio.file
    • 提供对文件路径字符串的操作
    • 创建 Path 类型的对象
      Path p1 = Paths.get("C:/Document/tmp/Hello.java");
      Path p2 = FileSystems.getDefault().getPath("C:/Document/tmp/Hello.java");
    System.out.format("toString: %s%n", path.toString()); // C:homejoefoo
    System.out.format("getFileName: %s%n", path.getFileName()); // foo
    System.out.format("getName(0): %s%n", path.getName(0)); // home
    System.out.format("getNameCount: %d%n", path.getNameCount()); // 3
    System.out.format("subpath(0,2): %s%n", path.subpath(0,2)); // homejoe
    System.out.format("getParent: %s%n", path.getParent());
    // homejoe
    System.out.format("getRoot: %s%n", path.getRoot()); // C:
    

    Files类

    包含文件操作的静态方法

    Path p;

    • 判断文件是否存在 Files.exists(p)
    • 判断文件是否可读 / 可写 / 可执行Files.isReadable(p));
      Files.isWritable(p);
      Files.isExecutable(p);
    • 删除文件
    try {
    Files.delete(path);
    } catch (NoSuchFileException x) {
    System.out.format("%s: no such" + " file or directory%n", path);
    } catch (DirectoryNotEmptyException x) {
    System.out.format("%s not empty%n", path);
    } catch (IOException x) {
    // File permission problems are caught here.
    System.out.println(x);
    }
    

    获得文件相关的信息

    • size(Path)
    • isDirectory(Path, LinkOption)
    • isRegularFile(Path, LinkOption...)
    • isSymbolicLink(Path)
    • getLastModifiedTime(Path, LinkOption...)
    • setLastModifiedTime(Path, FileTime)
    • getOwner(Path, LinkOption...)
    • setOwner(Path, UserPrincipal)

    流Stream

    每次读入/写出一个字节

    InputStream类

    • read()close()
    • 不同源头对应不同子类ByteArrayInputStreamStringBufferInputStreamFileInputStream

    装饰器FilterInputStream

    • InputStream的子类
    • 具有InputStream所有的类的子类接口
    BufferedInputStream

    缓冲 装饰器

    DataInputStream

    读取基本类型 装饰器
    readInt(), readDouble()

    OutputStream类

    • write()close()
    • 不同目的地对应不同子类(改为“Output”即可
    • String objects没有对应的StringBufferOutputStream

    装饰器FilterOutputStream

    • 为 OutputStream 的子类
    • 具有 OutputStream 所有的类的子类接口
    BufferedOutputStream

    缓冲 装饰器

    DataOutputStream

    读取基本类型 装饰器
    readInt(), readDouble()

    PrintStream

    格式化输出(到文件中) 装饰器
    println(), print()

    实现带缓冲的输入/输出流

    read()方法增加参数

    • read(byte[ ], int off, int len)
    • 缺点
      buffer长度需要用户指定
      用户需要知道更多实现细节

    继承

    • BufferedByteArrayInputStream, BufferedByteArrayOutputStream
    • BufferedStringBufferInputStream, BufferedStringBufferOutputStream
    • BufferedFileInputStream, BufferedFileOutputStream
    • 缺点
      类过多
      无法动态加载

    组合

    • 定义BufferedInputStream
    • 包含一个InputStream对象作为成员
    • 调用该InputStream对象的 read(byte[], int off, int len)
      现缓冲
    • 该调用在不同系统上有不同的优化 , 并且被封装

    Reader/Writer

    每次读入/写出一个字符

    • Utf-16
      每次读入 / 写出 16bit, 或者 32bit
    读写字节 读写字符
    InputStream Reader
    OutputStream Writer
    FileInputStream FileReader
    FileOutputStream FileWriter
    StringBufferInputStream StringReader
    (no corresponding class) StringWriter
    ByteArrayInputStream CharArrayReader
    ByteArrayOutputStream CharArrayWriter
    FilterInputStream FilterReader
    FilterOutputStream FilterWriter
    BufferedInputStream BufferedReader
    BufferedOutputStream BufferedWriter
    **DataInputStream ** DataInputStream
    DataOutputStream DataOutputStream
    PrintStream PrintWriter
    PrintWriter可以用 OutputStream
    作为参数

    Standard I/O

    System.out

    PrintStream

    System.err

    PrintStream

    System.in

    需要一些预处理

    public class Echo {
    	public static void main(String[] args) throws IOException {
    		BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
    	String s;
    	while((s = stdin.readLine()) != null && s.length()!= 0)
    		System.out.println(s);
    	}
    }
    

    RTTI

    运行时类型信息(RunTime Type Information)

    Class类

    每一个类都包含一个 Class 类的对象
    该对象包含该类的信息

    获得对象

    • 类的静态成员
      此时所有对象共享一个 Class 对象
    • 每个对象调用 getClass() 获得 Class 类的对象
      String s = “hello”; Class c = s.getClass();
    • 每个通过 .class 获得 Class 类的对象
      Class c = String.class;

    拥有方法

    • getName()
    • getInterfaces()
    • getSuperclass()
    • newInstance()

    RTTI 的用途

    给定 Object 引用 , 判断它的类型

    String s = new String(“hello”);
    Object o = s;
    Class c = o.getClass().getName();
    String t = (String)s;

    泛型

    • 参数化类型
      在定义类的成员和方法时 , 类型为可变参数

    泛型类

    public class TwoTuple<A, B>{ //... }

    泛型接口

    带有类型参数的接口
    public interface Generator<T>{ T next(); }

    泛型方法

    • 带有类型参数的方法的参数以及返回值
    • 语法public <T> void f(T x) { //…} 说明该方法带有类型参数T,且<T>需要放在返回值说明之前

    类型擦除 (Type Erasure)

    • T仅作为占位符 , 不包含任何具体类型的信息
    • 所有T类型的对象引用最终实现为Object对象引用
    • 类型变量仅仅对编译器的静态检查有用
    • 当通过静态检查 , 所有类型参数被擦除

    被限定的类型参数

    限定类型参数的范围

    • 语法:class A <T extends B> { //…}表示类型参数 T 只能是 B 类型或者 B 的子类型
    • 作用 : 静态检查时 , 可以合法引用 T 的方法 ( 但最终仍然是Object)
    • 多个限定类型class A <T extends B & C> { //…}如果有类和接口 , 类应该出现在第一个位置

    通配符*(不考)

    <? extends B>

    类型参数为某个 B 的子类型

    • 具体是哪一个无法确定
    • List<? extends Apple>
    • 无法add任何对象
    • 可以get对象

    <? super B>

    类型参数为某个 B 的父类型

    • 具体是哪一个无法确定
    • List<? super Apple>
    • 无法get任何对象
    • 无法确定是哪个父类
    • 可以addB的子类对象
  • 相关阅读:
    C++类模板的三种特化
    构造函数抛异常
    ScrapySharp
    QtWebKit
    visual studio 插件
    asp.net 开源
    cfr
    eclipse icon
    JAD Java Decompiler
    Java Decompiler
  • 原文地址:https://www.cnblogs.com/05410n/p/7269459.html
Copyright © 2011-2022 走看看