资讯专栏INFORMATION COLUMN

【期末考试季】JAVA进阶复习提纲

Jokcy / 2581人阅读

摘要:泛型类型对象之间没有关系,就算之间互为父子关系,也没有任何关系。泛型类的静态上下文中类型变量无效。不能捕获或抛出泛型类的实例。

前言

作为一块后端没有太多经验的年糕,下周要考试了,所以我必须得来好好复习一下我的JAVA进阶课/(ㄒoㄒ)/~~。这个学期主要是学了:

泛型

反射

线程

JDBC

JAVA WEB基础

Servlet

session&cookie

过滤器&监听器

泛型

定义:Java的参数化类型被称为泛型。
出现原因:JAVA不支持多继承,虽然有接口,但还是有约束,必须要实现接口的方法。
注意点:

虚拟机没有泛型类型对象。比如定义了ArrayList,实际上并没有这个class的存在。

泛型类型对象之间没有关系,就算T之间互为父子关系,也没有任何关系。

不能用基本类型实例化类型参数。

运行时类型查询只适用于原始类型。if( a instanceof Pair) //error

不能创建参数化的数组。声明类型为Pair[]的变量仍是合法的。不过不能用new Pair[10]初始化这个变量,但可以用(Pair[])new 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 类名

使用举例:

Apple a1 = new Apple("苹果"); 
Apple a2 = new Apple(5.67);

注意:不能多带带用来修饰静态变量和静态方法(方法定义具体看后面)。

泛型接口派生类、子类:

一定要指明T的类型,或者不写(编译器会警告,默认为是Object)

public class  A1  extends Apple{}
public class  A2  extends Apple{}  //等同于

泛型方法
public   void ArrayToCollection(T[] a, Collection c){
    //...
}

方法中的泛型参数无须显式传入实际类型参数。编译器根据实参推断类型形参的值。
为了让编译器能够准确的推断出泛型方法中的形参类型,不能产生多种可能性。

比如:我写了一个选出三个变量中中间的那个值的函数。我可以传入字符串比较,也可以传数字,但数字同时有Comparable和Number两个接口,这样它无法确定T应该是哪个,应该写成public static > Pair minmax(T[] a)
限定多个用&连接,比如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、List...都是List的子类。

限定:

设置上限:? extends Shape,必须是Shape/Shape的子类才可以。

设置下限:? super Apple,必须是Apple/Apple的父类才可以。

易错:
1.List集合是只读的。不能往List中添加除null的任何东西。
[原因]我们假设可以添加的话:

List  is = 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 getConstructor(Class..ParameterType)获取Class对象表示类的某个public构造器。

Constructor[] getConstructors()获取Class对象表示类的所有public构造器。

Constructor getDeclaredConstructor(Class..ParameterType)获取Class对象表示类的指定构造器。

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

相关文章

  • 转行测试,11k入职,我写了份1000多字的分享,每一笔都是经历

    摘要:从白天到晚上,不是在学就是在学的路上,从测试理论到实战操作,大大小小的问题,在群里前辈的帮助下,总是能很快解决。慢慢的,测试方法,用例设计,测试,测试,接口测试。大概面试了一周多,我就拿下了的。 ...

    luzhuqun 评论0 收藏0
  • 大学一年之后竟如此。。。开学前的挣扎

    摘要:后来知道有了院赛,学长说刷院和杭电就可,我就一直刷院,到最后比赛前院的前五十道基本做完,杭电也弄了十来道,就这样草草参加比赛了。 博客主页: https://b...

    MartinDai 评论0 收藏0
  • 2019新年目标和计划

    摘要:解放碑的钟声响起,年结束,迎来了新的一年时间本来无所谓结点,只是人类为其赋予了意义。生活就是这样,总结反思,再度起航。这并不算是自己的愿望,这是大家的愿望。所以,正值研究生一年级的我,很清楚自己这一年想要什么,也下定决心去实现它加油。 解放碑的钟声响起,2018年结束,迎来了新的一年2019.时间本来无所谓结点,只是人类为其赋予了意义。生活就是这样,总结反思,再度起航。作为一个新的开始...

    sf190404 评论0 收藏0
  • C语言 指针+二维数组详解 (应付期末、考研的最强笔记,建议收藏)

    摘要:需要注意的是用矩阵形式如行列表示二维数组,是逻辑上的概念,能形象地表示出行列关系。再次强调二维数组名如是指向行的。一维数组名如是指向列元素的。 哈喽!这里是一只派大鑫,不是派大星。本着基础不牢,地动山摇的学习态度,从基础的C语言语法讲到算法再到更高级的语法及框架的学习。更好地让同样热爱编...

    FrozenMap 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<