Javaweb学习笔记——(七)——————myexlipse基本使用、jdk5.0新特性及反射讲解

1.debug调试模式:
*使用这种模式,调试程序(看到程序运行停止在这一行)
-显示出来行号
-双击左边,出现一个圆点,表示设置了一个断点
*使用debug as方式,运行程序
-特使是否进入到调试界面,yes
-在断点那里,有一个绿色的条,表示程序停止在这一行,没有向下运行
*可以让程序向下执行:
-使用 step over 快捷键是 F6(单步执行)
-resume F8:表示调试结束,执行直接向下运行
**比如当前的断点之后还有断点,就会跳到下一个断点
**如果当前的断点后面没有断点,程序直接运行结束


*debug另外一个用途
**查看程序的源代码
**F5 step into:进入到方法
**F7 step return:返回


2.myeclipse的快捷键的使用
*代码提示 alt /
*快速导包 ctrl shift o
*单行注释 ctrl /
*去掉单行注释 ctrl /
*多行注释 ctrl shift /
*去掉多行注释 ctrl shift \
*删除行 ctrl d


3.junit的使用
*单元测试


*测试的对象是一个类中的方法


*junit不是Javase的一部分,想要使用导入jar包
**但是,在myeclipse中自带了junit的jar包


*首先junit版本 3.x,4.x
*单元测试方法时候,方法命名规则 public void 方法名() {}


*使用注释方式运行测试方法,在方法的上面
** @Test


-@Test
public void testAdd1(){
TestJunit test01 = new TestJunit();
test01.testAdd(2, 3);
}
-选中方法名称,右键运行 点击run as --- junit test
-当出现的绿色条,边上方法测试通过
-当出现了红棕色条,表示方法测试不通过


---要运行勒种的多个测试方法,点击类中的其他位置,run as --- junit test


** @Ignore:表示这个方法不进行单元测试


** @Before:在每个方法执行前运行
** @After:在每个方法之后运行


**断言(了解)
- Assert.assertEquals("测试期望的值", "方法运行的实际的值");






JDK5.0新特性
jdk1.1、 1.2、 1.4、 5.0 (因为在1.4过后,增加了好多新特性,所以直接没有1.5,直接命名为5.0) 

**泛型、 枚举、 静态导入、 自动拆装箱、 增强for循环、 可变参数
**反射


5.泛型的简介
*为什么要使用泛型?
-一般使用在集合上
**比如现在把一个字符串类型的值放入到集合里面,这个时候,这个值放入到集合之后,失去本身的类型,只能是object类型
这个时候,比如想要对这个值进行类型转换,很容易出现类型转换错误,可以通过泛型解决


*在集合上如何使用泛型
-常用集合 list set map
-泛型语法 集合<String> 集合名称 = new 集合<String>();


*在泛型里面写是一个对象,String 不能写基本的数据类型 比如int
**写基本的数据类型对应包装类
byte -- Byte
short -- Short
int -- Integer
long -- Long


float -- Float
double -- Double


char -- Character


boolean Boolean






*在list上使用泛型
List的三种实现方式:ArrayList linkedList Vector
代码
List<String> list = new ArrayList<String>();


list.add("aaa");
list.add("bbb");


// 比如吧aaa值取出来,类型转换,转换成int类型,会类型转换的错误。.


// 遍历list集合 有三种方式 三种
// 普通for循环,增强for,迭代器


// 普通for循环
for (int i = 0; i < list.size(); i++) {
String listStr = list.get(i);
System.out.println(listStr);
}


// 增强for
for (String listStr : list) {
System.out.println(listStr);
}


// 迭代器
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}


*在set上使用泛型
*代码
//泛型在set上的使用(唯一性,无序性)
public void testSet() {
Set<String> set = new HashSet<String>();
set.add("www");
set.add("aaa");
set.add("bbb");
set.add("zzz");
set.add("zzz");

//遍历set,有两种方式
//迭代器,增强for

//使用增强for遍历
for (String string : set) {
System.out.println(string);
}

//使用迭代器遍历
Iterator<String> iterator = set.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}


