- 泛型
- 定义
- 概念:
- 语法:
- 深入了解
- 泛型接口,类,方法
- 泛型方法和可变参数
- 泛型的继承
- 通配符
- 泛型上下界:
- 上界 <= 【extends】
- 下界 >= 【super】
- 泛型嵌套
- 注意:
- static和泛型:
- 泛型和数组
- 泛型没有多态,泛型没有数组
- 枚举类
- 定义理解
- 概念:
- 语法:
- 注意:
- 使用
- 枚举和switch
- 说明
- 示例
- java.lang.Enum
- 枚举类
- EnumMap 与 EnumSet
- EnumMap 类
- EnumSet
- 静态导入
- 理解
- 使用
- lambda表达式
- 简介
- 概念:
- 理解:
- 使用
- 接口的实现
- 语法
- 函数式编程接口
- lambda表达式的特征
- 可变参数:
- 定义
- 特点
JDK1.5加入的新特性,泛型的本质是参数化类型,即操作的数据类型被指定为一个参数。安全简单,且所有的强制类型转换都是隐式和自动进行的,提高代码的重用率。
定义 概念:将对象类型作为参数,指定到其它类或者方法上,从而保证类型转换的安全性和稳定性。
语法:类型
- 解析:
- <> 是泛型的特征
- E 表示某种数据类型,也可用其它字母,实际使用中需要用明确类型换掉 E
-
泛型接口:
-
泛型接口与泛型类的定义及使用基本相同。泛型接口常被用在各种类的生产器中。
-
只能用在抽象方法上
-
public interface Generator
{ public T next(); } class FruitGenerator implements Generator { @Override public T next() { return null; } }
-
-
泛型类:
-
用于类的定义中,被称为泛型类
-
最典型的就是各种容器类,如:List、Set、Map
-
只能用在成员变量上,只能使用引用类型
-
class 类名称
{ ..... } -
泛型类,是在实例化类的时候指明泛型的具体类型;泛型方法,是在调用方法的时候指明泛型的具体类型 。
-
-
泛型方法
-
是在调用方法的时候指明泛型的具体类型 。
-
返回值前面加上
-
public
T genericMethod(Class tClass)throws InstantiationException , IllegalAccessException{ T instance = tClass.newInstance(); return instance; }
-
-
public
void printMsg( T... args){ for(T t : args){ Log.d("泛型测试","t is " + t); } }
-
package com.bigdata.practice1011; public abstract class FanXin
{ T1 name; public abstract void setName(T2 sex); } -
保留父类泛型
-
// 全保留 package com.bigdata.practice1011; // 泛型父类 子类全部保留父类的泛型 public class FanXin1extends FanXin { @Override public void setName(T2 sex) { } } // 保留一个 package com.bigdata.practice1011; // 继续全写泛型不合适 得把用的那个泛型写成具体类型 public class FanXin2 extends FanXin { @Override public void setName(String sex) { } }
-
-
不保留父类泛型
-
package com.bigdata.practice1011; // 不保留父类的泛型 // 父类的泛型显示 // 泛型擦除:实现或继承父类的子类没有指定类型 类似于Object【不等于Object,
-
-
子类重写父类的方法,泛型类型随父类而定 子类使用父类的属性,该属性类型随父类定义的泛型
- T、K、V、E 等泛型字母为有类型,类型参数赋予具体的值
- ?未知类型 类型参数赋予不确定值,任意类型
- 只能用在声明类型、方法参数上,不能用在定义泛型类上
- 语法:? extends List
- 范围:指定的类必须是继承某个类,或者实现了某个接口(不是implements),即<=
- 注意:一般用于限制操作 不能使用在添加数据上,一般都是用于数据的读取
- 语法:? super List
- 范围: 即父类或本身
- 注意:一般用于下限操作
大概阅读源码理解一下就好了!泛型嵌套
HashMap使用了泛型的嵌套
Map注意: static和泛型:map = new HashMap (); map.put("a", "张三"); map.put("b", "李四"); Set > set = map.entrySet(); for (Entry entry : set) { System.out.println(entry.getKey()+":"+entry.getValue()); }
静态方法有一种情况需要注意一下,那就是在类中的静态方法使用泛型:静态方法无法访问类上定义的泛型;如果静态方法操作的引用数据类型不确定的时候,必须要将泛型定义在方法上。即使该类已经定义为泛型类。
// 泛型参数T2其实没用 静态方法的泛型T2和类定义的泛型T2没有任何关系 public class FanXin泛型和数组{ T1 name; public static T2 get(T2 name){ T2 t2 = name; return t2; }; }
不能创建一个确切的泛型类型的数组,使用通配符创建泛型数组是可以的
List泛型没有多态,泛型没有数组 枚举类 定义理解 概念:[] ls = new ArrayList [10]; // 不行 List>[] ls = new ArrayList>[10]; // 可以 List [] ls = new ArrayList[10]; // 可以
JDK1.5引入的一种新类型枚举(Enum),是指一组固定常量组成的类型。其实是一种类型,是java.lang.Enum的子类。
如果学过单例模式,我们可以理解为枚举就是多例模式,一个类有多个实例,但实例个数不是越多越好的,是有限的。
语法:修饰符 enum 枚举名{
枚举常量值1;
枚举常量值2;
}
// 调用
枚举名.枚举常量值1;
注意:
- enum 是关键字,小写的 ;
- 枚举型其实就是本类的实例;
- 多个枚举项之间使用逗号分隔,最后一个枚举项需要给出分号!如果只有枚举项(没有构造器,方法,实例变量)则可以省略分号。
- 不可使用new来创建枚举类对象,枚举类的枚举项就是实例,所以在外面用类面点来调用
通常用枚举表示一组常用且个数有限的值,用于实现对输入值进行约束检查
内部类的形式去给到性别属性的控制:
package com.bigdata.practice1008; public class Person枚举和switch 说明{ private String name; private int age; private sexType sex; private T personType; public Person() { } enum sexType{ 男,女 } public Person(String name, int age, sexType sex, T personType) { this.name = name; this.age = age; this.sex = sex; this.personType = personType; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public sexType getSex() { return sex; } public void setSex(sexType sex) { this.sex = sex; } public T getPersonType() { return personType; } public void setPersonType(T personType) { this.personType = personType; } public static void printInfo(T st){ System.out.println("泛型类中的静态方法!"); if (st instanceof Student){ System.out.println("OK!"); } } @Override public String toString() { return "Person{" + "name='" + name + ''' + ", age=" + age + ", sex=" + sex + ", personType=" + personType + '}'; } }
- switch中不可使用枚举类名称
- 编译器会根据switch(s)中的s来确定每个枚举类型
- case中直接使用枚举项
public enum Signal{
RED, GREEN, BLANK, YELLOW;
}
public class TrafficLight {
Signal color = Signal.RED;
public void change() {
switch (color) {
case RED:
color = Signal.GREEN;
break;
case YELLOW:
color = Signal.RED;
break;
case GREEN:
color = Signal.YELLOW;
break;
}
}
}
java.lang.Enum
Java 中的每一个枚举都继承自 java.lang.Enum 类。当定义一个枚举类型时,每一个枚举类型成员都可以看作是 Enum 类的实例,这些枚举成员默认都被 final、public, static 修饰,当使用枚举类型成员时,直接使用枚举名称调用成员即可
| 方法名称 | 描述 |
|---|---|
| values() | 以数组形式返回枚举类型的所有成员 |
| valueOf() | 将普通字符串转换为枚举实例 |
| compareTo() | 比较两个枚举成员在定义时的顺序 |
| ordinal() | 获取枚举成员的索引位置 |
- 可以拥有自己的方法
- 可以拥有自己的构造
为了更好地支持枚举类型,java.util 中添加了两个新类:EnumMap 和 EnumSet。使用它们可以更高效地操作枚举类型。
EnumMap 类EnumMap 是专门为枚举类型量身定做的 Map 实现。虽然使用其他的 Map(如 HashMap)实现也能完成枚举类型实例到值的映射,但是使用 EnumMap 会更加高效。
HashMap 只能接收同一枚举类型的实例作为键值,并且由于枚举类型实例的数量相对固定并且有限,所以 EnumMap 使用数组来存放与枚举类型对应的值,使得 EnumMap 的效率非常高。
EnumSet- EnumSet 是枚举类型的高性能 Set 实现,它要求放入它的枚举常量必须属于同一枚举类型。EnumSet 提供了许多工厂方法以便于初始化。
- allOf(Class element type) 创建一个包含指定枚举类型中所有枚举成员的 EnumSet 对象
- complementOf(EnumSet s) 创建一个与指定 EnumSet 对象 s 相同的枚举类型 EnumSet 对象,并包含所有 s 中未包含的枚举成员
- copyOf(EnumSet s) 创建一个与指定 EnumSet 对象 s 相同的枚举类型 EnumSet 对象,并与 s 包含相同的枚举成员
- noneOf(
- of(E first,e…rest) 创建包含指定枚举成员的 EnumSet 对象
- range(E from ,E to) 创建一个 EnumSet 对象,该对象包含了 from 到 to 之间的所有枚举成员
在一个类中使用其它类的静态属性和静态方法时,需要静态导入。
使用直接在前面用 import static 包名;导入,或者类名点去直接调用
lambda表达式 简介 概念:不推荐使用,有的时候同包不同类的同名函数或者同名参数不太好处理
lambda,其实是数学符号中的 λ,一个希腊字母。拉姆达 Lambda(大写Λ,小写λ),是第十一个希腊字母;在计算机术语中,Lambda 多表达式”是一个匿名函数,可以包含表达式和语句,并且可用于创建委托或表达式目录树类型。Java 8 引入的 Lambda 表达式的主要作用就是简化部分的写法。
理解:- Lambda表达式本身就是一个接口的实现
- 把“一块代码”赋给了一个变量。而“这块代码”,或者说“这个被赋给一个变量的函数”,就是一个Lambda表达式。
以Lambda语法创建线程和匿名内部类创建线程的区别:
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
public static void main(String[] args) {
// 用匿名内部类的方式来创建线程
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("我是一个线程啊");
}
});
// 使用Lambda来创建线程
new Thread(() -> System.out.println("我是一个线程啊"));
}
使用
接口的实现
- 1.new实现类
- 2.new接口自己匿名类借助
- 3.lambda表达式【只能去实现一个抽象方法的接口,用 @FunctionalInterface 注解的接口】
-
语法:(方法参数) -> {方法要实现的内容}
-
1.语法格式一:无参,无返回值,Lambda 体只需一条语句。
示例:
Runnable r1 = () -> System.out.println("Hello Lambda!");2.语法格式二:Lambda 需要一个参数。
示例:
Consumer
con = (x) -> System.out.println(x); 3.语法格式三:Lambda 只需要一个参数时,参数的小括号可以省略。
示例:
Consumer
con = x -> System.out.println(x); 4.语法格式四:Lambda 需要两个参数,并且有返回值。
示例:
Comparator
com = (x, y) -> { System.out.println("函数式接口"); return Integer.compare(x, y); }; 5.语法格式五:当 Lambda 体只有一条语句时,return 与大括号可以省略。
示例:
Comparator
com = (x, y) -> Integer.compare(x, y); 6.Lambda的表达式的参数不用去显示声明类型,jvm ”上下文推断出“类型
-
使用Labmda表达式需要函数式编程接口,接口上加上 @FunctionalInterface注解(标记着这个接口只有一个抽象方法)
接口上加上 @FunctionalInterface注解(标记着这个接口只有一个抽象方法)
内部的函数式编程接口的学习和Stream流一起
lambda表达式的特征- 可选的类型声明:不需要声明参数类型,编译器可以自动识别参数类型。
- 可选的参数圆括号:一个参数无须使用圆括号,但多个参数则需要使用圆括号。
- 可选的花括号:如果函数体只有一条语句,则不需要使用花括号。
- 可选的返回关键字:如果函数体只有一条语句,则编译器会自动返回该语句执行的结果;如果有多条语句且有返回值,那么在花括号中需要使用return语句来返回结果。
可变参数: 定义Lambda结合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代码变的更加简洁!后面再来
- A、 可变参数:适用于参数个数不确定,类型确定的情况,java把可变参数当做数组处理。
- B、 注意:可变参数必须位于最后一项。
- A、 只能出现在参数列表的最后;
- B、 …位于变量类型和变量名之间,前后有无空格都可以;
- C、 调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数。
package com.bigdata.practice1011;
public class ChangeParam {
public static void main(String[] args) {
append(25, new String[] {"AA", "Cc"});
append(34, "AA", "BB");
}
public static void append(int a, String... strs) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < strs.length; i++) {
System.out.println(strs[i]);
sb.append(strs[i]);
}
System.out.println(sb.toString());
}
}
调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数。
package com.bigdata.practice1011;
public class ChangeParam {
public static void main(String[] args) {
append(25, new String[] {"AA", "Cc"});
append(34, "AA", "BB");
}
public static void append(int a, String... strs) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < strs.length; i++) {
System.out.println(strs[i]);
sb.append(strs[i]);
}
System.out.println(sb.toString());
}
}



