前言
继续记录javaweb的一些知识点
开始
JDK经过这么多年的发展,5.0的版本中有一些新的特性:泛型、枚举、静态导入、自动拆装箱、增强for循环,可变参数。
此外再加一个反射的记录。
1.泛型
1.什么是泛型,为什么使用?
泛型一般使用在集合上
把一个字符串类型放到一个集合里面,这个字符串类型就失去了本身的类型,变成了object类型,这个时候想要对这个值进行类型转换,就很容易出现错误,解决这个问题可以使用泛型。
在泛型里面写是一个对象,String,不能写基本的数据类型比如int,要写进本数据类型所对应的包装类
byte——Byte
short——Short
int——Integer
long——Long
float——Float
double——Double
char——charcter
boolean——Blloean
2.如何使用泛型?
常用集合:list set map
泛型的语法:集合<String>,比如List<String>
在list上使用泛型:
list的三种实现有:ArrayList,LinkedList,Vector(要明白这三个的区别)
package jdk5;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.junit.Test;
public class fanxing {
@Test
public void fanxingTest() {
List<String> list = new ArrayList<String>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
//遍历list有三种方式:普通for循环,增强for循环和迭代器
//普通for循环
for(int i=0;i<list.size();i++) {
String string = list.get(i);
System.out.println(string);
}
System.out.println("----------------------------");
//增强for循环
for (String string : list) {
System.out.println(string);
}
System.out.println("----------------------------");
//使用迭代器
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
在set上使用泛型:
@Test
public void setTest() {
Set<String> set = new HashSet<String>();
set.add("www");
set.add("qqq");
set.add("zzz");
//遍历set,有两种方式,迭代器和增强for循环
//增强for循环
for (String string : set) {
System.out.println(string);
}
System.out.println("----------------------------");
//使用迭代器
Iterator<String> iterator = set.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
}
在map上使用泛型:
map的结构:key-value形式
@Test
public void mapTest() {
Map<String,String> map = new HashMap<String,String>();
map.put("aaa", "111");
map.put("bbb", "222");
map.put("ccc", "333");
//遍历map,有两种方式:1.获取所有的key,通过key得到value,使用get方法 2.获取key和value的关系
//1.获取所有的key,通过key得到value,使用get方法
//获取所有的key
Set<String> set = map.keySet();
//遍历所有的key
for (String key : set) {
//通过key得到value
String value = map.get(key);
System.out.println(key+" : "+value);
}
System.out.println("----------------------------");
//2.获取key和value的关系
Set<Entry<String, String>> set2 = map.entrySet();
//遍历set
for (Entry<String, String> entry : set2) {
//entry是key和value关系
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key+" : "+value);
}
}
3.泛型使用在方法上
通过一些联系来展现:
package jdk5;
import java.util.Arrays;
//练习: 编写一个泛型方法,实现指定位置上数组元素的交换
//方法逻辑相同,只是数据类型不同,这个时候使用泛型方法
public class fanxingInMethod {
public static void main(String args[]) {
//创建一个数组,实现11和13的交换
Integer[] arr1 = {10,11,12,13,14};
System.out.println(Arrays.toString(arr1));
swap1(arr1,1,3);
System.out.println(Arrays.toString(arr1));
//创建一个String类型的数组,实现bb和dd位置的交换
String[] arr2 = {"aa","bb","cc","dd","ff"};
System.out.println(Arrays.toString(arr2));
swap1(arr2, 1, 3);
System.out.println(Arrays.toString(arr2));
}
// private static void swap1(int[] arr1, int i, int j) {
// //定义一个中间变量
// int temp = arr1[i];
// arr1[i] = arr1[j];
// arr1[j] = temp;
//
// }
//
// private static void swap1(String[] arr2, int i, int j) {
// //定义一个中间变量
// String temp = arr2[i];
// arr2[i] = arr2[j];
// arr2[j] = temp;
//
// }
//使用泛型方法,需要定义一个数据类型,使用大写字母T,表示任意的类型,写在返回值的前面,表示定义了一个类型T
//下面就可以使用这个类型T
public static <T> void swap1(T[] arr,int a,int b) {
//定义一个中间变量
T temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
}
作业:可以写一个泛型方法,接收任意一种数组,颠倒数组中的全部元素。
4.泛型在类上的使用(了解)
在一个类上定义一个类型,这个类型可以在类里面直接使用
package jdk5;
public class fanxingInClass<T> {
//在类里面可以直接使用T的类型
T aa;
public void test(T bb) {
}
//写一个静态方法,在类上面定义的泛型不能再静态方法中使用,要在静态方法上在定义。
public static <A> void test1(A cc) {
}
}
2.枚举
1.什么是枚举
需要在一定范围内取值,这个值只能是这个范围内中的任意一个
应用场景:红绿灯,三种颜色,但是每次只能亮三种颜色中的一个
2.用代码来看看:
使用传统的方式体现枚举
package meiju;
public class meiju {
//传统的方式
private int color;
public void test() {
this.color = Color1.RED;
}
}
class Color1{
public static final int RED = 1;
public static final int YELLOW = 2;
public static final int GREEN = 3;
}
/**************************************************************************************/
package meiju;
public class meiju {
//第二种方式
private Color2 color1;
public void test() {
this.color1 = Color2.RED;
}
}
class Color2{
//构造方法私有化
private Color2() {
}
public static final Color2 RED = new Color2();
public static final Color2 YELLOW = new Color2();
public static final Color2 GREEN = new Color2();
}
使用枚举,有关键字enum
,枚举的构造方法也是私有的
package meiju;
public class meiju {
//使用枚举
private Color3 color3;
public void test() {
this.color3 = color3.RED;
}
}
enum Color3{
RED,GREEN,YELLOW;
}
/**********************************************************************************/
//特殊枚举,在枚举的类里面有构造方法,抽象方法
enum Color4{
RED("red"){
@Override
public void print1() {
System.out.println("red");
}},GREEN("green"){
@Override
public void print1() {
System.out.println("green");
}},YELLOW("yellow"){
@Override
public void print1() {
System.out.println("yellow");
}
};
private Color4(String name){
}
//当在枚举里面写了一个抽象方法的时候,需要在每个实例上面都实现抽象方法
public abstract void print1();
}
3.枚举的练习
package meiju;
import org.junit.Test;
//练习:枚举对象、枚举对象下标、枚举对象名称表示之间的转换
public class meijuTest {
//知道枚举的对象,怎么得到枚举的名称和下标
@Test
public void test1() {
//得到枚举对象
Color100 color100 = Color100.RED;
//枚举的名称
String name =color100.name();
//枚举的下标
int index =color100.ordinal();
System.out.println(name+" "+index);
}
//知道枚举的名称,怎么得到枚举的对象和下标
@Test
public void test2() {
String name1 = "GREEN";
//得到枚举对象
Color100 c1 = Color100.valueOf(name1);
//得到枚举的下标
int index1 = c1.ordinal();
System.out.println(index1);
}
//知道枚举的下标,怎么得到枚举的对象和名称
@Test
public void test3() {
int index3 = 2;
//得到枚举对象
Color100[] cs = Color100.values();
//根据下表得到对象
Color100 c3 = cs[index3];
//得到枚举的名称
String name3 = c3.name();
System.out.println(name3);
}
}
enum Color100{
RED,GREEN,YELLOW;
}
3.静态导入
可以在java代码里面使用静态导入的方式,导入静态方法或常量
写法:
import static xxx.xxx.xxx
演示:
package importststic;
//演示静态导入
import static java.lang.System.out;
public class importStaticTest {
public static void main(String[] args) {
//传统写法
System.out.println("hello1");
//静态导入之后的写法
out.println("hello2");
}
}
4.自动拆装箱
装箱:把基本数据类型转换成包装类
拆箱:把包装类转换成基本数据类型
在JDK1.4是如何实现拆装箱的:
//在JDK1.4中实现拆装箱
public void test1() {
//装箱
Integer mInteger = new Integer(10);
//拆箱
int a = mInteger.intValue();
}
自动拆装箱:
public static void main(String[] args) {
//自动装箱
Integer integer = 10;
//自动拆箱
int i = integer;
}
JDK是向下兼容的,在JDK1.4里的代码在5.0也可以运行。
5.增强for循环
语法:for(遍历出来的值:要遍历的集合)
数组或实现Iterable接口的集合可以使用增强for循环
list set集合实现了Iterator接口,可以使用增强for循环
map集合没有实现Iterator,不能使用增强for循环
增强for循环出现的目的:替代迭代器
增强for的底层就是迭代器
6.可变参数
应用场景:
假如有三个方法,实现两个数相加,实现三个数相加,实现四个数相加
如果实现的多个方法,这些方法里面的逻辑基本相同,唯一不同的是方法参数的个数,可以使用可变参数
public static void main(String[] args) {
add1(10,20);
}
public static void add1(int...nums) {
//num可以理解成一个数组,这个数组存储传递过来的参数
System.out.println(nums.length);
//遍历数组即可实现参数相加
}
使用可变参数是需要注意的地方:
(1)可变参数需要写在方法的参数列表中,不能单独定义
(2)在方法的参数列表中只能有一个可变参数
(3)方法的参数列表中的可变参数,必须放在参数的最后
7.反射
应用在一些通用性比较高的代码中,大多数框架都是使用反射来实现的
1.反射介绍
在框架的开发中,都是基于配置文件来开发的
在配置文件中配置了类,可以通过反射得到类中的所有内容,可以让类中的某个方法执行。
类中的所有内容:属性、没有参数的构造方法,有参数的构造方法,普通方法
2.反射的原理
首先需要把java文件保存在本地硬盘.java
编译.java文件,得到.class文件
通过jvm,把.class文件通过类加载器加载到内存中
万事万物皆对象,.class文件在内存中使用Class类表示
当使用反射的时候,首先要获取到Class类,得到了这个类之后,就可以得到.class文件里面的所有内容
3.使用反射操作类中的构造方法
操作无参数的构造方法
//操作无参数的构造方法
@Test
public void test1() throws Exception {
//得到class
Class clazz3 = Class.forName("fanshe.Person");
//得到Person类的实例
Person person = (Person) clazz3.newInstance();
//设置一些值
person.setName("zhangsan");
System.out.println(person.getName());
}
操作有参数的构造方法
//操作有参数的构造方法
@Test
public void test2() throws Exception {
//得到class
Class clazz3 = Class.forName("fanshe.Person");
//使用有参数的构造方法
// clazz3.getConstructors(); 获取所有的构造方法
//传递的是有参数的构造方法里面参数类型,类型使用class形式传递
Constructor constructor = clazz3.getConstructor(int.class,String.class);
Person p1 = (Person) constructor.newInstance(100,"lisi");
System.out.println(p1.getId()+" "+p1.getName() );
}
4.使用反射操作属性(Field类表示属性)
//使用反射操作name属性
@Test
public void test3() {
try {
//得到class
Class clazz3 = Class.forName("fanshe.Person");
//得到name属性
// clazz3.getDeclaredFields() 表示得到所有的属性
Field f1 = clazz3.getDeclaredField("name");
//得到Person类的实例
Person person = (Person) clazz3.newInstance();
//设置可以操作私有的属性
f1.setAccessible(true);
//设置name值
f1.set(person, "wangwu");
System.out.println(person.getName());
}catch (Exception e) {
e.printStackTrace();
}
}
4.使用反射操作普通方法(Method类表示普通方法)
//使用反射操作普通方法
@Test
public void test4() throws Exception{
//得到class
Class clazz3 = Class.forName("fanshe.Person");
//得到普通方法
// clazz3.getDeclaredMethods() 得到全部的普通方法
//第一个参数是方法名称,第二个参数是方法里面的参数类型
Method m1 = clazz3.getDeclaredMethod("setName", String.class);
//得到Person实例
Person p4 = (Person) clazz3.newInstance();
//让setName方法执行,执行设置值
m1.invoke(p4, "zhaoliu");
System.out.println(p4.getName());
}
当操作的方法是静态方法的时候,因为静态方法的调用方式是类名.方法名,所以不需要类的实例
此时使用反射操作静态方法的时候也不需要类的实例
m1.invoke(null,"zhaoliu");
在invoke方法的第一个参数写一个null,表示操作的是静态方法
后记
接到活了,干活去,后面回来补