*在map上面使用泛型
-map结构:key-value形式
代码:
Map<String, String> map = new HashMap<String, String>();
map.put("001", "aaa");
map.put("002", "bbb");
map.put("003", "ccc");

//遍历map,有两种遍历方式
//1.获取所有的key,通过key来得到value,使用get方法
//2.获取key和value的关系

//使用第一种方式遍历
//获取所有的key
Set<String> sets = map.keySet();
//遍历所有的key返回的set
for (String key : sets) {
//通过得到的key得到value
String value = map.get(key);
System.out.println(key+"        "+value);
}

//使用第二种方式遍历
//得到key和value的关系
Set<Entry<String, String>> sets1 = map.entrySet();
//遍历sets1
for (Entry<String, String> entry : sets1) {
//entry是key和value的关系
String keyv = entry.getKey();
String valuev = entry.getValue();
System.out.println(keyv+"  "+valuev);
}.




6.泛型使用在方法上
*定义一个数组,实现指定位置上的数组元素的交换
*方法逻辑相同,只是数据类型不同,这个时候使用泛型方法
* /*
* 使用泛型方法需要定义一个类型 使用大写字母表示T:这个T表示任意的类型 写在返回值之前 void之前 ========表示定义了一个类型
* 这个类型就是T 在下面就可以使用这个类型了
*/
public static <T> void swap1(T[] arr, int a, int b) {
T temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}


7.泛型在类上的使用
*在一个类上定义了一个类型,这个类型可以在类里面直接使用
//在类里面就可以直接使用T类型
T aa;
public void test11(T bb){

}

//写一个静态方法,在类上定义的泛型,不能在静态方法中使用
public static void test22(T cc){

}


8.枚举的简介
*什么的枚举
**需要在一定范围内取值,这个值只能是这个范围内中的任意一个。
**现实场景:交通信号灯,有三种颜色,但是每次只能亮里面的任意一个


*使用一个关键字enum :
**代码:
enum Color3 {
RED, GREEN, YELLOW;
}
*枚举的构造方法也是私有的

*特殊枚举的操作
**在枚举类里面有构造方法
**构造方法里面有参数,需要在每个实例上面都写参数
**在枚举类里面有抽象方法
**在枚举的每一个实例里面都重写这个抽象方法




9.枚举的api的操作
** name():返回枚举的名称
** ordinal():枚举的下标
** valueOf(Class<T> enumType, String name):得到枚举的对象


** 还有两个方法,这个两个方法不在api 里面,编译的时候生成两个方法
***valueOf(String name) 转换枚举对象
***values() 获取所有的枚举对象数组


*练习:
1.// 知道枚举的对象,得到枚举的名称和下标
@Test
public void test1() {
// 得到枚举对象
Color100 c100 = Color100.RED;
// 枚举名称
String name = c100.name();
// 枚举下标
int idx = c100.ordinal();
System.out.println(name + "    " + idx);
}


2.// 知道枚举的名称,得到枚举的对象和下标
@Test
public void test2() {
String name1 = "GREEN";
// 得到对象
Color100 c1 = Color100.valueOf(name1);
// 枚举下标
int idx1 = c1.ordinal();
System.out.println(idx1);
}


3.// 知道枚举的下标,得到枚举的对象和名称
@Test
public void test3() {
int idx2 = 2;
// 得到枚举的对象
Color100[] cs = Color100.values();
// 根据下标得到对象
Color100 c12 = cs[idx2];
// 得到枚举的名称
String name = c12.name();
System.out.println(name);
}




10.静态导入
*可以再代码里面,直接使用静态导入方式,导入静态方法或者常量
*import static XX.XX.xxx


*import static java.lang.System.out;
*import static java.util.Arrays.sort;


