java基础加强

一、泛型 Generic
1.集合泛型:

在没有泛型之前,集合中存入的数据,类型就会丢失掉,在取出数据时,需要做强制类型转换,就有转换失败的风险,而这种风险,在编译阶段是没有办法检查出来的
引入泛型后,在定义集合的过程中可以指定集合中存储的类型,当存入非这种类型的数据时,编译时会报错.取出数据时也不需要强转
List<String> list = new ArrayList<String>();

ArrayList<E>中的E称为 类型参数变量
ArrayList<Integer>中的Integer称为 实际类型参数
整个称为ArrayList<E> 泛型类型
整个ArrayList<Integer>称为参数化的类型ParameterizedType


如果两边都有泛型,则要求泛型必须一致,也可以只有一边有而另一边没有
ArrayList<String> list = new ArrayList<Object>();
ArrayList<Object> list = new ArrayList<String>();
ArrayList<String> list = new ArrayList ();//--考虑兼容1.5之前的老程序
ArrayList list = new ArrayList<String>();

2.自定义泛型
方法泛型:定义在方法上的泛型就叫做方法泛型,作用的范围的当前方法内部
泛型在使用之前必须先定义<T>,其中的字母可以是任意字母,但是通常使用大写字母
可以认为,当方法在被调用到时,虚拟机自动判断出泛型的具体类型.
public static <T> void doxx(T t);

public class Demo1 {
    public static void main(String[] args) {
           String []strs=new String[]{"a","b","c"};
             change(strs,0,2);
             System.out.println(strs);
             
             Integer [] ins=new Integer[]{1,2,3};
             change(ins, 0, 2);
             System.out.println(ins);
    }
    
    public static <T> void change(T[] arrs,int i,int j){
        T t=arrs[i];
        arrs[i]=arrs[j];
        arrs[j]=t;
    }
}

类上的泛型:定义在类上的放行叫做类泛型,作用范围是整个类中都可以使用
public class GenericDao<T> {}
可以认为,在使用这个类时,就需要指定出泛型的具体类型.如果不明确指定,则泛型是它的上边界类型的.
静态方法不能使用类上定义的泛型,如果想使用泛型静态方法必须自己定义泛型

public class Demo2 {
   Person<String> p=new Person<String>();
   
}


class Person <T>{
    public void say(T t){
        
    }
}



*泛型通配符:
因为泛型没有继承关系,所有当需要用一个泛型引用引用不同的泛型实现时,泛型中写他们共同的父类是不行的,这时该怎么做呢?引入一个新的概念,叫做泛型通配符?,注意泛型通配符只能用在泛型引用中,用来引用不同的泛型实现,不能出现在实现中.

List<?>list = null;
list = new ArrayList<String>();
list = new ArrayList<Integer>();

*泛型的边界:
如果没有指定泛型默认可以接受任意的类型,有时希望进一步限制,此时可以使用泛型的边界:
extends - 用来指定泛型的上边界,使用在泛型的通配符中和泛型定义中,指定具体的泛型实现必须是指定的类或其子类.
坏处是,在传入对象时,只能传入null
好处是,获取到泛型的对象时,可以调用上边界的方法.
super - 用来指定泛型的下边界,使用在泛型的通配符中,指定具体的泛型实现必须是指定类或其超类.
好处是,可以传入对象时,可以传入下边界的子孙类对象
坏处是,获取到泛型对象时,只能调用Object身上的方法

import java.util.ArrayList;
import java.util.List;

public class Demo2 {
    public static void main(String[] args) {
        Person p = new Person();
        
        List<?> list0 = new ArrayList<Teacher>();
        list0.get(0);
        
        
        //--上边界:指定泛型必须是某个类或其子孙类,好处是,获取到泛型类型后,可以直接调用上边界的方法,坏处是,当进行传入操作时,只能传入null,其他的值不能传入
        List<? extends Person>list1 = null;
        list1 = new ArrayList<Teacher>();
        list1.get(0).say();
        list1.add(null);
//        list1.add(new Object());
//        list1.add(new Ani());
//        list1.add(new Person());
//        list1.add(new Teacher());
        
        
        
        //-泛型的下边界,用来指定泛型是某个类型后去祖先类型,好处是,可以传入指定类的子孙对象,坏处是获取出来后只能当作Object使用
        List<? super Person>list2 = null;
        list2 = new ArrayList<Ani>();
        list2.add(new Person());
        list2.add(new Teacher());
        
        
    }
    
}

