JavaSE学习笔记(2)
面试题:简单叙述以下以下三个关键字有什么区别?
Enum à 枚举类默认继承的类
Enumeration à 早期的迭代器类型,主要用于Vector和顺序流
enum à 定义一个类为枚举时候的关键字
u 泛型
问题:如果不使用泛型,那么请看下面的代码发生的转型异常?
public static void printList(List list){
for(Object temp:list){
String str = (String) temp;
System.out.println(temp);
}
}
public static void main(String[] args) {
List list = new ArrayList();
list.add("aaa");
list.add(123);
list.add("bbb");
printList(list);
}
因此我们在实际的开发环境中需要进行泛型的使用。通过使用泛型我们可以约束在集合中存储的对象的类型。
泛型其实就是给容器上贴一个标签而已,指定容器存放的数据类型。
泛型的有点其实就是将运行时候的异常前置在编译时解决。
泛型的使用
原则“使用泛型的时候左右两边要一致!”
List list = new ArrayList<String>(); add提示的是Object
List<String> list = new ArrayList (); add提示的是String
List<String> list = new ArrayList<String>(); add提示的是String
以上的语法全对,但是推荐使用第三种。
泛型的自定义
如果在定义一个类的时候成员的类型不明确,那么可以先使用泛型进行代替,直到创建该类的对象的时候可以使用具体的数据类型来替换泛型的类型。
举例1:定义一个方法返回任意数据类型的数据。
public static <T> T returnType(T t){
return t;
}
如果一个类中很多地方都使用到了泛型,那么可以将泛型的定义放在类上。
public class Demo1<T>{
// 非静态成员都可以直接使用T泛型
}
如果是静态成员那么不能使用类上定义好的泛型。如果需要的话需要单独的进行声明。
泛型的继承和实现
public interface List<E> extends Collection<E>
public class Person implements Comparable<Person>
compareTo(T o)
泛型的通配符
举例1: 实现一个方法可以打印输出任意集合数据?
// 提供一个输出任意集合数据的方法
// Collection<Object> coll = new ArrayList<String>()
public static void printCollection(Collection<?> coll){
for(Object temp:coll){
System.out.println(temp);
}
}
泛型的限定
在通配符的基础上可以对实际的类型进行基本的限制
? extends 父类
? super 子类
举例2:实现数字集合的输出。
public static void printCollection(Collection<? extends Number> coll){
for(Object temp:coll){
System.out.println(temp);
}
}
实战:
查看List的boolean addAll(Collection<? extends E> c) 方法
注意:
在给泛型传递实际的数据类型的时候必须是对象类型,如果是基本数据类型那么默认会自动的进行装箱操作。
u 反射(Reflect)
反射即将Class类中的所有的成员映射为相应的对象。
要学习反射那么需要先了解和掌握以下几个类:
类 |
描述 |
Class |
描述所有的Class文件的共性 |
Filed |
描述的是Class文件的中的属性的共性 |
Constructor |
描述的是Class文件中的构造函数的共性 |
Method |
描述的是Class文件中的函数的共性 |
1. 获取指定类的Class对象
方式一: 类名.class
方式二: 对象名.getClass()
方式三: forName(String className) 该方法是Class类的静态方法 推荐
举例1: 获取字符串类的Class对象。
public static void main(String[] args)throws Exception {
// 使用不同的方式会过去Class对象
Class clazz1 = String.class;
Class clazz2 = new String("jnb").getClass();
// 参数必须指定类的全名(类的全限定名)
Class clazz3 = Class.forName("java.lang.String");
// class文件时候独一无二的,那么Class对象也应该是单例的
System.out.println(clazz1 == clazz2); // true
System.out.println(clazz2 == clazz3); // true
}
以上的方式都可以获取指定类的Class对象,在实际的开发中到底要使用哪一个?
一般的情况下我们都需要在不知道类名的情况下获取类的Class对象并进而获取类中包含的成员进行操作。
大家可以参考Tomcat的一个基本的server.xml文件
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory" à 类
pathname="conf/tomcat-users.xml" />
2. 将Class对象中的属性进行反射为Filed对象
常用的获取属性字段的方法
方法 |
描述 |
Field[] getDeclaredFields() |
获取所有声明的字段数组对象 |
Field[] getFields() |
获取所有的声明的共有字段数组对象 |
Field getDeclaredField(String name) |
获取指定名称的声明的字段对象 |
Field getField(String name) |
获取指定名称的声明的共有字段对象 |
举例1:获取所有的声明字段数组对象。
public static void main(String[] args)throws Exception {
// 获取Shape类的Class对象
Class clazz = Class.forName("cn.itcast.bean.Shape");
// 获取所有的属性
Field [] fs = clazz.getDeclaredFields();
System.out.println(fs.length); // 2
// 获取所有共有的属性
fs = clazz.getFields();
System.out.println(fs.length); // 1
// 获取指定名字的私有的属性
Field field = clazz.getDeclaredField("x");
System.out.println(field);
// 获取指定名字的共有的属性
field = clazz.getField("y");
System.out.println(field);
}
举例2:调用Field类的方法进行字段对象的操作。
u 内省
u BeanUtils工具
总结
大家主要要掌握以下几点内容:
增强for循环,而且必须要清楚底层采用的是迭代器进行的迭代。
安全的枚举,全部要会。枚举是单例的,有时候在项目中如果要使用单例,那么可以使用枚举。
泛型的应用。
练习
- 使用Properties类读取配置文件中的属性值。
- 使用Properties配置一个以下的值:
class=java.lang.String
使用程序获取指定类的Class对象进行属性对象的反射。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。