在使用Java开发当中,一些非常必要的知识,它会使你的代码更加的优美。
泛型
简单的理解,泛型就是限制类的类型。泛型提供了类型检查,减少了数据的类型转换,同时保证了类型安全。
下面我们来看下栗子
1 | public static void main(String[] args){ |
可以List的add()
方法默认是任意类型的数据,这样的话我们如果需要统一类型的话,我们添加数据的时候需要非常严谨。 因为我们即使添加了不同类型编译器也不会返回任何提醒。 而且当我们拿到数据的时候需要做强制转换。
1 | public static void main(String[] args){ |
明显可以看出泛型的最主要的优点就是让编译器追踪参数类型。Java类库中又很多使用的了泛型。例如整个集合框架,都被修改为泛型了。
1 | public interface List<E> extends Collection<E> { |
上面就是List的部分源码。显而易见整个Collection
都有使用的泛型。
我们来实现我们实际使用过程中的栗子
1 | /** |
1 | /** |
我们在List的addAll(Collection<? extends E> c)
可以看到 <? extends E> 这个又是什么东西呢?
因为有的时候我们在定义泛型的时候需要控制其类型。不能是所有类型,所以<? extends E>表示的就是该泛型必须继承子E类型.
1 |
|
为什么我们用的是T
,而不是?
。因为T指的是一种类型,?是泛指(就是通配符)。
例如List<? extends Object> list=new ArrayList<>();
这里就不能用T。
1 | public class Test<T extends Collection> { |
好吧,完了,泛型是种很好理解的东西。
枚举
在初级使用的时候枚举的工作有点想静态常量,不过相比较常量类型,枚举类型可以为申明的变量提供更大的取值范围。
定义一个枚举类
1 | public enum People { |
使用枚举
1 | public class Test{ |
除了表示类型,我们可能有属性需要添加在枚举里面,我们可以像类一样给枚举添加属性。
1 | public enum People { |
需要注意的是,枚举不能直接new对象。因为其构造方法必须是private的,枚举类的所有实例必须在类的第一行列出,否则这个枚举类不会产生对象。
枚举可以通过values()
方法类获取所有的枚举属性。
1 | for (People people : People.values()) { |
其实泛型的内容不是多,而且使用起来也很简单。我们可以像一个类一样在里面写各种方法,各种判断。我们再仔细想想其实枚举其实就是一个类,只不过Java对它进行了一定的约束。其实我们创建了一个枚举,然后系统就会帮我们继承Enum抽象类,只不过是编译将其隐藏了。例如:public final class People extends Enum
。我们在上一篇也说过,枚举是实现单例的最好方式,其实枚举就是一个经过编译器约束过的普通类。
反射
反射在Java进阶中非常重要,但是在实际开发中可能不会怎么使用到。它就像黑科技一样,可以通过非正常渠道获取到Class对象,大部分框架都有使用到反射机制。
java.lang.reflect包中的类就是反射机制所需要使用到的。
对于可以有访问权限的类可以使用getField
(获取成员属性)getMethod
(获取方法),getConstructor
(获取构造方法)
对于没有访问访问权限(或者static
)需要在get后面加上Declared(如:getDeclaredField
)
反射一个类的三种方式
1 | try { |
获取无参构造方法
1 | Class clazz1 = Class.forName("yugai.test.Person"); |
获取有参构造方法
1 | Class clazz1 = Class.forName("yugai.test.Person"); |
获取private构造方法
1 | Class clazz1 = Class.forName("yugai.test.Person"); |
获取属性(获取私有的方法同上)
1 | Class clazz1 = Class.forName("yugai.test.Person"); |
获取方法
1 | Class clazz1 = Class.forName("yugai.test.Person"); |
从上面的获取方法可以看到,static
的不用传递对象执行,但需要传入null,对于拿到static
的方法或者属性,我们需要通过Declared
的方法获取。
对于上面说的拿到单个方法或者属性,还有些方法是拿到所有的属性和方法
1 | try { |
注解
当我们开发过程当中其实会遇到很多注解,例如@Override
,@Deprected
… 这些都是系统提供的注解方法,用来表示一些代码的行为。
定义注解
1 | public 注解名{ |
上述注解中我们设置value的值为空字符串,那么我们在使用此注解时,可以不设置value的值,即让value使用设置的空字符串的默认值。
这样一个简单的注解就出来了,接下来我们来了解一下注解参数定义。
支持的类型
- 基本数据类型(int,float….)
- String
- Class
- enum
- Annotaion
- 数组(数组的类型必须是以上其中一种)
元注解
类型 | 描述 |
---|---|
@Documented | 用于描述其他类型的annotation应该被作为被标注的程序成员的公共API |
@Target | 说明Annotation所修饰的对象范围,即描述注解的使用范围 |
@Retention | 定义了Annotation被保留的时间长短 |
@Inherited | 阐述了某个被标注的类型是被继承的 |
其实日常使用当中我们几乎没有使用到自定义注解,但是有时候有些小技巧还是很有用的。例如Android当中不建议使用枚举,因为内存开销比较大,这个时候我们可以利用注解提到枚举,利用support包中@IntDef
。
//不知为何,插入代码快导致hexo出问题
一般使用注解的时候都需要定义注解解析器,我们通过反射来得到注解的信息,再实现注解的逻辑。