class someC<T>{
    public void method1(){
    }
    
}

class Ani{
    public void sayx(){
        
    }
}

class Person extends Ani{
    public void say(){
        
    }
    
}

class Teacher extends Person{
    public void teach(){
        
    }
}

二、注解:

可以作为配置信息控制程序的运行,注解可以在一些场合用来替代配置文件
Annotation 注解:程序中给人看到提示信息叫注释,给程序看的提示信息叫做注解
@xxxx(....)

jdk1.5内置的注解:
@Override: 限定重写父类方法, 该注解只能用于方法
@Deprecated: 用于表示某个程序元素(类, 方法等)已过时
@SuppressWarnings: 抑制编译器警告.
自定义注解:
1.声明注解
(1)使用 @interface关键字来定义注解,在这个类中可以声明注解的属性
注解属性的声明类似于在为接口声明一个方法,同时可以为属性设定默认值
注解属性支持如下类型:String、基本数据类型、枚举、Class 、其它注解类型、以上数据类型相应一维数组
如果注解中只包含一个名为value的属性,则这个属性在使用时可以省略注解的名字直接写值
public @interface tran{
//String name();
//String name2() default "xxx";
String value();
}
(2)使用元注解对注解进行描述
@Retention:用来指定注解的保留范围
RetentionPolicy.SOURCE: 编译器直接丢弃这种策略的注释
RetentionPolicy.CLASS: 编译器将把注解记录在 class 文件中. 当运行 Java 程序时, JVM 不会保留注解. 这是默认值
!!RetentionPolicy.RUNTIME:编译器将把注释记录在 class 文件中. 当运行 Java 程序时, JVM 会保留注解. 程序可以通过反射获取该注释
@Target:指定被修饰的注解可以使用在什么位置
ElementType的成员变量。可以是类/方法/字段/构造方法/包声明.....

@Documented: 用于指定被该元 Annotation 修饰的 Annotation 类将被 javadoc 工具提取成文档.

@Inherited: 被它修饰的 Annotation 将具有继承性.如果某个类使用了被 @Inherited 修饰的 Annotation, 则其子类将自动具有该注解
2.使用注解
在 @Target声明的位置上使用 @Tran(属性名=属性值,.....)

3.反射注解
JDK 5.0 在 java.lang.reflect 包下新增了 AnnotatedElement 接口, 该接口代表程序中可以接受注释的程序元素,包括Class Field Method Constructor Package都是这个接口的实现,所以这个接口中定义的反射注解的方法,他们都具有

<T extends Annotation> T getAnnotation(Class<T> annotationClass)
如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。
Annotation[] getAnnotations()
返回此元素上存在的所有注释。
Annotation[] getDeclaredAnnotations()
返回直接存在于此元素上的所有注释。
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
如果指定类型的注释存在于此元素上,则返回 true,否则返回 false。
获取注解上的属性?获取到注解对象后,就像调用方法一样后去注解的属性

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface DemoAnno {
    public String name();
    public int age() default 100;
}

三、动态代理:

用来修改已经具有的对象的方法,控制方法是否执行,或在方法执行之前和执行之后做一些额外的操作
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h);
loader -- 类加载器
interfaces -- 指定代理对象实现哪些接口,通常代理对象要和被代理对象实现相同的接口,从而保证和被代理者具有相同的方法
InvocationHandler
-- 处理器对象,当调用代理对象的任何方法时,都会导致此对象中的invoke方法执行,在这个方法中可以编写是否允许方法执行,以及在方法执行之前和之后做那些额外的操作
{
Object invoke(Object proxy, Method method, Object[] args)
proxy -- 代理者对象
method -- 当前调用到的方法
args -- 方法的参数
返回值 -- 就是这个方法要返回什么


}

原文地址:https://www.cnblogs.com/xiaoduc-org/p/5436311.html