**比如实现一个计算器 在Math类里面       




11.自动拆装箱
*装箱:
**把基本的数据类型转换成包装类
*拆箱:
**把包装类转换成基本的数据类型


** //自动装箱
Integer i = 10;


//自动拆箱
int m = i;  


**在jdk1.4里面如何实现装箱和拆箱
//在jdk1.4里面实现拆装箱
private void test() {
//装箱
Integer i = new Integer(10);

//拆箱
int i2 = i.intValue();
}


**jdk是向下兼容
比如子jdk1.4里面写的代码,到5.0里面也可以运行


练习:
==执行的结果会调用 doSomething(double d)
==首先在jdk1.4里面是调用这个方法,如果需要调用doSomething(Integer i)这个方法,则需要类型转换,但是jdk1.4不能实现自动拆装箱
==由于jdk是向下兼容的,所以,在jdk1.4调用这个方法,在jdk5.0还是会调用相同的方法
public static void main(String[] args) {
doSomething(1);
}


public static void doSomething(double d) {
System.out.println(1.0);
}

public static void doSomething(Integer i) {
System.out.println(1);
}




**  八种基本的数据类型对应的包装类
*int -- Integer
*char -- Character


12.增强for循环
*语法:for(遍历出来的值 : 要遍历的集合) {}
for (String string : list) {
System.out.println(string);
}
*实现Iterable接口可以使用增强for循环


*在集合上使用增强for循环遍历
list set 实现了Iterator接口,所以可以使用增强for循环
map不能使用增强for循环,没有实现Iterator接口,所以不能使用只增强for循环


*增强for循环出现目的:为了替代迭代器
**增强for底层就是迭代器


13.内容补充
(1).泛型擦除
*首先泛型知识出现在源代码阶段,当编译之后泛型就不存在了


(2).练习:实现一个泛型方法,接受任意类型元素,颠倒数组
*代码:
private static <T> void reverses2(T[] arr1) {
/*
* 基本思想, 把第一个元素和最后一个元素交换位置,把第二个元素和倒数第二个元素交换位置 交换 长度/2
*/


// 遍历数组
for (int i = 0; i < arr1.length / 2; i++) {
/*
* int temp = arr1[0]; arr1[0] = arr1[arr1.length-1]
*/


T temp = arr1[i];
arr1[i] = arr1[arr1.length - i - 1];
arr1[arr1.length - i - 1] = temp;
}
}


14.可变参数(指数量上的可变)
*可变参数应用场景:
**实现两个数的相加,实现三个数的相加,实现四个数的相加...


--如果实现的多个方法,这些方法里面逻辑基本相同,唯一不同的是传递的参数的个数,可以使用可变参数
*可变参数的定义方法 数据类型...数组的名称
*理解为一个数组, 这个数组存储传递过来的参数
-代码
public static void add1(int...nums){
//nums可以理解一个数组,用于存储传递过来的参数
//System.out.println(nums.length);

//遍历数组
int sum = 0;
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
}

System.out.println(sum);
}


*注意的地方
(1)可变参数需要写在方法的参数列表中,不能单独定义
(2)在方法的参数列表中只能有一个可变参数
(3)方法的参数列表中的可变参数,必须放在参数的列表之后
-add(int a, int...nums)


15.反射的原理
*应用在一些通用性比较高的代码中
*在后期中的框架中,大多数都是使用反射来实现的


*在框架开发中,都是基于配置文件开发
**在配置文件中配置了类,可以通过反射得到类中的所有内容,可以让类中的某个方法来执行


*类中的所有内容:属性、没有参数的构造方法,有参数的构造方法、普通方法


**反射的原理:
*首先需要把java文件保存到本地硬盘  .java
*编译java文件,成 .class文件
*使用jvm,把class文件通过类加载加载到内存中
*万事万物皆对象,class文件到内存中使用Class类表示


