摘要:泛型类型对象之间没有关系,就算之间互为父子关系,也没有任何关系。泛型类的静态上下文中类型变量无效。不能捕获或抛出泛型类的实例。
前言
作为一块后端没有太多经验的年糕,下周要考试了,所以我必须得来好好复习一下我的JAVA进阶课/(ㄒoㄒ)/~~。这个学期主要是学了:
泛型
反射
线程
JDBC
JAVA WEB基础
Servlet
session&cookie
过滤器&监听器
泛型定义:Java的参数化类型被称为泛型。
出现原因:JAVA不支持多继承,虽然有接口,但还是有约束,必须要实现接口的方法。
注意点:
虚拟机没有泛型类型对象。比如定义了ArrayList
泛型类型对象之间没有关系,就算T之间互为父子关系,也没有任何关系。
不能用基本类型实例化类型参数。
运行时类型查询只适用于原始类型。if( a instanceof Pair
不能创建参数化的数组。声明类型为Pair
不能实例化类型变量。如new T(), new T[...]或T.class都是无效的。
泛型类的静态上下文中类型变量无效。
不能捕获或抛出泛型类的实例。
List定义方式 泛型类l1=new ArrayList (); List l2=new ArrayList (); System.out.println(l1.getClass()==l2.getClass()); //true Collection c= new ArrayList (); if(c instanceof ArrayList ){} //报错
public class 类名
使用举例:
Applea1 = new Apple ("苹果"); Apple a2 = new Apple (5.67);
注意:不能多带带用来修饰静态变量和静态方法(方法定义具体看后面)。
泛型接口派生类、子类:一定要指明T的类型,或者不写
public class A1 extends Apple泛型方法{} public class A2 extends Apple{} //等同于
publicvoid ArrayToCollection(T[] a, Collection c){ //... }
方法中的泛型参数无须显式传入实际类型参数。编译器根据实参推断类型形参的值。
为了让编译器能够准确的推断出泛型方法中的形参类型,不能产生多种可能性。
比如:我写了一个选出三个变量中中间的那个值的函数。我可以传入字符串比较,也可以传数字,但数字同时有Comparable和Number两个接口,这样它无法确定T应该是哪个,应该写成public static
限定多个用&连接,比如T extends Comparable&Serializable。
泛型必须传入具体的类型,但如果不确定,就可以用类型通配符,用?表示。?代表可以使任意类型
如:
public void test(List> c){ for (int i = 0; i < c.size(); i++) { System.out.println(c.get(i)); } }
关系:
List>是List的子类,且List
限定:
设置上限:? extends Shape,必须是Shape/Shape的子类才可以。
设置下限:? super Apple,必须是Apple/Apple的父类才可以。
易错:
1.List>集合是只读的。不能往List>中添加除null的任何东西。
[原因]我们假设可以添加的话:
Listis = Arrays.asList("one", "two", "three"); List> list=is; list.add(new String("four"));//Ok list.add(new Integer(4));//如果假设成立,则是OK的
那么混入了其他类型的变量我们也没有办法判断,所以要禁止添加。
2.?不是类型变量,不可以代替类型来使用。
public static void swap(Pair> p){ ? t=p.getFirst(); //错误 }类的加载
定义:当程序主动使用某个类时,如果该类还未被加载到内存中,系统会通过加载、连接、初始化三个步骤来该类进行初始化,如果没有意外,JVM将会连续完成这三个步骤,即类的加载/初始化。
三个步骤:
加载——找到.class文件并把这个文件包含的字节码加载到内存中
连接——分为验证、准备和解析
初始化——类中静态属性和静态块的执行
JVM进程终止的情况:
运行到最后正常结束
运行到使用System.exit()/Runtime.getRuntime().exit()
遇到未捕获的异常或错误
所在平台强制结束JVM进程。
步骤-加载调用ClassLoader的findClass方法,可从不同来源中加载类的二进制数据,通常由如下来源:
本地文件系统
JAR包,例:JDBC编程用到的数据库驱动类
网络加载,例:Applet
其他文件生成,例:JSP文件生成对应的Class类
运行时计算生成,例:动态代理技术
步骤-连接验证:检查被加载的类是否有正确的内部结构,并和其他类一致。包括文件格式验证、元数据验证、字节码验证、符合引用验证
准备:为类的静态属性分配内存和指定初始值(通常情况下为默认初始值)。这些变量所使用的的内存在方法区被分配。
解析:将常量池中的符号引用替换为直接引用的过程。主要针对类和接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符。
注意:
public static int value = 123,变量value在准备阶段的值是0,注意是分配默认值。假设一个变量的定义如下:
public static final int value = 123;变量value在准备阶段的值是123,因为这是一个常量,存放在方法区的常量池中。
解析过程不一定发生在初始化之前,可以发生在初始化之后再开始。
步骤-初始化编译器自动收集类中所有类变量的赋值动作和静态语句块中的语句,收集的顺序由语句在源文件中出现的顺序所决定的。
public class Test { static int a = 5; //准备阶段的初值为0,初始化赋值为5 static int b; //准备阶段的初值为0 static int c; //准备阶段的初值为0 static{ //初始化阶段的赋值为6 b = 6; } }
初始化一个类的步骤
类没有被加载,先加载并连接该类。
类的直接父类还被初始化,先初始化其直接父类。
类中有初始化语句,系统依次执行这些初始化语句。
初始化类的5中情况
创建类的实例;读取或设置一个类的静态字段(放入常量池的除外);调用一个类的静态方法。
使用java.lang.reflect包方法进行反射调用(如果没有进行过初始化)。例:Class.forName("SuperClass")
父类没有进行初始化,则需要先触发父类的初始化
虚拟机启动,用户需制定一个执行的主类(包含main()方法的那个类),虚拟机会先初始化这个类。
来自JDK1.7:一个MethodHandle实例最后的解析结果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,且句柄所对应的类没有进行初始化。
注意
使用ClassLoader类的loadClass()加载某个类时并不会执行该类的初始化。
如果final类型的静态属性的值不能在编译时得到,必须等到运行时才能确定该属性的值,就会触发初始化。
类加载器将.class文件加载到内存中,生成对应的java.lang.Class对象。
注意:
只有类是同一个类加载器加载才有可能等于(包含Class对象的equals方法、instanceof)。
类加载器分类
Bootstrap ClassLoader:根类加载器,加载Java的核心类。
Extension ClassLoader:扩展类加载器,加载JRE的扩展目录(JAVA_HOME/jre/lib/ext)中的JAR的类包。
System ClassLoader:系统类加载器,加载命令java中的classpath选择的JAR包和类路径。
类加载机制
全盘负责:一个类加载器负责加载Class和它的依赖Class,除非显示使用另一个加载器。
父类委托:先让父类加载该Class,在父类加载器无法加载时从自己的类路径中加载。(类加载器之间的父子关系不是继承上的父子关系,是类加载器实例之间的关系。
)
缓存机制:当程序中需要Class时,先从缓存中搜寻,缓存中不存在时,才重读该类对应的二进制数据,并将其转换为Class对象,并存入到cache。
反射使用场合:编译的时候无法获悉类型,依靠运行时信息发现,这时就采用反射。
获取Class的方法Class类的forName()静态方法(可能抛出ClassNotFoundException)。
调用某个类的class属性。
调用某个对象的getClass()。
获取构造函数
Constructor
Constructor>[] getConstructors()获取Class对象表示类的所有public构造器。
Constructor
Constructor>[] getDeclaredConstructors()获取Class对象表示类的所有构造器。
创建对象Class对象的newInstance()方法:要求该Class对象有默认的构造方法。
调用Constructor对象的newInstance()。
调用方法Class对象的getMethods()方法/getMethod()方法,再调用Method Object invoke(Object obj, Object...args),该方法中的obj是执行该方法的主调,后面跟着的是参数。
访问属性获得Class对象后,通过该Class对象的getFields()方法或getDeclaredFields()方法来获取全部属性或指定属性。
Field nameField = personClazz.getDeclaredField("name"); nameField.setAccessible(true); nameField.set(p , "Yeeku.H.Lee");
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/69380.html
摘要:从白天到晚上,不是在学就是在学的路上,从测试理论到实战操作,大大小小的问题,在群里前辈的帮助下,总是能很快解决。慢慢的,测试方法,用例设计,测试,测试,接口测试。大概面试了一周多,我就拿下了的。 ...
摘要:后来知道有了院赛,学长说刷院和杭电就可,我就一直刷院,到最后比赛前院的前五十道基本做完,杭电也弄了十来道,就这样草草参加比赛了。 博客主页: https://b...
摘要:解放碑的钟声响起,年结束,迎来了新的一年时间本来无所谓结点,只是人类为其赋予了意义。生活就是这样,总结反思,再度起航。这并不算是自己的愿望,这是大家的愿望。所以,正值研究生一年级的我,很清楚自己这一年想要什么,也下定决心去实现它加油。 解放碑的钟声响起,2018年结束,迎来了新的一年2019.时间本来无所谓结点,只是人类为其赋予了意义。生活就是这样,总结反思,再度起航。作为一个新的开始...
摘要:需要注意的是用矩阵形式如行列表示二维数组,是逻辑上的概念,能形象地表示出行列关系。再次强调二维数组名如是指向行的。一维数组名如是指向列元素的。 哈喽!这里是一只派大鑫,不是派大星。本着基础不牢,地动山摇的学习态度,从基础的C语言语法讲到算法再到更高级的语法及框架的学习。更好地让同样热爱编...
阅读 1371·2021-11-11 16:54
阅读 9163·2021-11-02 14:44
阅读 2330·2021-10-22 09:53
阅读 3240·2019-08-30 11:18
阅读 1902·2019-08-29 13:29
阅读 1983·2019-08-27 10:58
阅读 1609·2019-08-26 11:38
阅读 3489·2019-08-26 10:31