1.泛型的简介
1.1为什么要使用泛型
一般使用在集合上
比如现在把一个字符串类型的值放入到集合里面,这个时候,这个值放入到集合之后,失去本来类型,只能是 object 类型,这个时候,比如想要对这个值进行类型转换,很容易出现类型转换错误,怎么解决这个问题,可以使用泛型类来解决。
1.2在集合上如何使用泛型
常用的集合 list set map
泛型语法 集合
比如 List
1.3 、在泛型里面写是一个对象 Stirng 不能写基本数据类型
写基本数据类型的包装类
- byte —— Byte
- short —— Short
- int —— Integer
- long —— Long
- float —— Float
- double —— Double
- char —— Character
- boolean —— Boolean
2.泛型类的使用
2.1、泛型类在 list 上的使用
代码:
List list=new ArrayList();
list.add("aaa") ;
list.add("bbb") ;
list.add("ccc") ;
//遍历 list
//普通 for 循环
for(int i=0;i it=list.iterator();
while(it.hasNext()){
System.out.print(it.next());
}
2.2、泛型使用在 set 集合上
set 集合特点:无序,唯一
代码:
Set set=new HashSet();
list.add("www") ;
list.add("qqq") ;
list.add("zzz") ;
//遍历 set ,有两种方式
//for(String s2 : set){
System.out.print(s2);
}
//使用迭代器遍历
Iterator it1=set.iterator();
while(it1.hasNext()){
System.out.print(it1.next());
}
2.3、在 map 上使用泛型
代码:
Map map=new HashMap();
map.put("aaa","111");
map.put("bbb","222");
map.put("ccc","333");
//遍历 map 有两种遍历方式
//1.获取所有的 key,通过 key 得到 value 使用 get 方法
//获取所有的 key
Set sets=map.keySet();
//遍历所有 key 返回的 set
for(String key:sets){
String value=map.get(key);
System.out.print(key+“ : ”+value);
}
//2.获取 key 和 value 的关系
Set > sets1 =map.entrySet();
for(Entry entry : sets1){
String keyv=entry.getKey();
String valuev=entry.getValue();
System.out.print(keyv+":"+valuev);
}
2.4 泛型使用在方法上
定义一个数组,实现指定位置上数组元素交换
方法逻辑相同,只是数据类型不同,这个时候使用泛型方法
public static void swap1(T[] arr,int a,int b){
T temp =arr[a];
arr[a]=arr[b];
arr[b] =temp;
}
2.5 泛型在类上的使用
代码:
public class Test{
T aa;
public void test1(T bb){}
//写一个静态方法在类上面定义泛型,不能在静态方法里面使用
public static void test2(A cc1){}
}
3.枚举的简介
3.1、什么是枚举
- 需要在一定的范围内取值,这个值只能是这个范围内的任意一个
- 现场取景:交通信号灯,有三种颜色,但是每次只能亮三种颜色里面的任意一个
使用一个关键字 enum
enum Color3{
RED 、 GREEN 、 YELLOW
}
枚举的构造方法也是私有的
3.2 特殊的枚举操作
- 在枚举里面有构造方法
——构造方法有参数,需要在每个实例上都写参数 - 在枚举里面有抽象方法
——在枚举的每个实例里面都重写这个构造方法
enum color{
RED("red") {
public void print1(){
System.out.print("red");
}
},GREEN("green")
{
public void print1(){
System.out.print("green");
}
},YELLOW("yellow") {
public void print1(){
System.out.print("yellow");
}
}
//构造方法
private color(String name){
}
//抽象方法 -- 在枚举的每个实例里面都重写这个构造方法
public abstract void print1();
}
4.枚举 api 的操作
- name():返回枚举的名称
- ordinal():枚举的下标,下标从零开始
- valueof(class
enumType,String name):得到枚举的对象
还有两个方法,都是这两个方法不在 api 里面,编译的时候生成两个方法 - valueof(String name)转换枚举对象
- values()获得所有枚举对象数组
练习:
1.知道枚举对象,得到枚举名称和下标
public void test(){
color c100=color.RED;
String name=c100.name; //得到枚举名称
int idx=c100.ordinal();//得到枚举下标
}
enum color(
RED,GREEN,YELLOW
)
2.知道枚举名称,得到枚举对象和下标
public void test(){
String name1="GREEN";
color c1=color.valueOf(name1);//得到枚举对象
int idx=c1.ordinal();//得到枚举下标
}
enum color(
RED,GREEN,YELLOW
)
3.知道枚举下标,得到枚举对象和名称
public void test(){
int idx2=2;
color[] cs=color.values();//得到枚举对象数组
color c2=cs[idx2]; //根据下标得到对象
String name=c2.name(); //根据对象得到名称
}
enum color(
RED,GREEN,YELLOW
)
5.自动拆装箱
装箱:把基本的数据类型转换成包装类
拆箱:把包装类转换成基本的数据类型
//自动装箱
Integer i=10;
//自动装箱
int m=1;
在 jdk 1.4里面如何实现装箱和拆箱
public void test1(){
//装箱
Integer m = new Integer(10);
//拆箱
int a = m.intValue();
}
jdk 向下兼容
——比如: jdk 1.4 里面写的代码,这个时候到 5.0 里面也可以运行
6.增强 for 循环
1.语法:
for( String s : list){
System.out.println(s);
}
2.使用场景:
- 数组:实现 Iterable 接口的集合 可以使用增强 for 循环
3.在集合上使用增强 for 循环遍历
list set 实现 Iterable 接口,所以可以使用增强 for 循环
map 不能使用增强 for 循环,没有实现 Interator 接口,所以不能使用
4.增强 for 循环出现的目的:为了替代迭代器
增强 for 底层就是迭代器实现的
7.内容补充
练习:实现一个泛型方法,接受任意类型的数组,颠倒数组中的所有元素
public static void reverse(T[] arr1){
for(int i=0;i
8.可变参数
应用场景:
实现两个数相加,实现三个数相加,四个数相加
如果实现多个方法,这些方法里面逻辑基本相同,唯一不同的是传递的参数个数,这时候可以使用可变参数
1.可变参数定义方法
数据类型...数组名称
可以理解为一个数组,这个数组存储传递过来的参数
public static void add1(int...nums){
int sum=0;
for(int i=0;i
注意的地方:
(1)可变参数需要写在方法的参数列表中,不能单独定义
(2)在方法的参数列表中只能有一个可变参数
(3)方法的参数列表中的可变参数,b必须放在参数最后
add1(int a , int...nums)
9.反射
9.1 反射的原理
1.应用在一些通用性比较高的代码中
2.后面学到的框架,大多数都是使用反射来实现的
3. 在框架开发中,都是基于配置文件开发的
——在配置文件中配置了类,可以通过反射得到类中的 所有内容,可以让类中的某个方法来执行
4.类中的所有内容:属性、没有参数的构造方法、有参数的构造方法、普通方法
5.画图分析反射的原理
1.首先需要 java 文件保存到本地硬盘 .java
2.编译java 文件,成 .class文件
3.使用 jvm ,把 class 文件通过类加载加载到内存中
4.万事万物皆是对象,class 文件在内存中使用 class 类表示
5.当使用反射的时候,首先需要获取到class 类,得到了这个类之后,就可以得到 class 文件里面的所有内容——包含属性,构造方法,普通方法
6.属性通过一个类 Filed
7.构造方法通过一个类 constructor
8.普通方法通过一个类 Method
9.2 使用反射操作类里面的属性
- 首先获取到 class 类
Class clazz1=person.class;
Class clazz2=new person().getClass();
Class clazz3=Class.forName("day06.person");
- 操作无参数的构造方法
public void test1() throws InstantiationException, IllegalAccessException, ClassNotFoundException {
//得到 class
Class c3=Class.forName("day06.person");
//得到 person 实例
person p=(person)c3.newInstance();
//设置值
p.setName("zhangsan");
System.out.println(p.getName());
}
- 操作有参数的构造方法
public void test2() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class c1=Class.forName("day06.person");
//传递有参数的构造方法里面的参数类型,类型使用 class 形式传递
Constructor cs=c1.getConstructor(String.class,String.class);
//通过有参数的构造方法设置值
person p1=(person) cs.newInstance("lisi","100");
System.out.println(p1.getId()+" "+p1.getName());
}
- 使用属性来操作属性
public void test3() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
try {
Class cc=Class.forName("day06.person");
//得到 person 类的实例
person p=(person) cc.newInstance();
//通过这个方法得到属性,参数是属性的名称
Field f1=cc.getDeclaredField("name");
//操作的是私有属性,不让操作,需要设置可以操作私有属性setAccessible(true)
f1.setAccessible(true);
//设置name的值
f1.set(p , "wangwu");//相当于 p.name="wangwu"
}catch(Exception e) {
e.printStackTrace();
}
}
- 使用泛型操作普通方法
使用 Method 类表示普通方法
public void test4() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class c4=Class.forName("day06.person");
//得到 person 实例
person p4=(person) c4.newInstance();
//得到普通方法
//传递两个参数,第一个参数:方法名称第二个参数:通过方法设置的值
Method m1=c4.getDeclaredMethod("setname", String.class);
//让 setName方法执行,执行设置值
m1.invoke(p4, "niuqi");
System.out.println(p4.getName());
}