Java进阶1

发布时间 2023-07-17 21:39:42作者: 媛~~

 

  • idea和eclipse
    • eclipse的快速生成
      • main函数:main
      • 输出语句:syso
    • idea的快速生成
      • main函数:psvm
      • 输出语句:sout
    • 在idea中一个project相当于eclipse当中的一个workspace,在空的工程下新建Module(模块),IDEA中模块类似于eclipse当中的project
      • eclipse的组织方式:workspace->project
      • idea的组织方式:project->module
    • idea的字体设置:
      • file->settings->输入font->设置字体样式以及字号大小
    • idea是自动保存,不需要ctrl+s
    • idea添加构造方法/setXxx/getXxx:alt+insert
  • 抽象类
    • 什么是抽象类?
      • 类和类之间具有共同特征,将这些共同特征提取出来,形成的就是抽象类,类本身是不存在的,所以抽象类无法创建对象,无法实例化。
    • 抽象类属于什么数据类型?
      • 抽象类也属于引用数据类型,编译之后也是一个class字节码文件
    • 抽象类怎么定义?
      • [修饰符列表]  abstract   class 类名{
        • 类体;
      • }
    • 抽象类是无法实例化的,无法创建对象,所以抽象类都是用来被子类继承的,所以final和abstract不能联合使用,这两个关键字是对立的
    • 抽象类的子类可以是抽象类
    • 抽象类虽然无法实例化,但抽象类有构造方法,这个构造方法供子类使用
    • 抽象类关联到一个概念,抽象方法,什么是抽象方法呢?
      • 抽象方法只有方法的声明,没有方法体,以分号结尾
      • public  abstract  void  doSome();
    • 抽象类中不一定有抽象方法,抽象方法必须出现在抽象类中
    • 重要结论:
      • 一个非抽象的类继承抽象类,必须将抽象类中的抽象方法重写
      • 一个抽象的类继承抽象类,可以不去将抽象类中的抽象方法重写
    • 抽象类和非抽象之间可以使用多态,面向OCP原则
    • 面试题:Java语言中凡是没有方法体的方法都是抽象方法
      • 不对,错误的
      • Object类中就有很多方法没有方法体,都是以;结尾的,但他们都不是抽象方法,例如:
        • public native int hashCode();
        • 这个方法底层调用了C++写的动态链接库程序
        • 前面修饰符列表中没有abstract,有一个native,表示调用JVM本地程序
  • 接口
    • 接口也是一种引用数据类型,编译之后也是一个class字节码文件
    • 接口是完全抽象的,(抽象类是半抽象的),或者也可以说接口是特殊的抽象类,特殊在他是完全抽象的
    • 接口怎么定义,语法是什么?
      • [修饰符列表]  interface  接口名{}
    • 接口支持多继承,一个接口可以继承多个接口
    • 接口中只包含两部分内容,一部分是常量,一部分是抽象方法,接口中的所有元素都是public修饰的
    • 接口中的抽象方法定义时,public abstract修饰符可以省略
    • 接口中的常量,public static final可以省略
    • 类和类是继承(单继承),接口和接口是继承(多继承),类和接口之间是实现implements(多实现)
    • 当一个非抽象类实现接口,必须将接口中的所有抽象方法全部实现
    • 接口和非抽象之间可以使用多态,面向OCP原则
    • 继承和实现都存在的话,extends关键字在前,implements关键字在后,如果没写继承,则默认继承Object类
    • 接口在开发中的作用:
      • 注意:接口在开发中的作用类似于多态在开发中的作用:
      • 多态:面向抽象编程(将Dog/Cat写成Animal),不要面向具体编程,降低程序的耦合度,提高程序的扩展力、
      • 总结:面向接口编程,可以降低程序的耦合度,提高程序的扩展力
      • 接口离不开多态,接口+多态才可以达到降低程序的耦合度,提高程序的扩展力
    • 类型和类型之间的关系:
      • is a
        • Cat is a Animal(猫是一个动物)
        • 凡是能够满足is a的表示“继承关系” 
        • A extends B 
      • has a
        • I has a Pen(我有一只笔)
        • 凡是能够满足has a关系的表示“关联关系”
        • 关联关系通常以“属性的形式存在”
        • A{
        •    B b;
        • }
      • like a:
        • Cooker like a FoodMenu(厨师像一个菜单一样)
        • 凡是能够满足like a关系的表示“实现关系”
        • 实现关系通常是:类实现接口
        • A implements B
    • 抽象类和接口的区别:
      • 抽象类是半抽象的
      • 接口时完全抽象的
      • 抽象类中有构造方法
      • 接口中没有构造方法
      • 类之间是单继承
      • 接口之间可以多继承
      • 类可以实现多个接口
      • 接口中只允许出现常量和抽象方法
  • Object类中的方法在哪找?
    • 第一:去源代码当中(但是这种方式比较麻烦,因为源代码也比较难)
    • 第二: 去查阅java的类库的帮助文档
  • 什么是API(Application Program Interface)?
    • 应用程序编程接口
    • 整个JDK类库就是一个javase的API
    • 每一个API都会配置一套API帮助文档
  • Object类需要了解的方法:
    • protected Object clone()//负责对象克隆
    • public int hashCode()//获取对象哈希值
    • public boolean equals(Object obj)//判断两个对象是否相等
    • public String toString()//将对象转换成字符串形式
    • protected void finalize()//垃圾回收器负责调用的方法
  • Object的toString方法
    • public String toString() {
      • return getClass().getName() + "@" + Integer.toHexString(hashCode());
    • }
    • 返回的是:类名@对象的内存地址通过哈希算法转换为十六进制的形式
    • SUN公司设计toString方法的目的?
      • toString方法的设计目的是:通过调用这个方法可以将一个“Java对象”转换成字符串形式
    • SUN公司开发Java语言的时候,建议所有的子类都去重写toString方法
    • 输出引用的时候。默认会调用引用的toString方法
  • Object的equals方法
    • public boolean equals(Object obj){
      • return (this == obj);
    • }
    • 以后编程的过程当中,都要通过equals方法来判断两个对象是否相等
    • 判断基本数据类型是否相等直接使用“=”就可以,=判断的是值的大小,所以引用数据类型不能用“=”判断
    • 在Object类的equals方法中,默认采用的是“==”判断两个Java对象是否相等,而“==”判断的是两个对象的内存地址是否相等,所以老祖宗的equals方法不够用,需要重写equals方法
    • 改良之后的代码

    • 再次改良之后的代码 

  •  String类

    • String类已经重写了equals方法,比较两个字符串相等不能使用==,必须使用equals
    • String类已经重写了toString方法
  • Object的finalize方法
    • protected void finalize()  throws Throwable { }
    • finalize()方法有一个没有代码的方法体,而且这个方法是protected修饰的
    • 这个方法不需要程序员手动调用,JVM的垃圾回收器负责调用这个方法,不像equals,toString方法是需要写代码调用的,finalize方法只需要重写,重写完将来自动会有程序来调用
    • 当一个Java对象即将被垃圾回收器回收的时候,垃圾回收器负责调用finalize()方法
    • finalize()方法实际上是SUN公司为Java程序员准备的一个时机,垃圾销毁时机,如果希望在对象销毁时机执行一段代码的话,这段代码要写到finalize()方法当中
    • java中的垃圾回收器不是轻易启动的,垃圾太少,或者时间没到,种种条件下,又可能启动,也有可能不启动
    • 有一段代码可以建议垃圾回收器启动:System.gc();,只是建议,可能启动,也可能不启动,只是启动的概率高了一些
  • Object的hashCode方法
    • public native int hashCode();
    • 这个方法不是抽象方法,带有native关键字,底层调用C++程序
    • hashCode方法返回的是哈希码
      • 实际上就是一个Java对象的内存地址,经过哈希算法,得出的一个值
      • 所以hashCode方法的执行结果可以等同看做一个Java对象的内存地址
  • 内部类:
    • 在类的内部又定义了一个新的类。被称为内部类
    • 分类:
      • 实例内部类:类似于实例变量
      • 静态内部类:类似于静态变量
      • 局部内部类:类似于局部变量
        • 不能使用访问权限修饰符和static修饰
      • 匿名内部类:
        • 匿名内部类是一种特殊的局部内部类,它是通过匿名类实现接口
        • 学习匿名内部类主要是以后阅读别人的代码时,可以理解,并不代表以后都要这样写,因为匿名内部类有两个缺点:
          • 缺点一:太复杂、太乱、可读性差
          • 缺点二:类没有名字,以后想重复使用,不能用
    • 内部类的修饰符:private、protected、public及默认修饰符 
    • dosome方法中的局部内部类,在其他方法内不能使用
    • 使用内部类编写的代码可读性很差,能不用尽量不用 
  • 数组
    • 一维数组:
      • 数组是一种引用数据类型,不属于基本数据类型,父类也是Object
      • 数组实际上是一个容器,可以同时容纳多个元素
      • 数组当中可以存储“基本数据”类型的数据,也可以存储“引用数据类型”的数据
      • 数组因为是引用数据类型,所以数组对象在堆内存当中
      • 数组当中如果存储的是java对象的话,实际存储的是对象的“引用(内存地址)” 

      • 数组一旦创建,长度不可变
      • 数组的分类:一维数组、二位数组、三维数组、多维数组...........
      • 所有的数组对象都有length属性,用来获取数组中元素的个数
      • Java中的数组要求数组中元素的类型统一,比如int类型数组只能存储int类型,Person类型数组只能存储Person类型
      • 数组在内存方面存储的时候,数组中的元素内存地址是连续的,这是数组存储元素的特色,数组实际上是一种简单的数据结构
      • 所有数组都是拿第一个小方框的内存地址作为整个数组的内存地址,因为这样就可以算出后面数组的内存地址
      • 数组中每一个元素都是有下标的,下标从0开始,以1递增,最后一个数组的下标是length-1
      • 数组数据结构的优点和缺点?
        • 优点:
          • 查询/查找/检索某个下标上的元素时效率极高,可以说查询效率最高的一个数据结构
            • 为什么检索效率高?
            • 第一:数组中元素的内存地址在空间存储上是连续的
            • 第二:每一个元素类型相同,所以占用空间大小一样
            • 第三:知道第一个元素的内存地址,有知道下标,所以通过一个数学表达式就可以某个下标上元素的内存地址,然后直接通过内存地址定位元素,所以数组的检索效率最高
            • 数组中存储100个元素,或者100万个元素,在元素检索方面,效率是一样的,因为数组中的元素查找的时候,不会一个一个找,是通过数学表达式计算出来的(算出一个内存地址,直接定位)
        • 缺点:
          • 第一:由于为了保证数组中每个元素的内存地址连续,所以在数组上随机删除或者增加元素的时候,效率较低,因为随机增删元素会涉及到后面元素统一向前或向后移的操作
          • 第二:数组不能存储大数据量,因为很难在内存空间上找到一快特别大的内存空间
          • 注意:对于数组中最后一个元素的增删,是没有效率影响的
      • 怎么声明/定义一个一维数组?
        • int[] array1;或int ayyar1[];//不建议这种,这是C++风格
        • double[] array2;
        • String[] array3;
        • Object[] array4;
      • 怎么初始化一个一维数组?
        • 包括两种方式:静态初始化一维数组、动态初始化一维数组
        • 静态初始化一维数组(定义的同时初始化):
        • int[] array={1,2,,3,4,5};
        • int[] array=new int[]{1,2,3,4,5};
        • 动态初始化一维数组(先定义,后初始化):
        • int[] array=new int[5];//5表示数组元素的个数,每个元素默认值0
        • 什么时候采用静态初始化方式,什么时候采用动态初始化方式?
        • 当创建数组的时候,确定数组中存储哪些具体的元素时,采用静态初始化方式
        • 当创建数组的时候,不确定数组中存储哪些元素时,采用动态初始化方式来预先分配内存空间、
      • public static void main(String[] args){}

        • System.out.println(args.length);//值是0,代表数组创建了只是没有任何数据

        • 其实这个数组是留给用户的,用户可以在控制台输入参数
        • 例如这样运行程序:java ArrayTest abc def xyz
        • 那么这个时候JVM自动将”abc def xyz“通过空格的方式进行分离,分离完成之后,自动放到“String[] args”数组中
        • 把abc def xyz 转换成字符串数组{“abc”,“def”,“xyz”}
      • 数组的扩容:

        • 在Java开发中,数组长度一旦确定不可变,那么数组满了怎么办?
        • 数组满了,需要扩容
        • Java中对数组的扩容:先建一个大容量的数组,然后将小容量的数组中的数据一个一个拷贝到大数组当中
        • 结论:数组扩容效率较低,因为涉及到拷贝的问题,所以在以后的开发中请注意,尽可能少的进行数组的拷贝,可以在创建对象的时候预估计多少合适,最好预估准确,这样可以减少数组的扩容次数,提高效率
    • 二维数组:

      • 二维数组其实是一个一维数组,特殊在这个一维数组当中的每一个元素是一个一维数组
        • 三维数组其实是一个二维数组,特殊在这个二维数组当中的每一个元素是一个一维数组
      • 二维数组的静态初始化:
        • int[][] a={{1,2,3,},{4},{5,6,7}};
        • int[][] array=new int[][]{{1,2,3,},{4},{5,6,7}};
      •  二维数组的动态初始化:

        • int array[][]=new int[3][4]; 
    • 常见的算法:
      • 排序算法:冒泡排序、选择排序.......
      • 查找算法:二分法查找
      • 以上的算法其实在Java中已经封装好了,直接调用就可以,只不过面试可能会碰上
      • 算法在Java中不需要精通,Java已经封装好,要排序调用方法就行,例如:Java中提供了一个数组工具类:
      • java.util.Arrays;//Arrays是一个工具类,其中sort()方法可以排序,是静态方法,直接使用类名调用就行
      • 冒泡排序:
      •  选择排序:

        • 选择排序比冒泡排序的效率高,高在交换位置的次数上,选择排序的交换位置是有意义的
        • 循环一次,然后找出参加比较的这对数据中最小的,拿着这个最小的值和最前面的数据交换位置
        •  选择排序和冒泡排序的比较次数没变,但是交换次数明显减少了

      • 二分法查找:二分法查找要建立在排序的基础之上

        • 二分法查找效率要高于“一个挨着一个”的这种查找方式

        • 二分法查找算法的终止条件:一直折半,直到中间的那个元素恰好是被查找的元素

    •  Arrays工具类:

      • Arrays是SUN公司为程序员已经写好的一个工具类
      • java.util.Arrays
      • int[] arr={10,21,30,5,3,8,19,22};
      • Arrays.binarySearch(arr,22);//用来对数组进行二分法查找
      • Arrays.sort(arr);//用来对数组进行排序
  • String类
    •  无论String a=“abc”;还是String a=new String("abc");a中都保存的是内存地址

    • 所以字符串比较的时候不能用双等号,双等号不保险 ,String类已经重写了equals方法,所以应该调用String类的equals方法

    •  String a="abc",  a.equals("abc");  和  "abc".equals(a)  建议使用 "abc".equals(a),可以避免空指针异常

    • 关于String类的常用构造方法:
    • String类的常用方法:

      •  charAt方法:
      • compareTo方法:

      • contains方法

      •  endsWith方法

      • startWith方法
      • equals方法

      • equalsIgnoreCase方法

      • getBytes方法
      • indexOf方法
      • lastIndexOf方法

      • isEmpty方法:length长度为0,则为空,

        • 判断数组长度和字符串长度不一样:
          • 判断数组长度是length属性
          • 判断字符串长度是length方法
      • replace方法
      • split方法

      • substring方法

      •  toCharArray方法

      •  toLowerCase方法

      • toUpperCase方法

      • trim方法

      •  valueOf方法

  •  StringBuffer类

    • 思考:我们在实际开发中,如果需要进行字符串的频繁拼接,会有什么问题?
      • 因为java中的字符串是不可变的,每一次拼接都会产生新的字符串
      • 这样会占用大量的方法区内存,造成内存空间的浪费
        • String s="abc";
        • s+="hello";
        • 就以上两行代码,就导致在方法区字符串常量池中创建了3个对象:
          • "abc"
          • "hello"
          • "abchello"
    • 如果以后需要进行大量的字符串拼接操作,建议使用JDK中自带的:
      • java.lang.StringBuffer
      • java.lang.StringBuilder
    • 如何优化StringBuffer的性能?
      • 在创建StringBuffer的时候尽可能给定一个初始化容量
      • 最好减少底层数组的扩容次数(因为每扩容一次底层就会调用System.arraycopy方法),预估计一下,给一个大一点些的初始化容量
    • String不可变:
    • StringBuffer可变:
    • StringBuffer和StringBuilder区别:

      • StringBuffer中的方法都有:synchronizaed关键字进行修饰,表示StringBuffer在多线程环境下是安全的
      • StringBuilder中的方法都没有:synchronizaed关键字进行修饰,表示StringBuilder在多线程环境下运行是不安全的
  • 包装类:
    • 装箱和拆箱:
      • 装箱:自动将基本数据类型转换为包装器类型;
      • 拆箱:自动将包装器类型转换为基本数据类型
    • 构造方法
    • 访问最大值和最小值
    • 自动装箱和拆箱

    • 数字格式化异常:
    • 字符串转换为int类型

  • java对日期的处理 

      • 注意:字符串的格式的日期格式和SimpleDateFormat对象指定的日期格式要一样,不然会出现异常
    • 获取自1970年1月1日 00:00:00 000到当前系统的总毫秒数

  •  简单总结一下System类相关属性和方法:

      • System.out【out是System类的静态变量】
      • System.out.println()【println()方法不是System类的,是PrintStream类的方法】
      • System.gc()【建议启动垃圾回收器】System.currentTimeMillis【获取自1970年1月1日 00:00:00 000到当前系统的总毫秒数】
      • System.exit(0)【退出JVM】
  • 数字格式化:
  • BigDecimal

  •  Random 

  •  枚举

    • 思考:以上的这个方法设计没毛病,挺好,返回true和false两种情况,但是在以后的开发中,有可能遇到一个方法的执行结果可能包括三种情况,四种情况,五种情况等等,但是每一种情况都是可以数清楚的,一枚一枚列举出来的,这个布尔类型就无法满足了,此时需要使用Java中的枚举类型

    •  枚举:一枚一枚列举出来的,才建议使用枚举类型

    • 枚举编译之后也是生成class文件
    • 枚举也是一种引用数据类型
    • 枚举怎么定义:
      • enum 枚举类型名{
        • 枚举值1,枚举值2;
      • }
    • 结果只有两种情况的建议使用布尔类型,结果超过2种并且还是可以一枚一枚列举出来的,建议使用枚举
      • 例如:颜色、四季、星期
  • 异常:

    • UML(统一建模语言):
      • 画UML图的工具有很多,例如Rational Rose(收费的)、starUML等...
      • 什么是UML?有什么用?
        • UML是一种统一建模语言
        • 一种图标式语言(画图的)
        • UML不是只有java中使用,只要是面向对象的编程语言,都有UML
        • 一般画UML图的都是软件架构师/系统分析师,这些级别的人员使用的
        • 在UML图中可以描述类和类之间的关系,程序执行的流程,对象的状态等
        • 在Java软件开发当中,java软件开发人员必须能看懂
    • java异常的结构图: 

      •  编译时异常又被称为受检异常/受控异常,运行时异常又被称为未受检异常/未受控异常

         编译时异常和运行时异常,都是在运行阶段发生的,因为程序只有在运行阶段才可以new对象,异常的发生就是new异常对象,编译阶段异常是不会发生的,

      • 编译时异常为什么而得名?

        • 因为编译时异常必须在编译(编写)阶段预先处理,如果不处理编译器报错,而得名
      •  编译时异常和运行时异常区别:
        • 运行时异常一般发生的概率比较低
          • 举个例子:
            • 你看到外面下雨,倾盆大雨
            • 你出门之前会预料到:如果不打伞,我可能会生病(生病是一种异常)
            • 而且这种异常的概率很高,所以我们出门之前要拿一把伞
            • 拿一把伞就是对生病异常的发生之前的一种处理方式
            • 小明走在街上,可能会被天上的飞机轮子砸到
            • 被飞机轮子砸到也算一种异常,
            • 但是这种异常发生概率低
            • 在出门之前你没必要对这种发生概率较低的异常进行预处理
            • 如果你预处理这种异常,你将活得很累
        • 假设Java中没有对一场进行划分,没有分为,编译时异常和运行时异常,所有的异常都需要在编写程序阶段进行预处理,将是怎样的效果呢?
          • 首先,这样的话,程序的绝对安全的,但是程序员编写代码太累,到处都是处理异常的代码
    • Java语言对异常的处理方式包括两种:
      • 第一种方式:在方法的声明位置使用throws关键字
        • 异常发生之后,如果一直上抛,最终抛给了main方法,main方法继续向上抛,抛给了调用者JVM,JVM知道这个异常发生了,只有一个结果,终止java程序
      • 第二种方式:使用try...catch方式进行异常的捕捉
    • 异常处理方式代码:

      • 向上抛:
      •  try...catch

    • 注意:

      • 只要异常没有捕捉,采用上报的方式,后续的代码就不会执行 

      •  另外需要注意,try语句块中的某一行出现异常,该行后面的代码不会执行

      • try..catch捕捉异常之后,后续的代码可以执行
    • try..catch深入
      • catch小括号中的类型,可以是具体的异常类型,也可以是异常类型的父类型
      • catch可以写多个,建议catch的时候,精确的一个一个处理,这样有利于程序的调试
      • catch写多个的时候,从上到下,必须从小到大 

      • JDK8的新特性:
    • 异常对象有两个非常重要的方法:

      • 获取异常简单的描述信息
        • String msg=exception.getMessage();
      • 打印异常追踪信息
        • exception.printStackTrace();
    • 发生异常和打印堆栈信息
      • 发生异常
      • 打印堆栈信息 
    •  我们以后查看异常追踪信息,应该怎么看,可以快速调试程序?

      • 异常追踪信息,从上往下一行一行看
      • 但需要注意,SUN公司写的代码就不用看了(看包名就知道是自己的还是SUN的),主要问题是出现在自己编写的代码上
    • finally
      • 补充:如果初始化的语句用在try块中或if块中,也必须要让它在第一次使用前一定能够得到赋值。也就是说,把初始化语句放在只有if块的条件判断语句中编译器也会抗议,因为执行的时候可能不符合if后面的判断条件,如此一来初始化语句就不会被执行了,这就违反了局部变量使用前必须初始化的规定。但如果在else块中也有初始化语句,就可以通过编译,因为无论如何,总有至少一条初始化语句会被执行,不会发生使用前未被初始化的事情。对于try-catch也是一样,如果只有在try块里才有初始化语句,编译不通过。如果在catch或finally里也有,则可以通过编译。
    • 自定义异常类:
      •   

  • finalize()是什么?
    • 垃圾回收机器(Garbage Collection),也叫GG,垃圾回收器主要有以下特点:
    • 1. 当对象不再被程序所使用的时候,垃圾回收器将会将其回收

    • 2. 垃圾回收是在后台运行的,我们无法命令垃圾回收器GC马上回收资源,但是我们可以告诉他可以尽快回收资源(System.gc()和Runtime.getRuntime().gc())

    • 3. 垃圾回收器在回收某个对象的时候,首先会调用该对象的finalize()方法

    • 4. GC主要针对堆内存

  •  final、finalize、finally的区别?

    • final是一个关键字,表示最终的,不可变的
    • finally也是一个关键字,和try联合使用,使用在异常处理机制中,finally语句块中的代码是一定会执行的
    • finalize()是Object类中的一个方法,作为方法名出现,所以finalize是标识符,这个方法是由垃圾回收器GC负责调用的
  • throws和throw区别
    • throws在方法的声明位置上使用,表示上报异常给声明者
    • throw手动抛出异常
  • 集合
    • 什么是集合?有什么用?
      • 数组其实就是一个集合,集合实际上就是一个容器,可以来容纳其他类型的数据,但数组可以存储基本数据类型,也可以存储引用数据类型;集合只能存储引用数据类型
    • 集合为什么说在开发中使用较多?
      • 集合是一个容器,是一个载体,可以一次容纳多个对象,在实际开发中,假设连接数据库,数据库当中有10条数据,那么假设把这10条记录查询出来,在Java程序中会将10条数据封装成10个Java对象,然后将10个Java对象放到某一个集合当中,将集合传到前端,然后遍历集合,将数据一个个展现出来
    • 集合不能直接存储基本数据类型的数据,另外集合也不能直接存储java对象,集合当中存储的是java对象的内存地址(或者说,集合存储的是引用)
      • list.add(100);//自动装箱Integer
      • 注意:
        • 集合在java中本身是一个容器,是一个对象
        • 集合中任何时候存储的都是引用
    • 数组和集合的区别:
      • 数组可以存储基本数据类型,也可以存储引用数据类型;集合只能存储引用数据类型
      • 当我们需要保存一组类型相同的数据的时候,我们应该是用一个容器来保存,这个容器就是数组,但是,使用数组存储对象具有一定的弊端, 因为我们在实际开发中,存储的数据的类型是多种多样的,于是,就出现了“集合”,集合同样也是用来存储多个数据的。
    • 集合的内存空间可以连续也可以不连续,元素类型可以相同也可以不同
    •  

      在java中每一个不同的集合,底层会对应不同的数据结构,往不同的集合中存储元素,等于将数据放到了不同的数据结构当中,什么是数据结构? 数据存储的结构就是数据结构,不同的数据结构,存储方式不同,例如:数组、二叉树、链表、哈希表等等

    • 在Java集合这一章,需要掌握的不是精通数据结合,Java中已经将数据结构实现了,已经写好了常用的集合类,你只需要掌握怎么用?在什么情况下选择哪一种集合去使用即可
    • 集合在java.util.*;下,所有的集合类和集合接口都在java.util包下
    • java集合分为两大类:
      • 一类是单个方式存储元素:
        • 单个方式存储元素,这一类集合中的超级父接口:java.util.Collection
      • 另一类是键值对儿的方式存储元素:
        • 以键值对的方式存储元素,这一类集合中的超级父接口:java.util.Map
    • 集合的继承结构图
      •  

      • 类之间的关系
        •  依赖:一个类作为另一个类的返回值类型,形参类型,局部变量类型(虚线箭头)
        • 关联:一个类作为另一个类的成员变量类型 (实线箭头)
        • 继承:子类和父类之间,子接口和父接口之间(实线空心三角)
        • 实现:子类和接口之间(虚线空心三角)
      • 总结: 

        • ArrayList:底层是数组
        • LinkedList:底层是双向链表
        • Vector:底层是数组,线程安全的,效率低,使用较少
        • HashSet:底层是HahMap,放到HashSet集合中的元素,等同于放到HashMap集合的key部分了
        • TreeSet:底层是TreeMap,放到TreeMap集合中的元素,等同于放到TreeMap集合key部分了
        • HashMap:底层是哈希表
        • Hashtable:底层是哈希表,只不过是线程安全的,效率较低,很少使用
        • Properties:是线程安全的,并且key和value只能存储字符串String
        • TreeMap:底层是二叉树,TreeMap集合的key可以自动按照大小顺序排序
    • 关于java.util.Collection接口中的常用方法
    • 迭代器:

      •