*当使用反射时候,首先需要获取到Class类,得到这个类之后,就可以得到clss文件里面的所有内容了
-包含属性  构造方法 普通方法
*属性通过一个类:Filed
*构造方法通过一个类:Constructor
*普通方法通过一个类:Method


16.使用反射操作类里面的无参数的构造方法
*首先获取到Class类
// 获取class类
Class class1 = Person.class;
Class class2 = new Person().getClass();
Class class3 = Class.forName("com.changeyd.test09.Person");
*比如:对一个类型进行实例化,可以new,如果不使用new,如何获取?
//得到class类
Class class1 = Class.forName("com.changeyd.test09.Person");
//得到Person类的实例
Person person = (Person) class1.newInstance();
-代码:
//操作无参数的构造方法
@Test
public void test1() throws ClassNotFoundException, InstantiationException, IllegalAccessException{
//得到class类
Class class1 = Class.forName("com.changeyd.test09.Person");
//得到Person类的实例
Person person = (Person) class1.newInstance();
//设置值
person.setName("Wangji");
System.out.println(person.getName());
}


17.使用反射操作有参数的构造方法
//操作有参数的构造方法
@Test
public void test2() throws NoSuchMethodException, SecurityException, ClassNotFoundException, InstantiationException,
IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// 得到class类
Class class1 = Class.forName("com.changeyd.test09.Person");
// 使用有参数的构造方法
// class1.getConstructors();//获取所有的构造方法
Constructor cs = class1.getConstructor(String.class, String.class);
// 通过有参数的构造方法设置值
// 通过有参数的构造方法来创建Person实例
Person person = (Person) cs.newInstance("lisi", "100");
System.out.println(person.getId() + "    " + person.getName());


}


18.使用反射来操作属性
* @Test
public void test3() throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException,
SecurityException, InstantiationException {
try {
// 得到class类
Class class1 = Class.forName("com.changeyd.test09.Person");


// 得到name属性
// class1.getDeclaredFields();//表示得到所有的属性
// 得到Person类的实例
Person person = (Person) class1.newInstance();
//通过这个方法得到属性,参数是属性的名称
Field field = class1.getDeclaredField("name");


//操作的是私有的属性,不让操作,需要设置可以操作私有属性setAccessible(true),可以操作私有属性
field.setAccessible(true);

// 设置name值 set方法,两个参数:第一个参数类的实例,第二个参数是设置的值
field.set(person, "wangwu");// 相当于在p.name = "wangwu";
System.out.println(field.get(person)); // 相当于p.name;


} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}




19.使用泛型来操作普通方法
*使用Method来表示普通方法
*代码
// 普通方法,比如操作 setName
@Test
public void test4() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException,
NoSuchMethodException, SecurityException, InstantiationException, ClassNotFoundException {
// 得到Class类
Class class1 = Class.forName("com.changeyd.test09.Person");
// 得到Person的实例
Person person = (Person) class1.newInstance();
// 得到普通方法
// class1.getDeclaredFields();//得到所有的普通方法
//传递两个参数:第一个参数,方法名称;第二个参数,通过方法设置的值
Method method = class1.getDeclaredMethod("setName", String.class);
// 让setName方法执行,执行设置值
//使用invoke(person, "niuqi");传递两个参数;第一个参数,person实例;第二个参数,设置的值
//执行了invoke方法之后,相当于,执行了setName方法,同事通过这个方法设置了一个值是niuqi。
method.invoke(person, "niuqi");


System.out.println(person.getName());
}


//如果操作的是私有的方法,需要设置值为true
method.setAccessible(true);


*当操作的方法是静态的方法时候,因为静态方法调用的方式是 类名.方法名,不需要类的实例
*使用反射操作静态方法的时候,也是不需要实例
*在invoke方法的第一个参数里面,写一个null
-method.invoke(null, "wangji");

猜你喜欢

转载自blog.csdn.net/qq_40223688/article/details/79840332
今日推荐