• Java 基础总结


                                     Java基础总结


    jdk:Java的开发环境与部署环境
    jre:Java的运行环境


    Java数据类型分为:基本类型和引用类型
    基本类型:①整数类型 byte   short   int   long 默认值: 0
      ②字符类型 char 默认值: 空格
      ③浮点类型 float  double 默认值: 0.0
      ④布尔类型 boolean 默认值: false
    引用类型:①类
     ②接口
     ③数组
     ④ null 类型
    Java中除基本类型之外的类型都被称为引用类型,默认值为: null


    八大基本数据类型: 
    byte 字节型 1个字节 8位 -2^7~2^7-1
    short 短整型 2个字节 16位 -2^15~2^15-1
    int 整型 4个字节 32位 -2^31~2^31-1 默认
    long 长整型 8个字节 64位 -2^63~2^63-1 使用时在数据最后加 L/l
    float 单精度浮点型 4个字节 32位 使用时在数据最后加 F/f
    double 双精度浮点型 8个字节 64位 默认
    char 字符型 2个字节 16位 0~65535
    boolean 布尔型 1个字节 8位 false true
    可以给 char 型的变量直接赋 int 型的值,取值范围是0~65535,但是不能直接赋整数的变量。
    整数与小数(整型与浮点型)运算得到的结果是一个浮点型的数。
    整数与整数(或整型变量)运算得到的是一个 int 型的值,但 long 与其他整数进行运算得到的是一个 long 型的值。


    数据类型转换: 字节小的可以直接转换成字节大的
    强制类型转换: 需要的数据类型 变量名=(需要的数据类型)要转换的数据


    Java运算符:
    算术运算符: + - * / %  
    赋值运算符: = += -= *= /= %= &= |= ^= <<= >>= >>>=
    位运算符: &(按位与) |(按位或) ~(按位非) ^(按位异或) <<(左移运算符) >>(右移运算符) >>>(无符号右移运算符)
    比较运算符: > < >= <= == !=
    逻辑运算符: &&(逻辑与):两者为真才为真,只要一个为假,结果则为假 运算时如第一个运算结果为假,则不再进行后续运算 得到结果为假
    ||(逻辑或):一个为真,结果就为真 运算时,如第一个运算结果为真,则后续运算不再进行 得到结果为真
    !(逻辑非): 把假变真,把真变假
    &(不短路与)
    |(不短路或)
    ^(异或):当两个结果不同时才返回 true,当两个结果相同时则返回 false;
    自增自减: ++(自增): 前++: 先自增再运算  后++: 先运算再自增
      --(自减): 前--: 先自减再运算  后--: 先运算再自减
    三目运算符: (先对逻辑表达式求值) ? (为真返回结果) : (为假返回结果);


    &和&&的区别:
    单&时,左边无论真假,右边都进行运算;
    双&时,如果左边为真,右边参与运算,如果左边为假,那么右边不参与运算。
    |和||的区别同理,双或时,左边为真,右边不参与运算。


    ==与=号的区别:
    ==判断等号两边是否相等,==号判断八大基本数据类型的时候是比较值是否相等,比较非八大基本数据类型的时候是比较引用地址是否相等
    =号是赋值运算符,是将=号右边的数值赋值给=号左边;


    条件语句: 
    ① if(条件表达式){
    代码块;
       }
    ② if 嵌套:if(条件表达式1){
        if(条件表达式2){
         if(条件表达式n){
       代码块;
         }
        }
           }
    ③ if(条件表达式){
    代码块1;
       }else {
     代码块2;
       }
    ④ if(条件表达式1){
    代码块1;
       }else if(条件表达式2){
    代码块2;
       }else if(条件表示式3){
    代码块3;
       }else{
    代码块4;
       }
    ⑤ switch(值或一个变量){
    case 值1:
    执行内容;
    break;
    case 值2:
    执行内容;
    break;
    default:
    默认内容;
    break;

    switch 条件中可以使用的类型:byte,short,int,char,枚举,jdk1.7后可以使用 String;


    循环控制语句:
    for 循环: for (初值表达式;终止条件;步长表达式){
    语句块;
     }
    while 循环: while (循环条件){
    循环体;
    迭代语句;
       }
    do while 循环: do{
    循环体;
    迭代语句;
      }while (循环条件);
    do while 特点是条件无论是否满足,循环体至少被执行一次。

    foreach 循环: Java1.5后才出现
    使用 foreach 循环遍历数组和集合元素时,无须获得数组和集合长度,无须根据索引来访问数组元素和集合元素


    foreach 循环与普通循环的区别:无须循环条件,无须循环迭代语句;


    九九乘法表:
    for (int i=1;i<=9 ;i++ )
    {
    for (int j=1;j<=i ;j++ )
    {
    System.out.print(j+"*"+i+"="+i*j+" ");
    }
    System.out.println();
    }


    百钱买百鸡:100元钱买100只鸡,其中公鸡5元一只,母鸡3元一只,小鸡3只一元,问有多少方案?
    for (int cock=1;cock<=20 ;cock++ )
    {
    for (int hen=1;hen<=33 ;hen++ )
    {
    for (int chick=3;chick<=99 ;chick+=3 )
    {
    if (cock*5+hen*3+chick/3==100) //百钱
    {
    if (cock+hen+chick==100) //百鸡
    {
    System.out.println("公鸡: "+cock+" 母鸡: "+hen+" 雏鸡: "+chick);
    }
    }
    }
    }
    }


    斐波那契数列:0、1、1、2、3、5、8、13、21、34....
    ①int[] arr = new int[20];  
    arr[0] = arr[1] = 1;  
    for (int i = 2; i < arr.length; i++) {  
    arr[i] = arr[i - 1] + arr[i - 2];  
    }  
    System.out.println("斐波那契数列的前20项如下所示:");  
    for (int i = 0; i < arr.length; i++) {  
    System.out.print(arr[i] + " ");  

    ②int s=1;
    int k=1;
    int temp=0;
    for (int i=0; i<20;i++ ){
    temp=s+k;
    s=k;
    k=temp;
    }
    System.out.println("斐波那契数列的前20项"+temp);  


    1~100以内的质数:
        for(int i=1;i<=100;i++) {
          for(int j=2;j<=i;j++){
           if(i%j==0)//素数是指除了1和自身外不能被任何数整除的数,因此遍历每一个小于i大于2的整数j
           //如果i能够被j整除
             if(i==j)
               //如果当i等于j的时候则满足i是素数的条件,即只能被1(j是从2计数的)和自身整除,因此i是素数
               System.out.println(i +"是素数");
             else
               //在如果存在一个小于i大于2的整数j可以整除i,则i必不是素数,因此break操作.
               break;//如果i可以被j整除且j不等于i,则跳出循环
          }
        }


    打印正三角形:
    for(int i=1;i<=10;i++){
    for(int j=10-i;j>0;j--){
    System.out.print(" ");
    }
    for(int j=1;j<=2*i-1;j++){
    System.out.print("*");
    }
    System.out.println();
    }


    break:跳出当前循环语句(结束当前循环语句);
    continue:结束本次循环,继续执行下一次循环,而不是直接退出,
    当使用 continue 时,此后的代码将无法运行,可以控制循环何时结束;
    return:返回方法,后面不能再存在语句


    数组:同一种数据类型的集合(下标从0开始~length-1结束)
    格式:数据类型[] 数组名=new 数据类型[数组长度];
    获取数组长度: 数组名.length;
    获取数组元素: 数组名[下标号];
    数组遍历与数组增删查改
    二维数组:
    格式:数据类型[][] 数组名=new 数据类型[行数][列数];
     数据类型[][] 数组名={{},{},{}};
    冒泡排序法:把小的泡冒到上面,大的沉到下面,最值在中间与其他值进行交换
    for (int i=0;i<array.length-1 ;i++ )
    {
    for (int j=0;j<array.length-i-1 ;j++ )
    {
    if (array[j]>array[j+1])
    {
    int temp=array[j];
    array[j]=array[j+1];
    array[j+1]=temp;
    }
    }
    }

    选择排序法:
    for (int i=0;i<array.length-1 ;i++ )
    {
    for (int j=i+1;j<array.length ;j++ )
    {
    if (array[i]>array[j])
    {
    int temp=array[i];
    array[i]=array[j];
    array[j]=temp;
    }
    }
    }


    从前往后删除多个:
    for (int i=0;i<count ;i++ )
    {
    if (del==array[i][0])
    {
    for (int j=i;j<count-1 ;j++ )
    {
    for (int k=0;k<array[i].length ;k++ )
    {
    array[i][j]=array[i+1][j];
    }
    }
    count--;
    i--;
    }
    }


    ------------------------------------- 面 向 对 象 --------------------------------------
    数据结构
    目的:加强类与对象的内存分配理解、加强操作能力、理解数据结构。
    数据:计算机化的信息。
    数据元素:数据的基本单位,即数据集中的个体,节点、记录
    数据项:有独立含义的数据,数据域、字段
    数据对象:具有相同特性的数据元素的集合。

    结构:数据元素之间的关系
    数据结构:带有结构的数据对象
    线性结构:各数据元素之间的逻辑可以用一个线性序列简单的表达出现,反之为非线性结构
    线性结构包括:线性表(数组,链式表(单链,双链))、队列,栈
    非线性结构:树(只有一个根结点)、图
    栈:限定只能从表一端进行插入和删除的线性表
    特点:First In Last Out(FILO) 先进后出
    队列:限定只能在表的一端进行插入运算,在表的另一端进行删除运算的线性表
    特点:First In First Out(FIFO) 先进先出


    数组与链表的区别:
    ①存储空间的区别:数组是静态分配内存空间的,所有元素时存放在一组地址连续的存储单元中,一旦分配,不可更改,也就不便于扩展,
    数据元素在数组中的顺序号可确定它在存储单元中的位置,因此顺序中不需要指针域,而链表是动态分配内存空间,存储空间是不确定的。
    ②数组便于查找和修改(因为是下标定位),但是不利于插入和删除(删除的时候数组要一个一个的移动,数据的移动量过大),也不便于扩充因为它是连续的地址,
    是静态的存储结构,而链表不便于查找与修改(需要从链头找到链尾数组量过大),但便于插入,删除且速度快(因为可以指针直接指向,删除的时候直接脱链就可以了)。


    链表是不是二叉树?
    是,链表是左斜树或右斜树中的一种。
    左斜树:从根节点开始,所有节点都一直往左走。
    右斜树:从根节点开始,所有节点都一直往右走。


    树是N(N>0)个结点的有限集合,在一棵非空有限集合中,有且仅有一个特定的结点称为树的根结点,根节点之下可以有0个以上的子节点(也可以没有),而各子节点称为此树的子树。
    根结点、叶子结点(终端结点)、父结点、兄弟结点、结点度(分支度)、树的度(树的分支度)、阶层、高度(深度)、祖先、林、
    根结点:一个树当中没有父结点的结点。
    叶子结点(终端结点):一棵树中没有子结点的结点。
    非终端结点:除叶子结点以外的所有结点。
    兄弟结点:同一个父结点的所有结点。
    结点度(分支度):每一个结点拥有结点的个数。
    树的度(树的分支度):一棵树中最大的结点。
    阶层:结点特性值:将结点值设为1,其子结点的值为2。
    高度和深度:一棵树中最大阶层值。
    祖先:由某个结点X到根结点之路径上的所有结点。


    二叉树也被称为二次树或二分树,是树的一种,二叉树的结点最多只有两个,因此二叉树的结点度最大值是2。
    二叉树的定义: 由有限个结点所构成之集合,此集合可以为空。
    二叉树的结点可以分为两棵子树,称左子树和右子树。同时左右子树也是二叉树。
    在二叉树的第I层最多有2的I减1次方个结点。(I>=1)。2^(I-1)
    高度为K的二叉树中最多有2的K次方减1个结点。2^K-1

    满二叉树:树中所有结点均在同一阶层而其它非终端结点度均为“2”,且树的高度是K,其结点为2的K次方减1。2^k-1
    完全二叉树:一棵树中扣除最大阶层,那层后一满二叉树,且阶层最大层的阶层均向左对齐。此树称为完全二叉树。
    一棵树如果是满二叉树,那么它一定是完全二叉树,一棵树如果是完全二叉树,它不一定是满二叉树。


    (小左大右)
    二叉树的遍历:①先序:根 左 右 若二叉树非空,则访问根结点,按先序遍历左子树,再遍历右子树。
     ②中序:左 根 右 若二叉树非空,按中序遍历左子树,再访问根结点,再按中序遍历右子树。
     ③后序:左 右 根 若二叉树非空,按后序遍历左子树,再遍历右子树,再访问根结点。


    二叉树的删除:①无左无右:分为: 根结点 非根结点,但是是叶子结点(分为:左叶子 右叶子)
     ②有左无右:分为: 根结点 非根结点(分为:左结点 右结点)
     ③有右无左:分为: 根结点 非根结点(分为:左结点 右结点)
     ④有左有右:分为: 根结点 非根结点(分为:左结点 右结点)(判断是要上移左结点的最右边或右结点的最左边)


    树与二叉树的比较:
    二叉树可以为空,而树不可以(至少要有根结点)。
    二叉树的子树有顺序关系,而树没有。
    二叉树的度必为(0 ,1, 2)而树的结点度可以大于2。




    定义Java中的方法:
    访问修饰符  返回值类型   方法名(参数列表){
    方法体;
    }
    方法的优点: (方法的命名以小写字母开头,遵循驼峰命名规则)
    ①使程序变得更简短而清晰
    ②有利于程序的维护
    ③可以提高程序开发的效率
    ④提高了代码的复用性

    class 类名{
    属性(成员变量): 数据类型 属性名=初始值;
    行为(方法);
    }
    根据类来创建对象:
    语法: 类型(数据类型)变量名=new 类名(); //类名与变量名不能一致
    类的对象的调用: 
    对象的变量名.方法名([参数]);
    在同一个Java文件中可以定义多个类,但是只有一个类可以用 public 修饰,并且类名要与 public 所修饰的类名保持一致。


    成员变量(实例变量、全局变量):成员变量定义在类中,在整个类中都可以被访问
     成员变量有默认初始化值,每 new 一次就开辟一次内存空间
    成员变量随着对象的建立而建立,存在于对象所在的堆内存中
    局部变量:局部变量只定义在局部范围内(函数内,语句内等)
     局部变量存在于栈内存中,作用范围结束,变量空间将自动释放
     局部变量没有默认初始化值
    类变量:使用 static 修饰,只开辟一次内存,定义在类中
       伴随类的存在而存在,释放内存较晚
    成员变量与类变量的区别:
    ①存放位置: 类变量随着类的加载而存在于方法区中,实例变量随着对象的建立而存在于堆内存中、
    ②生命周期: 类变量生命周期最长,随着类的消失而消失,实例变量生命周期随着对象的消失而消失


    静态变量和实例变量的区别:
    ①在语法定义上的区别: 静态变量前要加static关键字,而实例变量前则不加。
    ②在程序运行时的区别: 实例变量属于某个对象的属性,必须创建了实例变量,其中的实例变量才会被分配空间,才能使用这个实例变量。
       静态变量不属于某个实例对象,而属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会分配空间,静态变量就可以被使用了。
    实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。




    面向对象开发经过 OOA(面向对象分析)、OOD(面向对象设计)和 OOP(面向对象编程) 三个阶段
    面向对象(OO): 将功能封装进对象,强调具备了功能的对象
    类与对象的关系: 类是对象的抽象,对象是类的实例
    类的成员包括: 属性(变量)和行为(方法)
    用来描述对象的动态特征(行为)的一个动作序列是对象的方法而非属性,类的方法描述了该类的对象的行为
    使用对象的属性形式是: 对象.属性名
    使用对象的方法形式是: 对象.方法名()
    面向对象的三大(四大)特征: 封装、继承、多态(抽象)
    面向对象的思维:
    作为面向对象的思维来说,当考虑问题时,不应该再考虑第一步干嘛,第二步干嘛,而应该首先考虑,作为这个问题来说,
    在这个问题里,应该有哪些类哪些对象;然后再考虑这些类和对象,每一种类和每一种对象,应该具有哪些属性和方法;
    再考虑类与类之间具备了什么样的关系。


    Java中参数传递:
    ①传值:方法调用时,实参把它的值传递给对应的形参,方法执行中形参值的改变不影响实参的值。(八大基本类型)
    ②传引用(传址):方法调用时,实参的引用(地址,而不是参数的值)被传递给方法中相对应的形参,
    在方法执行中,对形参的操作实际上就是对实参的操作,方法执行中形参值的改变将会影响实参的值。(非八大基本类型,数组,对象)


    权限修饰符: public 公共的 > protected 受保护的 > default 默认的、缺省的、友元 > private 私有的
    所有类、所有包 > 本类、本包、子类  > 本包、本类 (包修饰符)        > 本类


     static 静态修饰符
    ① static 修饰的方法是静态方法,静态方法不能直接访问非静态方法,静态方法可以直接访问静态方法和静态属性
    ②非静态方法任何时候都可以直接访问静态方法和静态属性
    ③静态的方法和属性可以直接用类名.访问(不同类中)
    ④ static 修饰的方法和属性内存只分配一次,在内装载器中开辟内存
    ⑤ static 修饰的变量是属于类而不属于对象, static 修饰的内容被对象所共享
    ⑥ static 不能以任何形式去访问 this 和 super
    ⑦如果想在第一时间执行加载某段代码,可以使用静态代码块(静态代码块只会执行一次)
    ⑧ main 方法是程序的入口,必须使用 static 修饰
    ⑨ static 不能修饰类(内部类可以使用 static 修饰),不能修饰构造方法
    静态是在内装载器中开辟内存,而非静态是在 new 一个对象的时候才在堆内存中开辟内存
    静态如果想要调用非静态,必须要先 new 一个对象,然后使用对象调用
    当成员被静态修饰符修饰时,就多了一个调用方式,除了可以被对象调用外,还可以直接被类名调用,类名.静态成员


    是否可以从一个static方法内部发出对非static方法的调用?
    不可以,因为非static方法是要与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方法调用,而static方法调用时不需要创建对象,可以直接调用。


    重载( overload ): 在同一个类中,方法名相同,参数列表不同,与返回值及权限修饰符无关
    参数列表不同的情况: ①参数个数的不同
      ②参数个数相同,但参数类型不同
      ③参数个数与参数类型都相同时,参数类型的顺序不同


    封装(private): 把一个对象的属性私有化,同时提供一些可以被外界访问的属性和方法, setter() 方法和 getter() 方法,this代表当前对象
    封装就是使用方法将类的数据隐藏起来,控制用户对类的修改和访问数据的程度。
    隐藏对象的内部实现细节
    private double money;
    public void setMoney(double money){
    this.money = money;
    }
    public double getMoney(){
    return this.money;
    }
    封装的好处: ① 类内部的结构可以自由的修改
    ② 可以对成员进行更精确的控制
    ③ 隐藏信息,实现细节


    继承(extends): 子类继承父类除私有化修饰的属性和方法 具有 "什么什么是一种什么" 二者之间就存在继承关系
      关键字: extends (子类其实也继承了父类私有化修饰的属性和方法,但是子类没有访问父类中私有化修饰的属性和方法的权限)
    父类(超类、基类)(superclass) 子类(派生类) object 类是所有类的父类(祖宗类)
    继承的特点: Java只支持单一继承,不支持多继承 一个子类只能有一个直接父类,一个父类可以有多个子类
    继承的优点: 减少了代码的冗余,提高了代码的复用性
    继承的目的: 让子类可以使用父类除私有化修饰的属性和方法


    重写( override / overwrite )(方法覆盖): 建立在继承的基础之上,子类与父类拥有相同的方法名,相同的参数列表,子类返回值权限小于等于父类返回值权限,并且子类方法访问权限大于等于父类方法访问权限
    重写遵循 两同两小一大 原则:
    两同: ①方法名相同 
      ②形参列表相同
    两小: ①子类方法返回值类型应比父类方法返回值类型更小或相等
      ②子类方法声明抛出的异常类应比父类方法声明抛出的异常类更小或相等
    一大: 子类方法的访问权限应比父类方法的访问权限更大或相等
    为何需要重写: 当父类方法不能满足子类的需求的时候,就需要重写父类方法


    重载与重写的异同: 
    同:都有相同的方法名
    异:①重载是在同一个类中,而重写是在继承的基础上,在子父类中
       ②重载是方法的参数列表不同,而重写是子父类中方法参数列表一致
       ③重载与返回值无关,而重写是子类方法返回值类型比父类方法返回值类型更小或相等
       ④重载与权限修饰符无关,而重写是子类方法的访问权限比父类方法的访问权限更大或相等
    Overload 和 Override 的区别。Overloaded的方法是否可以改变返回值的类型?
    Overload是重载的意思,Override是覆盖的意思,也就是重写。
    重载Overload表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同(即参数个数或类型不同)。
    重写Override表示子类中的方法可以与父类中的某个方法的名称和参数完全相同,
    子类覆盖父类的方法时,只能比父类抛出更少的异常,或者是抛出父类抛出的异常的子异常,
    子类方法的访问权限只能比父类的更大,不能更小。
    Override 可以翻译为覆盖,它是覆盖了一个方法并且对其重写,以求达到不同的作用,在覆盖是要注意:
    1、覆盖的方法的标志必须要和被覆盖的方法的标志完全匹配,才能达到覆盖的效果;
    2、覆盖的方法的返回值必须和被覆盖的方法的返回一致;
    3、覆盖的方法所抛出的异常必须和被覆盖方法的所抛出的异常一致,或者是其子类;
    4、被覆盖的方法不能为private,否则在其子类中只是新定义了一个方法,并没有对其进行覆盖。
    Overload对我们来说可能比较熟悉,可以翻译为重载,是指我们可以定义一些名称相同的方法,通过定义不同的输入参数来区分这些方法,
    然后再调用时,VM就会根据不同的参数样式,来选择合适的方法执行,在使用重载要注意:
    1、在使用重载时只能通过不同的参数样式。例如,不同的参数类型,不同的参数个数,不同的参数顺序(当然,同一方法内的几个参数类型必须不一样);
    2、不能通过访问权限、返回类型、抛出的异常进行重载;
    3、方法的异常类型和数目不会对重载造成影响;
    4、对于继承来说,如果某一方法在父类中是访问权限是private,那么就不能在子类对其进行重载,如果定义的话,也只是定义了一个新方法,而不会达到重载的效果。
    Overloaded的方法可以改变返回值的类型,因为重载与返回值无关。

    构造方法(构造器)( constructor ):
    ①方法名与类名一样
    ②构造方法无返回类型,并且在new一个对象的时候,由JVM自动调用
    ③构造方法同样遵从方法重载的原则
    ④在构造方法中调用另一个构造方法, this 语句必须放在第一行,this(要调用的构造方法的参数)
    ⑤提前初始化类中的属性和方法
    ⑥如果程序在类中有非空构造方法,那么JVM不会自动生成空构造方法,否则会自动生成一个空构造方法
    ⑦ new 一个对象的时候,从这个对象开始到 object ,默认是最子类查找空构造方法直到 object ,
      途中如果有一个类缺少空构造方法,则编译不通过。
      查找是从最子类查找到最父类
      执行是从最父类执行到最子类
    ⑧ super 可调用父类的非空构造方法 super(要调用构造方法参数);要放在第一行。
      super 调用父类的属性和方法
    ⑨不能使用 static 修饰构造方法


    在同一个构造方法中,不能同时出现使用 super 与 this 调用构造函数,因为在构造函数中,
    使用 super 与 this 调用构造方法,语句都需要放在程序的第一行!!!


    构造器Constructor是否可以被Override?
    构造器Constructor不能被继承,因此不能重写Override,但可以被重载Overload。


    多态(动态绑定、迟绑定)( Polymorphism ): 使用 instanceof 判断前一个对象是否为后一个类的实例
    指在执行期间(而非编译期)判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。
    多态是建立在继承的基础之上,在继承机制的允许下,可以将某个对象看成其所属类,也可以看成其超类,这样就可以将
     多个对象看成同一个类,当子类重写父类的方法,由同一个对象调用,产生不同的行为,这种现象就叫多态。
    把子类的实例赋给父类的引用,父类的引用指向子类的实例。
    多态存在的三个必要条件:①要有继承
    ②要有重写
    ③父类引用指向子类对象
    三个条件满足,当你调用父类里被重写的方法时,实际中 new 的哪个子类对象就调用哪个子类对象的方法。
    非静态方法: 父有子有,调子类方法;父有子无,调父类方法;
    静态方法:父有子有,调父类方法;父有子无,调父类方法;
    属性:父有子有,调父类方法;父有子无,调父类方法;
    父无子有 编译失败
    引用类型变量 instanceof 类(接口)
    instanceof 运算符前面操作数的编译时,类型要么与后面的类相同,要么与后面的类具有父子继承关系,否则会引起编译错误。
    instanceof 运算符的作用是: 在进行强制类型转换之前,首先判断前一个对象是否为后一个类的实例,是否可以成功转换,从而保证代码更加健壮。
     
    final:
    ①可以修饰类,但是不能被继承(没有子类, final 类中的方法默认是 final 的)
    ②可以修饰方法,但是不能被重写,可以被继承
    ③可以修饰属性,修饰的属性值不能改变,是一个常量(常量命名规则,字母全部是大写,两个单词以上的用"_"连接)
    ④可以修饰参数,修饰的参数也不能改变
    ⑤不能修饰构造方法。


    使用final 关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?
    使用final 关键字修饰一个变量时,是引用变量不能变,引用变量所指向的对象中的内容还是可以改变的。


    抽象类:abstract 抽象的就是看不懂的
    抽象类的含义:逆着关系由下向上(从子类到父类),类逐渐变得通用,变得抽象,越往上越通用、越抽象,越往下越具体实用
    注意事项:
    ①抽象方法所在的类就是抽象类
    ②抽象方法:没有方法体的方法就叫做抽象方法,抽象方法要用 abstract 修饰
    ③抽象类不能 new(不能实例化)
    ④抽象类可以被继承,但是子类要有两种情况(1.重写父类的所有抽象方法 2.要么子类用 abstract 修饰)
    ⑤抽象类可以继承抽象类,也可以继承普通类,普通类也可以继承抽象类
    ⑥抽象类里面可以有变量、常量、普通方法、构造方法
    ⑦抽象方法不能用 private 修饰(私有化)
    ⑧抽象方法不能用 static 修饰
    ⑨抽象类也不能用 final 修饰
    ⑩被 abstract 修饰的东西不能与 native 同时使用,也不能与 synchronized 同时使用
    ⑾抽象类中的方法要被使用,必须由子类重写其所有的抽象方法后,建立子类对象调用
    如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类


    接口:interface 扩展了程序的功能
    概念:和类是同一种结构,但是比抽象类更加抽象
    (可以把接口理解为一个纯的抽象类,接口里所有的方法都是抽象方法)
    注意事项:
    1.接口里不能有构造方法、不能有普通方法、可以有抽象方法
    2.接口里抽象方法可以加 abstract 修饰,可以不加,默认会是 public 、 abstract 修饰
    3.接口里面的抽象方法不能用 protected 和 private 修饰,可以用 public 修饰
    4.接口里可以有变量、常量、静态常量,编译后所有属性都是静态常量(默认为:public static final 修饰)
    5.接口可以用来弥补Java里面类单一继承的缺陷
    6.接口可以继承接口,并且可以继承多个接口(接口只能继承接口,不能继承类,继承多个接口中间用","分隔)
    7.类可以实现多个接口(实现接口后必须要重写所有的抽象方法),实现多个接口的时候用","分隔
    8.接口不能实例化(不能 new)
    9.实现接口关键字:implements
    10.类实现接口语法是: class 类名 implements 接口名


    类可以继承一个类的同时实现多个接口。


    为什么Java不支持多继承却支持多实现?
    因为多继承的方法,都存在方法体,当子类重写父类的方法时,会使JVM绑定规则变得更复杂,
    而多实现的方法,不存在方法体,可以由子类任意定义,只需重写一次,故而不会增加JVM的绑定机制和复杂度。


    抽象类与接口的区别: 
    同: ①都是上层的抽象层
        ②都不能实例化
        ③都能包含抽象的方法,这些抽象的方法用于描述类具备的功能,但是不必提供具体的实现。
    异: ①在抽象类中可以写非抽象的方法,从而避免在子类中重复书写他们,这样可以提高代码的复用性,这是抽象的优势;接口中只能有抽象的方法。
        ②一个类只能继承一个直接父类,这个父类可以是具体的类也可以是抽象类;但是一个类可以实现多个接口。
    接口可以继承接口。抽象类可以实现(implements)接口,抽象类可以继承具体类。抽象类中可以有静态的main方法。


    abstract class类中定义抽象方法必须在具体(Concrete)子类中实现
    接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的
    接口中的方法定义默认为public abstract类型,接口中的成员变量类型默认为public static final


    抽象类与接口两者的语法区别:
    1.抽象类可以有构造方法,接口中不能有构造方法。
    2.抽象类中可以有普通成员变量,接口中没有普通成员变量
    3.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
    4. 抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然eclipse下不报错,但应该也不行),但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。
    5. 抽象类中可以包含静态方法,接口中不能包含静态方法
    6. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。
    7. 一个类可以实现多个接口,但只能继承一个抽象类。
    两者在应用上的区别:
    接口更多的是在系统架构设计方法发挥作用,主要用于定义模块之间的通信契约。
    而抽象类在代码实现方面发挥作用,可以实现代码的重用.
    ------------------------------------------------------------------------------------------------------------------------------------------
    面向对象试卷知识点解析
    1. Java是一种面向对象的语言,其核心概念即 类和对象,采用面向对象的设计思想可以利用封装、继承和多态实现代码的复用。
    2. 所谓对象就是真实世界中的实体,对象与实体是一一对应的,类是具备某些共同特征的实体的集合,它是一种抽象的概念。
       类是一种抽象的数据类型,它是对所具有相同特征实体的抽象,类与对象的关系:类是对象的抽象,对象是类的实例。
    3. 在Java中,一组有相同属性、共同行为和共同关系的对象的抽象称为类。
    4. 类是对象的抽象,对象是类的实例。
    5. 类的实例是对象,类是对现实世界中客观事物的抽象。
    6. 用来描叙对象的动态特征的一个动作序列是对象的方法而非属性。类的方法描述了该类的对象的行为。
    7. 使用对象的属性形式是 对象.属性,使用对象的方法形式是对象.方法名();属性是对象所拥有的静态特征,方法是对象拥有的动态特征。
    8. 类的成员包括属性和行为。
    9. 在Java中,定义一个类使用关键字 class ,而创建类的对象则使用 new 关键字。类可以是 private 的也可以是 public 的。
    10.方法定义后,声明为 public 的方法,可以被本类或其他类调用,而如果被本来的其他方法定义,不一定非要声明为 public 。
    11.方法的调用,在本类中两个普通方法的相互调用,可以直接写方法名即可,也可以通过 this 关键字调用。
    12.对象的方法除在main()中可以调用外,也可以在其他位置调用。
    13. Java中类的创建方式: 访问修饰符  class  类名{}
    14. Java中无参方法的创建方式: 访问修饰符 返回值类型 方法名(){}
    15.被 static 修饰的变量叫静态变量或类变量,被 static 修饰的成员变量和成员方法独立于该类的任何对象,也就是说,
       它不依赖类特定的实例,被类的所有实例共享,只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内找到它们,
       因此, static 对象可以在它的任何对象创建之前访问,无需引用任何对象,用 public 修饰的 static 成员变量和成员方法本质是全局变量和全局方法,
       当声明它类的对象的时候,不生成 static 变量的副本,而是类的所有实例共享同一个 static 变量。
    16. 在类中,被 static 修饰的方法叫静态方法,也叫类方法。类方法可以被类名直接调用,也可以被实例调用,在静态方法中,
       只能调用静态方法,不可以直接调用非静态方法。
    17.使用 static 修饰的成员称为静态成员或类成员,可以使用类名直接访问,而未使用 static 修饰的成员为实例成员,只能使用类的对象访问。
    18.在静态方法中,类的静态成员变量可以直接使用,而类的实例变量不能直接使用,必须先创建对象,再使用对象访问。
    19.实例方法可以直接调用本类的方法,不能直接调用父类的实例方法和类方法,也不能调用其他类的实例方法。
    20.成员变量可以和成员方法中的局部变量同名,在成员变量前加 this ,使用 this 访问该成员变量。
    21.一个成员方法中的局部变量不能在另一个成员方法中直接访问。
    22.全局静态变量在函数调用过程中更改,离开函数后更改任然有效。
    23.构造方法名必须和类名一致,并且没有返回值,并不是 void ,构造方法是在创建对象时调用,
       对其进行初始化工作,构造方法可以在一个类中出现多次,即 重载。
    24.如果类中显示定义了一个或多个构造方法,并且所有的构造方法都带参数,那么这个类就失去了默认的空构造方法。
    25.实现封装需要通过 private ,在开发中,往往将属性私有化,这些使用 private 修饰的属性或方法,
       只能在本类访问,其他类中不可直接调用,而且构造方法也可以封装。
    26.在类中,私有方法(private)是不可以被其他类直接访问的,访问范围仅限本类。
    27.Java封装的三个步骤:设置 private 属性,生成 get、set 方法对属性进行读写。
    28.封装可增强数据的访问限制,降低各模块之间的依赖程度,也可以提高代码的复用程度,
       增强程序的可维护性,与提高性能无关。
    29.进行程序设计时,应尽量避免一个模块直接操作和访问另一个模块的数据,模块设计追求 高内聚、低耦合。
       高内聚:尽可能把模块的内部数据、功能实现细节隐藏在模块内部独立完成,不允许外部直接干预。
       低耦合:仅暴露少量的方法给外部使用。
    30. String 类型的对象是不能被改变的。
    31. return 语句之后不能再存在其他语句,否则会引起编译错误。
    32.常量使用 final 关键字修饰,其值不能被修改,如果修改了,编译器将不能通过。
    33. abstract 修饰的类是抽象类,抽象类无法实例化,但是可以被继承,自身的方法是可以重载的。
    34.多重继承中,初始化顺序为:父类属性-->父类构造方法-->子类属性-->子类构造方法。
    35.抽象类实现接口时,可以不重写接口内的方法。
    36.接口用于描述系统对外提供的所有服务,因此接口中的成员常量和方法都必须是公开(public)类型的,
       确保外部使用者能访问它们;接口仅仅描述系统能做什么,但不知如何去做,所以接口中的方法都是抽象(abstract)方法;
       接口不涉及任何与实例相关的细节,因此接口没有构造方法,不能实例化,没有实例变量,只有静态(static)常量(final)。
    37.Java可以通过实现接口,间接实现多重继承。
    38.接口不能被实例化,可以有多个实现类,实现类实现接口必须实现接口方法,接口可以被接口继承。
    39.Java中,面向接口编程的好处有:更加抽象,更加面向对象,提高编程的灵活性,提高可维护性,降低耦合。
    40.在Java中,父类对象转换为子类类型是不安全的,子类对象转换为父类类型是安全的。
    41.在Java中,如果被重载和重写的方法相同,那么重载的方法和重写的方法不可以放在相同的类中。
    42.在Java中,如果被重载和重写的方法不同,那么重载的方法和重写的方法可以放在相同的类中。
    43.在Java中,如果被重载和重写的方法不同,那么重载的方法和重写的方法可以放在不同的类中。
    44.创建包的语句是 package ,该语句必须放在程序的第一行。
    45.Java中方法绑定分为: 编译时刻绑定、运行时刻绑定。
    46.在编译时刻绑定的方法有: 静态方法、 private 修饰的方法、 final 修饰的方法
    -------------------------------------------------------------------------------------------------------------------------------------------------
    API(application program interface): 应用程序编程接口


    java.lang.*;


    八大基本类型对象八大基本包装类: byte   short   int   long   float   double   char    boolean
    Byte   Short  Integer Long   Float   Double Character Boolean
    Integer 与 int的区别:
    int是java提供的8种原始数据类型之一。Java为每个原始类型提供了封装类,Integer是java为int提供的封装类。
    int的默认值为0,而Integer的默认值为null,即Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况.
    int不适合作为web层的表单数据的类型

    ==号与equals的区别: 
    == 比较八大基本类型是比较值是否相等,比较非八大基本类型的地址是否相等 ,
    equals 是比较非八大基本类型的地址是否相等,但是equals可以通过重写从而满足比较非八大基本类型的值是否相等的要求
    重写equals() 方法 以满足判断非八大基本类型值是否相等的要求
    重写toString() 方法 利用三目运算符 返回需要得到的信息
    ==号与equals方法的区别:
    ==操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,
    要比较两个基本类型的数据或两个引用变量是否相等,只能用==操作符。
    equals方法是用于比较两个独立对象的内容是否相同。它比较的是两个对象是独立的。


    常量池: 常量池在编译期遇见String 字符串时,它会检查该池内是否已经存在相同的String 字符串,如果找到,
    就把新变量的引用指向现有的字符串对象,不创建任何新的String 常量对象,没找到再创建新的。
    所以对一个字符串对象的任何修改,都会产生一个新的字符串对象,原来的依然存在,等待垃圾回收。


    变长参数: ...  在最后一个形参的类型后增加三点(...),表明该形参可以接受多个参数值。
    个数可变的形参只能处于形参列表的最后,一个方法中最多只能包含一个个数可变的形参。
    个数可变的形参本质就是一个数组类型的形参,因此调用包含个数可变形参的方法时,
    该个数可变的形参既可以传入多个参数,也可以传入一个数组。
    当不明确参数个数的时候采用变长参数。


    克隆: 三原则: ①必须 implements Cloneable 
    ②必须重写
    ③调用的时候要捕获异常
    浅克隆:对象内部是八大基本类型和String ,原对象和克隆出的对象是两个不同的对象,改变原对象数据,并不会改变克隆后对象的值。
    深克隆:对象内部是自定义类型,改变的是地址,改变原对象数据,会影响到克隆后的数据的值。


    写clone()方法时,通常都有一行代码,是什么?
    clone()有缺省行为,代码是: super.clone();因为首先要把父类中的成员复制到位,然后才是复制本身的成员。


    String 和 StringBuffer 的区别: 
    String 类提供了数值不可改变的字符串,而StringBuffer 类提供的字符串可以进行修改。
    String 类覆盖了equals方法和hashCode方法,而 StringBuffer 没有覆盖equals方法和hashCode方法,
    所以,将 StringBuffer 对象存储进Java集合类中时会出现问题


    --------------------------------- 异常处理: Exception --------------------------------
    异常: 运行期 出现的错误。程序中出现不正常的情况。
    错误是指在程序运行的过程中,发生的一些异常事件(如: 除0溢出,数组下标越界,所要读取的文件不存在等);
    抛出(throw)异常:Java程序的执行过程中如出现异常事件,可以生成一个异常类对象,该异常对象封装了异常事件的信息并提交给Java运行时的系统。
    捕获(catch)异常:当Java运行时系统接收到异常对象时,会寻找能处理这一异常的代码,并把当前异常对象交给其处理。
    Throwable : 可被抛出的  Java语言中所有错误或异常的超类。
    Error: 严重问题:Error 我们不处理。这种问题一般都是很严重的,由java虚拟机生成并抛出,比如说内存溢出、动态链接失败、虚拟机错误等。
    Exception: 编译期异常(检查性异常): 必须进行处理的,因为你不处理,编译就不能通过
    RuntimeException: 运行期异常(非检查性异常):RuntimeException 这种问题我们可以不处理,因为是你的问题,而且这个问题出现肯定是我们的代码不够严谨,需要修正代码的。


    异常的分类:
    Error: 称为错误-由java虚拟机生成并抛出,比如说内存溢出、动态链接失败、虚拟机错误等。程序对其不做处理
    Exception: 所有异常类的父类,其子类对应了各种各样可能出现的异常事件,一般需要用户显示的声明或捕获。
    RuntimeException: 一类特殊的异常,如被0除、数组下标越界等,其产生比较频繁,处理麻烦,如果显式的声明或捕获将会对其程序可读性和运行效率影响很大。
    因此由系统自动检测并将它们交给缺省的异常处理程序(用户可不必对其处理)


    编译时异常和运行时异常的区别:
     * 编译期异常:Java程序必须显示处理,否则程序就会发生错误,无法通过编译
     * 运行期异常:无需显示处理,也可以和编译时异常一样处理


    常用异常:
    ArithmeticException 算术异常
    ArrayIndexOutOfBoundsException 下标越界
    ArrayStoreException 数组存储异常
    ClassCastException 类转换异常
    ClassNotFoundException 找不到类异常
    IllegalThreadStateException 非法线程异常
    InterruptedException 中断异常
    NoSuchFieldException 没有字段异常
    NoSuchMethodException 没有这个方法异常
    CloneNotSupportedException 不支持克隆
    NullPointerException 空对象异常
    NumberFormatException 数字格式化异常
    RuntimeException 运行时异常
    UnsupportedOperationException 不支持当前操作异常


    异常中要常用的几个方法:
     public String getMessage():异常的消息字符串
     public String toString():返回异常的简单信息描述
       此对象的类的 name(全路径名)
       ": "(冒号和一个空格) 
       调用此对象 getLocalizedMessage()方法的结果 (默认返回的是getMessage()的内容)
     printStackTrace() 获取异常类名和异常信息,以及异常出现在程序中的位置。返回值 void 。把信息输出在控制台


    处理异常的方式: 
    try catch finally 三都不能独立存在, catch 和 finally 也不能组合使用,只能try 与 catch 或 try 与 finally 组合使用
    A:try...catch...finally
    B:try...catch
    C:try...catch...catch...
    D:try...catch...catch...finally
    E:try...finally


    如果 catch 里面有 return 语句,请问 finally 里面的代码还会执行吗?如果会,请问是在 return 前,还是 return 后。
    答: 会。前。准确的说,应该是在中间。


    final,finally 和finalize的区别
     final :最终的意思,可以修饰类,成员变量,成员方法 修饰类,类不能被继承 修饰变量,变量是常量 修饰方法,方法不能被重写
     finally :是异常处理的一部分,用于释放资源。一般来说,代码肯定会执行,特殊情况:在执行到finally之前jvm退出了
     finalize :是 Object 类的一个方法,用于垃圾回收


    异常处理第二种方式: 
    格式: throws 异常类名
    注意:这个格式必须跟在方法的括号后面。
    throw:如果出现了异常情况,我们可以把该异常抛出,这个时候的抛出的应该是异常的对象


    注意:
    尽量不要在main 方法上抛出异常。


    throws 和 throw 的区别(面试题)
    throws
    用在方法声明后面,跟的是异常类名
    可以跟多个异常类名,用逗号隔开
    表示抛出异常,由该方法的调用者来处理
    throws 表示出现异常的一种可能性,并不一定会发生这些异常
    throw
    用在方法体内,跟的是异常对象名
    只能抛出一个异常对象名
    表示抛出异常,由方法体内的语句处理
    throw 则是抛出了异常,执行 throw 则一定抛出了某种异常
    throw 语句可以单独使用, throw 语句抛出的不是异常类,而是一个异常实例,而且每次只能抛出一个异常实例。


    自定义异常类 自定义异常类名以 Exception 结尾
    两种方式: 
    A:继承 Exception-------编译期异常类
    B:继承 RuntimeException-----运行期异常类


    ------------------------------------ 线程 Thread ------------------------------------
    进程: 就是正在运行的程序。进程是系统进行资源分配和调用的独立单位。
    每一个进程都有它自己的内存空间和系统资源。
    同一时间CPU只能执行一个进程,线程上下文切换比进程上下文切换要快得多。
    线程是依赖于进程而存在的,一个进程中至少有一个线程。
    线程是程序的执行单元,执行路径,是程序使用CPU的最基本单位。
    单线程: 如果程序只有一条执行路径。
    多线程: 如果程序有多条执行路径。
    多线程的意义: 不是提高程序的执行速度,而是为了提高应用程序的使用率。


    并发(Concurrent): 一个处理器同时处理多个任务。  逻辑上的同时发生
    并发(Parallel): 多个处理器或是多核的处理器同时处理多个不同的任务。   物理上的同时发生。
    Java程序的运行原理: 
    由java命令启动JVM,JVM启动就相当于启动了一个进程。
    接着由该进程创建了一个主线程去调用main方法。
    JVM虚拟机的启动是单线程还是多线程的: 
    JVM虚拟机的启动时多线程的,原因是垃圾回收线程也要先启动,否则会很容易出现内存溢出。
    垃圾回收线程加上主线程,最低启动了两个线程,故,JVM的启动是多线程的。
    线程的生命周期: 
    新建: 创建一个线程对象
    就绪: 调用start()方法后,线程有执行资格,但没有获取到执行权(也就是没有获取到CPU内存资源)
    运行: 获取到执行权(获取到CPU内存资源)
    阻塞: 没有执行资格也没有执行权,一般是调用方法 suspend() sleep() wait() join() 方法后线程进入阻塞状态
    死亡: run()方法结束,或线程被中断(调用方法stop()或destroy())


    如何实现多线程:
    1.继承 Thread 类。
    A: 自定义类继承 Thread 类。
    B: 自定义类中重写run()方法。
    C: 创建自定义类对象
    D: 启动线程 使用start()方法
    2.实现 Runnable 接口。
    A: 自定义类实现 Runnable 接口。
    B: 自定义类中重写run()方法。
    C: 创建自定义类对象
    D: 创建 Thread 类对象,并把自定义类对象作为构造参数传递。


    为什么要将 Runnable 接口的子类对象传递给 Thread 类的构造函数:
    因为自定义的run()方法所属的对象是 Runnable 接口的子类对象,
    所以要让线程去执行指定对象的run()方法就必须明确该run()方法所属对象。


    两种实现多线程的方法的区别: 
    实现 Runnable 接口可以避免Java中单一继承的局限性;
    适合多个相同程序的代码去处理同一个资源的情况,把线程同程序代码数据有效的分离。
    增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。
    继承 Thread : 线程代码存放在 Thread 子类run()方法中
    实现 Runnable : 线程代码存放在 Runnable 接口的子类的run()方法中。
    Thread 类中的run()方法,是用于存储线程要运行的代码。
    重写run()方法的目的是: 将自定义的代码存储在run()方法中,让线程运行。
    一个线程只能调用一次start()方法,如果调用多次会出现: IllegalThreadStateException : 非法的线程状态异常


    run()和start()的区别: 
    run() : 仅仅是封装被线程执行的代码,直接调用时普通方法
    start() : 首先启动了线程,然后再由JVM去调用该线程的run()方法




    多线程安全问题的原因(判断一个程序是否有线程安全问题的依据)
    A : 是否有多线程环境
    B : 是否有共享数据
    C : 是否有多条语句操作共享数据


    线程同步: 
    ①线程同步就是线程排队 
    ②只有共享资源的读写访问才需要同步
    ③只有变量才需要同步访问
    ④多个线程访问共享资源的代码有可能是同一份代码,也有可能是不同的代码。
    解决线程安全问题: 
    A : 同步代码块:
    synchronized(对象){ 需要被同步的代码; }
    这里锁的对象是任意对象
    B : 同步方法
    把同步加在方法上。
    这里的锁对象是 this
    C : 静态同步方法
    把同步加在静态方法上
    这里的锁对象是 当前类的字节码文件对象 文件名.class
    同一对象共享数据不需要加 static ,多个不同对象共享数据要加 static


    多线程有几种实现方案,分别是哪几种?
    两种  继承 Thread 类,实现 Runnable 接口
    扩展一种: 实现 Callable 接口,和线程池结合。重写call()方法
    同步有几种方式?分别是什么?
    同步代码块,同步方法,同步静态方法
    sleep()和wait()方法的区别:
    sleep() : 必须值时间;不释放锁;
    wait() : 可以不指定时间,也可以指定时间;释放锁;
    为什么wait(),notify(),notifyAll()等方法都定义在 Object 类中?
    因为这些方法都调用是依赖于锁对象的,而同步代码块的锁对象是任意锁。
    而 Object 代表任意的对象,所以,定义在这里面。


    当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?
    分几种情况:
         1.其他方法前是否加了synchronized关键字,如果没加,则能。
         2.如果这个方法内部调用了wait,则可以进入其他synchronized方法。
         3.如果其他个方法都加了synchronized关键字,并且内部没有调用wait,则不能。
         4.如果其他方法是static,它用的同步锁是当前类的字节码,与非静态的方法不能同步,因为非静态的方法用的是this。


    简述synchronized和java.util.concurrent.locks.Lock的异同?
    主要相同点:Lock能完成synchronized所实现的所有功能
    主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。
    synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放。


    守护线程:也叫精灵线程、后台线程
    特点:
    A : 不具备生命周期,它随着虚拟机的结束而结束
    B : 如果想把线程转换成精灵线程,必须在start()之前调用 setDaemon(boolean)方法
    一旦线程变为精灵线程就不能变为用户线程了。


    守护线程和用户线程的区别: 
    守护线程是无生命周期的,伴随着用户线程存在,如果用户线程执行完毕,守护线程还没有执行完毕,
    那么守护线程也将结束,守护线程在线程启动前调用,setDaemon(true)


    线程池: 根据自身的环境情况,有效的限制执行线程的数量,使得运行效果达到最佳。
    线程池的作用: 
    减少创建和销毁线程的次数,每个工作线程可以多次使用
    可根据系统情况调整执行的线程数量,防止消耗过多内存。
    使用:
    ExecutorService pool = Executors.常见线程池;
    常见线程池:
    ①newSingleThreadExecutor : 创建一个单线程的线程池
    ②newFixedThreadExecutor(n) : 创建固定大小的线程池
    ③newCacheThreadExecutor(推荐使用) : 创建一个可缓存的线程池
    ④newScheduleThreadExecutor : 大小无限制的线程池,支持定时和周期性的执行线程


    1.线程同步的目的是为了保护多个线程访问一个资源时对资源的破坏。
    2.线程同步方法是通过锁来实现的,每个对象都有且仅有一个锁,这个锁与一个特定的对象关联,线程一旦获取了对象锁,
    其他访问该对象的线程就无法再访问该对象的其他同步方法。
    3.对于静态同步方法,锁是针对这个类的,锁对象是该类的Class对象。文件名.class 
    静态和非静态方法的锁互不干预。
    一个线程获得锁,当在一个同步方法中访问另外对象上的同步方法时,会获取这两个对象锁。
    4.对于同步,要时刻清醒在哪个对象上同步,这是关键。
    5.编写线程安全的类,需要时刻注意对多个线程竞争访问资源的逻辑和安全作出正确的判断,
    对"原子"操作作出分析,并保证原子操作期间别的线程无法访问竞争资源。
    6.当多个线程等待一个对象锁时,没有获取到锁的线程将发生阻塞。
    7.死锁是线程间相互等待锁造成的,在实际中发生的概率非常的小。


    线程组(ThreadGroup): 是指java.lang.ThreadGroup 类的对象


    线程组与线程池的区别: 
    ①线程组存在的意义,首要原因是 安全。
    java默认创建的线程都是属于系统线程组,而同一个线程组的数据是可以相互修改对方的数据的。
    线程组除安全外,最有用的一个地方就是 控制,只需用单个命令即可完成对整个线程组的操作。
    ②线程池存在的意义,首要作用是 效率。
    线程的创建和结束都需要耗费一定的系统时间,不停创建和删除线程会浪费大量的时间,
    所以,在创建出一条线程并使其在执行完任务后不结束,而是使其进入休眠状态,在需要用时再唤醒,
    那么 就可以节省一定的时间
    线程组和线程池共有的特点: 
    1. 都是管理一定数量的线程
    2. 都可以对线程进行控制---包括休眠,唤醒,结束,创建,中断(暂停)--但并不一定包含全部这些操作。


    ------------------------------------java.util.*------------------------------------
    数组和集合的区别: 
    A : 长度区别 数组的长度是固定的,集合长度是可变的
    B : 存储内容不同 数组存储的是同一种类型的元素,而集合可以存储不同类型的元素
    C : 元素的数据类型问题 数组可以存储基本数据类型,也可以存储引用类型,而集合只能存储引用类型。


    public interface Collection<E> extends Iterable<E>
    Collection 接口用于表示任何对象或元素组 这是一个超级接口 迭代器是 iterator() 实用add()进行存储
    <> 代表泛型,里面只能放类名,里面放的是什么类型,那么这个容器就只能存储对应类型的数据。
    集合必须只有对象,集合中的元素不能是基本数据类型
    功能: 
    1.添加功能: boolean add(Object obj) : 添加一个元素
    boolean addAll(Collection c) : 添加一个集合的元素
    2.删除功能: void clear() : 移除所有元素
    boolean remove(Object obj) : 移除一个元素
    boolean removeAll(Collection c) : 移除一个集合的元素
    3.判断功能: boolean contains(Object obj) : 判断集合中是否包含指定元素
    boolean containsAll(Collection c): 判断集合中是否包含指定的集合中所有元素
    boolean isEmpty() : 判断集合是否为空
    4.获取功能: Iterator<E> iterator() : 返回在 Collection 的元素上进行迭代的迭代器
    5.长度功能: int size() : 得到集合中元素个数
    6.交集功能: boolean retainAll(Collection c) : 两个集合都有的元素
    7.把集合转换为数组: Object[] toArray() : 将集合转换成 Object[] 数组


    public abstract class AbstractCollection<E> extends Object implements Collection<E>
    AbstractCollection 继承于 Collection 为其减少工作负担而存在的一个抽象类。


    迭代器(Iterator)本身是一个对象,而且是轻量级的,它的工作就是:
         遍历并选择集合序列中的元素,而客户端没有必要知道底层的实现。
    一个标准的、统一的来遍历一个Collection的方式,它是一个迭代器
    hasNext() 是否有下一个元素
    next()必须重复调用这个方法直到hasNext()返回false
    remove();方法删除由next方法返回的最后一个元素,每次调用next()方法后,只能调用一次该方法


    public interface List<E>extends Collection<E>
    List 集合代表一个有序的集合,集合中的每一个元素都有其对应的顺序索引。List集合允许使用重复的元素,可以通过索引访问指定位置的集合元素
    简述 实现 操作特性 成员要求
    ArrayList 提供快速的基于索引的成员访问,对尾部成员的增加和删除支持较好
    List 提供基于索引的对成员的随机访问 成员可为任意 Object 子类的对象
    LinkedList 对列表中任何位置的成员的增加和删除支持较好,但对基于索引的成员访问支持性能较差
    List集合的特点: 有序(存储和取出的元素一致),可重复的。增加了下标了操作
    List集合的特有功能:
     A:添加功能:
    void add(int index,Object element):在指定位置添加元素
     B:获取功能:
    Object get(int index):获取指定位置的元素
     C:列表迭代器:
    ListIterator listIterator():List集合特有的迭代器
     D:删除功能:
    Object remove(int index):根据索引删除元素,返回被删除的元素
     E:修改功能:
    Object set(int index,Object element):根据索引修改元素,返回被修饰的元素


    public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>
    AbstractList 使用链表进行存储的一个抽象类,能最大的程度减少随机访问的数据,也有数组存储,允许多个null,可以重复,因为每个值都有单独的存储空间


    列表迭代器:
    ListIterator listIterator():List集合特有的迭代器
    该迭代器继承了Iterator迭代器,所以,就可以直接使用hasNext()和next()方法。  
    特有功能:
    Object  previous():获取上一个元素
    Boolean  hasPrevious():判断是否有前一元素 * 
    注意:ListIterator可以实现逆向遍历,但是必须先正向遍历,才能逆向遍历,所以一般无意义,不使用
    ArrayList,Vector集合应该使用随机访问方法(get)来遍历集合元素,这样性能最好,对于 LinkedList 集合,则应该采用迭代器来遍历集合元素
    如果要经常执行插入删除操作来改变包含大量数据的 List 集合的大小,可考虑使用 LinkedList


    public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable
    Vector 是同步的,实用 Enumeration elements() 的迭代器, 这是以数组的形式存储的。 
    Vector 的特有功能:
    1:添加功能
    public  void  addElement(Object obj) add()
    2:获取功能
    public  Object  elementAt(int index)  get()
    public  Enumeration  elements() Iterator iterator()
    boolean  hasMoreElements() hasNext()
    Object  nextElement() next()


    public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable
    ArrayList 
    这是一个异步的,它实现了 List 接口,是一个实用类,用数组进行储存的,此类大致上等同于 Vector 类,除了此类是不同步的


    ArrayList 与 Vector 区别: 
    ① Vector 是同步的, ArrayList 是异步的
    ② Vector 速度慢, ArrayList 速度快
    这两个类都实现了List接口(List接口继承了Collection接口),他们都是有序集合,即存储在这两个集合中的元素的位置都是有顺序的,相当于一种动态的数组.

    同步性:
    Vector是线程安全的,也就是说是它的方法之间是线程同步的,而ArrayList是线程序不安全的,它的方法之间是线程不同步的
    如果只有一个线程会访问到集合,那最好是使用ArrayList,因为它不考虑线程安全,效率会高些;如果有多个线程会访问到集合,那最好是使用Vector,因为不需要我们自己再去考虑和编写线程安全的代码。
    数据增长: 
     ArrayList与Vector都有一个初始的容量大小,当存储进它们里面的元素的个数超过了容量时,就需要增加ArrayList与Vector的存储空间
     Vector默认增长为原来两倍,而ArrayList的增长策略在文档中没有明确规定(从源代码看到的是增长为原来的1.5倍)。
     Vector增长原来的一倍,ArrayList增加原来的0.5倍。
     
    public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, Serializable
    LinkedList 是用链表进行存储的,实用 ListIterator listIterator(int index)作为迭代器,可以从指定的位置开始循环,
    因为是链表,所以这个方法方便插入和删除,可以快速找到开头和结尾,这是双向链表
    LinkedList 的特有功能:
      A:添加功能
    public void addFirst(Object e)
    public void addLast(Object e)
    B:获取功能
    public Object getFirst()
    public Obejct getLast()
    C:删除功能
    public Object removeFirst()
    public Object removeLast()


    public class Stack<E> extends Vector<E>
    Stack 类表示后进先出(LIFO)的对象堆栈
    这是以栈的形式进行存储,它在 Vector 的基础上进行了扩充,允许将允许将向量视为堆栈。
     E push(E item) 压入栈顶
    List 总结
    1. 数据增长到一定程度的时候, ArrayList 增长原来的一半,而 Vector 增长原来的一倍。 
    2. ArrayList 底层以数组形式存储数据( Vector, Stack 也是以数组存储数据的),且长度可变。 
    3. LinkedList 底层以双向链表的形式存储数据。 
    4. ListIterator 和 Iterator 的区别:前者双向链表,后者是单向链表。 
    5. ArrayList : 允许多个 null ,可以放入不同种类型,也可以放入相同的值。 
    6. ArrayList 里头的remove()、indexOf()都要用equals()方法判断,否则比较的是地址。 
    7. ArrayList 和 Vector 区别: Vector 是同步的,一次一个数据,子类是 Stack ; ArrayList 是异步的,一次可以来多个数据,速度快,安全性不好。
    ArrayList : 底层数据结构是数组,查询和修改快,增加删除慢,线程不安全,效率高。异步的
    Vector : 底层数据结构是数组,查询和修改快,增加删除慢,线程安全,效率低。
    LinkedList : 底层数据结构是链表,查询和修改慢,增加删除快,线程不安全,效率高。


    public interface Queue<E>extends Collection<E>
    Queue 接口并未定义阻塞队列的方法,实现通常不允许插入 null 元素。
    remove() 和 poll() 方法可移除和返回队列的头


    public abstract class AbstractQueue<E> extends AbstractCollection<E> implements Queue<E>
    AbstractQueue 此类提供某些 Queue 操作的骨干实现。此类中的实现适用于基本实现不允许包含 null 元素时。
    它是以队列的形式存储,先进先出,不能有null,可以快速进行判断堆栈是否为满或空,这是一个抽象类


    public interface Set<E> extends Collection<E>
    一个不包含重复元素的 Collection 。更确切地讲, Set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个 null 元素。
    Set 集合的特点: 无序(存储和取出的元素顺序不一致),不允许重复的


    public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E>
    此类提供 Set 接口的骨干实现,从而最大限度地减少了实现此接口所需的工作。


    public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, Serializable
    此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 Set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。
    异步的,可以有 null ,迭代器为 Iterator iterator() ,实现 Set 接口,采用哈希算法存储
    A:底层数据结构是哈希表(是一个元素为链表的数组)
    B:哈希表底层依赖两个方法:hashCode()和equals()
      执行顺序:
    首先比较哈希值是否相同
    哈希值相同:继续执行equals()方法
    返回true:元素重复了,不添加
    返回false:直接把元素添加到集合
    哈希值不同:就直接把元素添加到集合
    C:如何保证元素唯一性的呢?
    由hashCode()和equals()保证的
    D:自定义类如果想要元素的唯一性必须重写hashCode()和equals()方法
    HashSet 中元素无序,允许空,不允许重复
    LinkedHashSet:底层数据结构由哈希表和链表组成。 哈希表保证元素的唯一性。链表保证元素有序。(存储和取出是一致)
    HashSet 集合判断两个元素相等的标准就是两个对象通过equals方法确认相等,并且两个对象的hashCode()方法返回值也相等。
    HashSet之类的集合不可以按索引号去检索其中的元素,也不允许有重复的元素
    重写hashCode的规则:
    【1】当两个对象通过equals方法比较时返回true时,这两个对象的hashCode应该相等。 
    【2】对象中用作equals比较标准的属性,都应该用来计算hashCode值。 




    public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E> , Cloneable, Serializable
    TreeSet 异步的,可以进行排序;这是二叉树,以链表形式进行存储,实现 SortedSet 接口,默认是升序。
    A:底层数据结构是红黑树(是一个自平衡的二叉树),是TreeMap的键
    B:保证元素的排序方式
    a:自然排序(元素具备比较性)
    让元素所属的类实现 Comparable 接口 ,重写compareTo()方法
    b:比较器排序(集合具备比较性)
    让集合构造方法接收 Comparator 的实现类对象
    提供比较器,重写compare()方法和equals()(equals方法可以使用Object中默认继承的)方法
    TreeSet 中元素不允许空,不允许重复,必须是同一种类型的数据,可以实现元素排序
    TreeSet 是 SortedSet 接口的实现类, TreeSet 可以确保集合元素处于排序状态。
    hash(哈希、散列)算法的功能是,它能保证快速查找被检索的对象,hash的价值在于速度。
    重写hashCode() 方法的基本规则: 
    ①在程序运行过程中,同一个对象多次调用hashCode()方法应返回相同的值。
    ②当两个对象通过equals()方法比较返回true时,这两个对象的hashCode()方法应返回相等的值。
    ③对象中用作equals()方法比较标准的实例变量,都应该用于计算hashCode()值。
    LinkedHashSet 也是根据元素的hashCode值来决定元素的存储位置,但同时使用链表维护元素的次序,当遍历 LinkedHashSet 集合里的元素时,
    LinkedHashSet 将会按元素的添加顺序来访问集合里的元素。


    HashSet 的性能总是比 TreeSet 好(特别是最常用的添加查询元素等操作),因为 TreeSet 需要额外的红黑树算来维护集合元素的次序。
    只有当需要一个保持排序的 Set 时,才应该使用 TreeSet ,否则都应该使用 HashSet;
    对普通的插入、删除操作, LinkedHashSet 比 HashSet 要略微慢一点,这是由维护链表所带来的额外开销造成的,但由于有了链表,遍历 LinkedHashSet 会更快。


    public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> implements Cloneable, Serializable
    EnumSet : 是一个专为枚举类设计的集合类, EnumSet 中的所有元素都必须指定枚举类型的枚举值,该枚举类型再创建 EnumSet 时显式或隐式地指定。
    EnumSet 的集合元素也是有序的, EnumSet 以枚举值在 Enum 类内的定义顺序来决定集合元素的顺序。
    EnumSet 集合不允许加入 null 元素,如果试图插入 null 元素, EnumSet 将抛出 NullPointerException 异常
    EnumSet 是所有 Set 实现类中性能最好的,但它只能保存同一个枚举类的枚举值作为集合元素。
    Set 的三个实现类 HashSet 、 TreeSet 和 EnumSet 都是线程不安全的。
    如果有多个线程同时访问同一个 Set 集合,并且超过了一个线程修改了该 Set 集合,则必须手动保证该 Set 集合的同步性,
    通常可以通过 Collections 工具类的 synchronizedSortedSet() 方法来"包装"该 Set 集合;


    Collection 总结 :
    1. List :
    集合代表一个有序集合,集合中每个元素都有其对应的索引,所以List集合允许使用重复元素通过索引来访问指定位置的集合元素。 
    List默认按元素的插入顺序设置元素的索引。 
    List可以根据索引插入、替换、删除集合元素 
    List最大特点是:能够自动根据插入数量动态改变容器大小。
    2.ArrayList 和 Vector:
    它们都是基于数组实现的类,所以它们封装了一个动态分配的 Object[] 
    区别: 
    ArrayList :对线程不安全,当多线程访问同一数据时,必须手动集合的同步性[synchronized] 
    Vector :对多线程访问安全,它本身就是同步的,所以效率要比 ArrayList 低 
    3.LinkedList:
    基于链表实现的 List 类,对顺序访问集合中的元素进行优化,特别是插入和删除的速度特别块 
    4.Set 集合:
    Set 集合和 Collection 基本上完全一样,它没有提供任何额外的方法,实际上 Set 就是 Collection ,只是行为不同, Set 不允许包括重复元素,集合里多个元素之间无明显顺序。 
    Set 集合判断两个对象相同,不是"=="而是"equals" 
    5.HashSet :
    按Hash算法来存储集合中的元素, HashSet 会调用该对象的hashCode方法来得到该对象的hashCode值,然后该hashCode值来决定该对象在hashCode中的存储位置。 
    它不能保证元素的排列顺序,顺序有可能发生变化。 
    它不是同步的,如果多个线程同时访问一个该集合时,必须通过代码来保证其同步 
    它的元素值可以是 null 。
    6.LinkedHashSet:
    此类也是根据元素的hashCode值来决定元素位置,但它同时使用链表维护的顺序元素看起来插入的顺序保存的,它需要维护元素的插入顺序,因此略低于 HashSet 的性能,但迭代访问 Set 里的全部元素时将有很多的性能,因此以链表来维护内部顺序
    7.TreeSet :
    SortedSet 接口的唯一实现,可以确保集合元素处于排序状态,也就是元素是有序的,并不是根据元素插入顺序,而是根据元素实际值而进行排序的。 
    它的两种排序:一:定制排序 二:自然排序 
    如果没有比较器最多只能插入一个元素,如果插入第二个元素,会抛一个[ClassCastException] 
    8.如何选择数据结构:
    1>Array :读快-写慢
    2>Linked:改快-读慢
    3>Hash :间于两者之间
    数组:便于查询和修改 不便于删除和插入(有下标很快的找到和修改,插入删除还要移位)
    链表:便于删除和插入 不便于查询和修改(无下标 查找修改必从链头开始,删除和插入直接连接即可)


    线性结构 有序集合 List 元素可以重复,可以有多个 null
    LinkedList 使用链表作为底层,方便插入和删除
    ArrayList 使用数组作为底层,方便查询和修改 异步
    Vector 使用数组作为底层, 同步
    映像 无序集合 Set 元素不可以重复,仅可以有一个 null
    HashSet 使用哈希表作为底层,可以有 null
    TreeSet 使用链表作为底层,二叉树


    如果访问 List 集合中的元素,可以直接根据元素的索引来访问。
    如果访问 Map 集合中的元素,可以根据每项元素的Key来访问其value。
    如果访问 Set 集合中的元素,则只能根据元素本身来访问(这也是 Set 集合中元素不允许重复的原则)


    Map 集合 : 用于保存具有映射关系的数据 key --- value 
    Map 的key不允许重复,即同一个 Map 对象的任何两个key通过equals()方法比较总是返回false。
    key 和 value 之间存在单向一对一关系,即通过指定的key,总能找到唯一的确定的value。
    Map 集合的特点 :
    将键映射到值的对象,一个映射不能包含重复的键,每个键最多只能映射到一个值。
    Map 集合和 Collection 集合的区别 : 
    Map 集合存储元素是成对出现的, Map 集合的键是唯一的,值是可以重复的。
    Collection 集合存储元素是单独出现的, Collection 的子类 Set 是唯一的, List 是可重复的。
    Map 集合的功能 : 
    1:添加功能
    V put(K key,V value):添加元素。
    如果键是第一次存储,就直接存储元素,返回null
    如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值
    2:删除功能
    void clear():移除所有的键值对元素
    V remove(Object key):根据键删除键值对元素,并把值返回
    3:判断功能
    boolean containsKey(Object key):判断集合是否包含指定的键
    boolean containsValue(Object value):判断集合是否包含指定的值
    boolean isEmpty():判断集合是否为空
    4:获取功能
    Set<Map.Entry<K,V>> entrySet();
    V get(Object key):根据键获取值
    Set<K> keySet():获取集合中所有键的集合
    Collection<V> values():获取集合中所有值的集合
    5:长度功能
    int size():返回集合中的键值对的对数
    Map 集合的键是唯一的,值是可重复的。
    HashMap 集合的键是唯一的,值是可重复的,键允许空,值也允许空,键只允许一个null,值可以允许多个空
    Hashtable 键不允许空,值也不允许空。
    TreeMap 键不允许空,值允许空,值可以允许多个空。
    HashMap 与 Hashtable 的区别 : 
    HashMap 键可以为空,值也可以为空,并且值可以有多个空, HashMap 是线程异步的。
    Hashtable 键和值都不允许为空, Hashtable 是线程同步的。
    Hashtable 是 Dictionary<k,v> 接口的子类。
    HashMap 和 Hashtable 的特点: 
    a:HashMap和Hashtable不能排序,键不能重复,值可以重复 


    b:HashMap键仅允许一个null,值可以是多个null; Map集合全是Map.Entry类型。(也可以说Map集合为Set集合);HashTable不允许使用null作为key或Value 


    c:为了成功的在HashMap和Hashtable上获取对象,用作key的对象必须实现hashCode方法和equals方法。 


    d:和HashSet一样,HashMap和Hashtable也不能保证其中的key-value对的顺序。 


    e:使用HashMap和Hashtable判断两个key相等的标准也是:两个key通过equals相等,那两个key的hashCode值也相等。 


    f:HashMap和Hashtable判断集合中两个值相等,只要equals相等即可。例如:containsValue方法。


    g:如果HashMap和Hashtable使用可变对象作为key,并且程序修改了作为key的可变对象,也可能引发和HashSet类似的情形:程序在也无法访问到被修改过的key
    Hashtable 是一个线程安全的 Map 实现,但 HashMap 是线程不安全的实现,所以 HashMap 比 Hashtable 的性能高一点,但如果有多个线程访问同一个 Map 对象时,使用 Hashtable 实现类会更好。
    Hashtable 不允许使用 null 作为key 和value ,如果试图把 null 值放进 Hashtable 中,将会引发 NullPointerException 异常,但 HashMap 可以使用 null 作为key或value


    HashMap和Hashtable的区别:
    HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key),由于非线程安全,在只有一个线程访问的情况下,效率要高于Hashtable。
    HashMap允许将null作为一个entry的key或者value,而Hashtable不允许。
    最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap就必须为之提供外同步
    三方面:
    一.历史原因:Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现
    二.同步性:Hashtable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步的
    三.值:只有HashMap可以让你将空值作为一个表的条目的key或value


    List 和 Map 区别:
    一个是存储单列数据的集合,另一个是存储键和值这样的双列数据的集合,List中存储的数据是有顺序,并且允许重复;Map中存储的数据是没有顺序的,其键是不能重复的,它的值是可以有重复的。


    Collection和 Collections的区别:
    Collection是集合类的上级接口,继承与他的接口主要有Set和List.
    Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。


    heap和stack有什么区别:
    Java的内存分为两类,一类是栈内存,一类是堆内存。
    栈内存是指程序进入一个方法时,会为这个方法单独分配一块私属存储空间,用于存储这个方法内部的局部变量,当这个方法结束时,分配给这个方法的栈会释放,这个栈中的变量也将随之释放
    堆是与栈作用不同的内存,一般用于存放不放在当前方法栈中的那些数据
    方法中的局部变量使用final修饰后,放在堆中,而不是栈中。


    Date 時間,瞬間
    public class Date extends Object implements Serializable, Cloneable, Comparable<Date>
    Date在java.util包下
    SimpleDateFormat在java.text包下
    Date-->String
    Date date = new Date();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    String str = sdf.format(date);
    System.out.println(str);
    Date-->Long
    Date date = new Date();
    System.out.println(date.getTime());
    String -->Date
    SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    Date d = sdf1.parse("2013-01-01 10:09:03");
    System.out.println(d);
    String -->毫秒
    String-->Date-->Long
    毫秒-->Date
    Date d = new Date();
    long l = date.getTime();
    System.out.println(new Date(l));
    毫秒-->String
    毫秒-->Date-->String


    -------------------------------------java.IO.*------------------------------------
    java.io.*;
    File类是java.io包下代表与平台无关的文件和目录
    File能新建、刪除和重命名文件和目錄,File不能訪問文件本身
    \ 表示 路徑分隔符 /
    絕對路徑: 完整的路徑
    相對路徑: 必須使用其它路徑的信息去解釋
    Stream 数据在两设备间的传输称为流, 流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作
    按照流的方向不同分为:输入流和输出流[针对程序]
    按处理单位不同分为:字节流和字符流
    按功能不同分为:节点流和处理流 
    輸入流與輸出流的區別: 
    输入流:只能从中读取数据,而不能向其写出数据 
    输出流:只能向其写出数据,而不能从中读取数据 
    字节流两个基类: 
    InputStream OutputStream


    字符流两个基类: 
    Reader Writer
    字符流是字節流的包裝,字符流則是直接接受字符串。
    字節流與字符流的區別: 
    ·读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。 
    ·处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。 
    结论:只要是处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流.
    節點流與處理流: 
    节点流:从一个特定的数据源(节点)读写数据(文件,内存),也称为:低级流 
    处理流:连接在已存在的流之上(节点流或处理流),通过此对数据的处理为程序提供更强大的读写功能 
    節點流:
    1. InputStream 是所有的输入字节流的父类,它是一个抽象类。
    2. ByteArrayInputStream、StringBufferInputStream、FileInputStream 是三种基本的介质流,
    它们分别从Byte 数组、StringBuffer、和本地文件中读取数据。
    3. PipedInputStream 是从与其它线程共用的管道中读取数据。
    4. ObjectInputStream 和所有FilterInputStream 的子类都是装饰流(装饰器模式的主角)。
    5. OutputStream 是所有的输出字节流的父类,它是一个抽象类
    6. ByteArrayOutputStream、FileOutputStream 是两种基本的介质流,它们分别向Byte 数组、和本地文件中写入数据。
    7. PipedOutputStream 是向与其它线程共用的管道中写入数据。
    8. ObjectOutputStream 和所有FilterOutputStream 的子类都是装饰流。
    9. Reader 是所有的输入字符流的父类,它是一个抽象类。 
    10.CharReader、StringReader 是两种基本的介质流,它们分别将Char 数组、String中读取数据。
    11.PipedReader 是从与其它线程共用的管道中读取数据。
    12.BufferedReader 很明显就是一个装饰器,它和其子类负责装饰其它 Reader对象。 
    13.FilterReader 是所有自定义具体装饰流的父类,其子类PushbackReader 对Reader 对象进行装饰, 会增加一个行号。 
    14.InputStreamReader 是一个连接字节流和字符流的桥梁,它将字节流转变为字符流。
    15.Writer 是所有的输出字符流的父类,它是一个抽象类。
    16.CharArrayWriter、StringWriter 是两种基本的介质流,它们分别向Char 数组、String 中写入数据。 
    17.PipedWriter 是向与其它线程共用的管道中写入数据。
    18.BufferedWriter 是一个装饰器为Writer 提供缓冲功能。
    19.PrintWriter 和PrintStream 极其类似,功能和使用也非常相似。
    20.OutputStreamWriter 是OutputStream 到Writer 转换的桥梁,它的子类FileWriter 其实就是一个 实现此功能的具体类(具体可以研究一SourceCode)。功能和使用和OutputStream 极其类似。
    處理流:
    緩衝流: BufferedReader,BufferedWriter BufferedInputStream,BufferedOutputStream
    過濾流: FilterReader,FilterWriter FilterInputStream,FilterOutputStream
    合併流: SequenceInputStream
    管道流: PipedReader,PipedWriter PipedInputStream,PipedOutputStream
    數據流: DataInputStream,DataOutputStream
    打印流: PrintStream PrintWriter 
    對象序列化: 正序列化: ObjectOutputStream 反序列化: ObjectInputStream
    需要實現  Serializable 接口,禁止序列化關鍵字: transient
    處理流的好處: 
    1)性能的提高:主要以增加缓冲的方式来提高输入/输出的效率
    2)操作的便捷:处理流可能提供了系列便捷的方法来一次输入/输出大批量的内容,而不是输入/输出一个多个"水滴"。 
    處理流的特點:1)可以嫁接到任何流之上。 
    转换流的特点:
    1.其是字符流和字节流之间的桥梁
    2.可对读取到的字节数据经过指定编码转换成字符
    3.可对读取到的字符数据经过指定编码转换成字节


    何时使用转换流?
    1.当字节和字符之间有转换动作时;
    2.流操作的数据需要编码或解码时。


    具体的对象体现:
    1.InputStreamReader:字节到字符的桥梁
    2.OutputStreamWriter:字符到字节的桥梁
    这两个流对象是字符体系中的成员,它们有转换作用,本身又是字符流,所以在构造的时候需要传入字节流对象进来。


    數據流:
    1.DataInputStream和DataOutputStream 分别继承自于InputStream和OutputStream,它属于处理流。
    分别需要套接到:InputStream和OutputStream类型的节点流上。
    2.DataInputStream和DataOutputStream 提供了可以存取和机器无关的原始Java数据类型(int,...)方法 


    --------------------------------------集合与IO流考试易错分析------------------------------
    1.Map 接口存储一组成对的键-值对象,其中key不要求有序,不允许重复,value不要求有序,但允许重复
    2.Java集合框架中,HashMap 类是基于哈希表的Map接口的实现,此实现提供所有可选的映射操作,并允许使用null值和null键,
    此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
    3.在Java中,List 集合可以存储多个null
    4.以InputStream(输入)/OutputStream(输出) 为后缀的是字节流;以Reader(输入)/Writer(输出) 为后缀的是字符流。
    5.在Java编程中,类对象使用完毕后,建议赋值为null来释放分配的内存,对于BufferedReader类对象来说,还要释放分配的缓冲
    区空间,在类方法中close()方法起这个作用。
    6.Java的list接口有3个实现类,分别是 ArrayList、LinkedList、Vector,它们用于存放多个元素,维护元素的次序,而且
    允许元素重复,ArrayList 是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问,Vector与ArrayList
    一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性,
    但实现同步需要很高的花费,因此,访问它要比访问ArrayList慢。
    7.Java的 HashSet 类是由哈希表支持,它不保证set的迭代顺序,特别是它不保证该顺序恒久不变,此类允许使用null元素,HashSet类
    为基本操作提供了稳定性能。
    8.Java的 HashMap 和 Hashtable 都实现了Map接口,它们及其子类都采用Hash算法决定Map中key的存储。
    9.java.util.Collections 类包含很多有用的方法,使用swap()方法可以在指定列表的指定位置处变换元素。
    10.泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法的创建中,分班称为
    泛型类、泛型接口、泛型方法。如果一个类或接口上有一个或多个类型变量,那它就是泛型。
    11.在Java中,Hashtable和Vector是属于线程安全的。
    12.FileReader 是继承自 InputStreamReader,在  Reader的方法read()中,其返回值为-1的时候,表示当前读取到文件
    流的末尾,此时读取完毕当前流(如果是文件操作,表示读取到了文件末尾);
    13.ArrayList 采用的是数组形式来保存对象的,这种方式将各元素存储在连续的内存空间中,所以优点是遍历和随机访问比较方便,最大的
    缺点是插入删除时非常麻烦,因为都需要循环移位。
    14.LinkedList 采用的是将各元素存放在独立的内存空间中,而且在每个空间中还保存下一个元素的链接索引,因此插入和删除比较方便,
    只需找到插入和删除的位置,重置相应元素的链接索引,但是缺点就是查找非常麻烦,因为其各元素的存储位置不是连续的。
    15.ObjectOutputStream 是用于序列化输出的类,transient用来屏蔽不想序列化的属性。
    16.在Java中,能够用来关闭流的方法是close();
    17.Java的集合框架四个基本接口的区别:
    Collection 接口是一组允许允许重复的对象;Set 接口继承 Collection ,但不允许重复;List 接口继承 Collection,
    有序保存数据,允许出现重复的数据,并引入位置下标;Map 接口既不继承Set 也不继承 Collection,存取的是键值对。
    TreeSet 类是 Set 接口的实现类,它有序的保存数据,但不能用对应的索引获得其中的数据,而HashMap 类是基于 Map 实现的,
    HashMap存储"键值对(key-value)"的散列表,系统将key-value当成一个整体进行处理,根据Hash算法来计算key-value的
    存储位置,通过key获取相对应的value值。

    ------------------------------------ 泛型与反射 ---------------------------------------
    泛型: 是一種把類型明確的工作推遲到創建對象或者調用方法的時候才去明確的特殊的類型
    泛型的本质是参数化类型
    格式:
    <數據類型>
    此處的數據類型只能是引用類型。
    好處: 
    1.把運行時期的問題提前到了編譯期間。
    2.避免了強制類型轉換
    3.增加數據的安全性,提高了性能
    定義泛型類,但不指定泛型類中的參數類型與Object的效果等同。
    定義泛型類,並且指定泛型類中的參數類型,如果傳入的數據不是指定類型那麼編譯期間就會報錯。
    通配符: ?  <?> 代替所有類型
    泛型上限: 表示參數化的類型可能是所指定類型,或其子類。 <? extends E>
    泛型下限: 使用的泛型只能是本類及其父類類型。 <? super E>
    泛型接口: 子類實現有兩種方法:
    一.子類確定泛型的類型
    二.子類繼續使用泛型
    泛型只在編譯器有效。


    類的加載:
    当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。
    加載-------連接-----------初始化
    類加載器
    负责将.class文件加载到内存中,并为之生成对应的Class对象。
    Bootstrap ClassLoader 根类加载器 也被称为引导类加载器,负责Java核心类的加载
    Extension ClassLoader 扩展类加载器 负责JRE的扩展目录中jar包的加载
    Sysetm ClassLoader 系统类加载器 负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径
    反射
    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;
    这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制
    getConstructors() 獲取所有公共的構造方法
    getDeclaredConstructors() 獲取所有的構造方法
    getConstructor() 獲取單個公共的構造方法
    getDeclaredConstructor() 獲取單個(所有)的構造方法
    newInstance() 創建對象
    invoke() 方法調用
    getName() 獲取名稱
    方法.setAccessible(true) 暴力訪問(訪問私有方法屬性)
    getMethods() 獲取所有公共的方法(包括父類中公共的方法)
    getDeclaredMethods() 獲取所有的方法
    getMethod() 獲取單個公共的方法(包括父類中公共的方法)
    getDeclaredMethod() 獲取單個(所有)的方法
    getFields() 獲取所有公共的屬性
    getDeclaredFields() 獲取所有的屬性
    getField() 獲取單個公共屬性
    getDeclaredField() 獲取單個(所有)屬性
     
    -----------------------------------XML-------------------------------------------
     XML有两个先驱--SGML和HTML  
      SGML(Standard Generalized Markup Language)的全称是标准通用置标语言,
      它为语法置标提供了异常强大的工具,同时具有极好的扩展性,因此在分类和索引数据中非常有用。
      但是,SGML非常复杂,并且价格昂贵,在网上传播遇到了很大障碍
      超文本置标语言HTML(HyperText Markup Language)免费、简单,在世界范围内得到了广泛的应用
    *XML:
         可扩展标记语言 
    *标记: 
         指计算机所能理解的信息符号。 
    *标记语言:
         协调一致用来定义整套语法和文法的标记集 
    *XML的官方定义
         SGML的子集,其目标是允许普通的SGML在WEB上以目前HTML的方式被服务、接收和处理。
         XML易于实现,且可在SGML和HTML之间互相操作。 
     XML的優點:
      1) 可扩展的标记
    2) 数据共享和重用
    3) XML遵循严格的语法要求
    4) XML便于不同系统之间信息的传输
    5) 数据存储格式不受显示格式的制约
    6) 包含语义的文档格式
    7) 对面向对象(OOP)的支持  dom
    8) 内容与形式的分离。
    9) 具有较好的保值性。
     XML的缺點:
      1)语义表达能力上略显不足
    2)XML的有些技术尚未形成统一的标准
    3)应用程序浏览器对XML的支持也是有限的
    XML声明: 
    <?xml version = "1.0" encoding = "GB2312" standalone = "no"?>
    其形式是:
            <标记>数据内容</标记>
    XML和HTML的主要区别: 
    XML是被设计用来描述数据的,重点是:什么是数据,如何存放数据。
    HTML是被设计用来显示数据的,重点是:显示数据以及如何更好显示数据。
    @Test 执行指定的方法 导入JUnit4包
    DOM 是用与平台和语言无关的方式表示 XML 文档的官方 W3C 标准。DOM 是以层次结构组织的节点或信息片断的集合。
    DOM xml文件的创建: 
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();//获取 DocumentBuilderFactory 的新实例。
    DocumentBuilder db = dbf.newDocumentBuilder();//使用当前配置的参数创建一个新的 DocumentBuilder 实例。
    Document doc = db.newDocument();//获取 DOM Document 对象的一个新实例来生成一个 DOM 树。
    Element root = doc.createElement("root"); //创建根结点

    TransformerFactory tf = TransformerFactory.newInstance();// 获取 TransformerFactory 的新实例。
    Transformer t = tf.newTransformer();//此抽象类的实例能够将源树转换为结果树。
    t.transform(new DOMSource(root), new StreamResult("xml文件路径"));


    SAX解析
    基于推模式的事件的方式来解析xml,较少占用内存,速度比DOM解析更快,适应于大文件。
    只能读,不能写


    SAXParserFactory saxp=SAXParserFactory.newInstance();
    SAXParser sp=saxp.newSAXParser();
    sp.parse(new File("xml文件路径"),new LxitDefaultHandler());


    自定义 类 继承 DefaultHandler ,
    重写以下五个方法:
    startDocument() 接收文档开始通知
    endDocument() 接收文档结束通知
    startElement() 接收节点开始通知
    endElement() 接收节点结束通知
    characters()  接收元素中字符数据的通知。


    DOM4j解析
    创建xml文件
    String fileName = "xml文件路径";
    Document doc = DocumentHelper.createDocument(); //创建document对象
    Element cla = doc.addElement("root"); //建立根结点
    XMLWriter writer = new XMLWriter(new FileWriter(fileName));
    writer.write(doc);
    writer.close();
    将字符串转化为XML
    String text = "<root><stu>值</stu></root>";
    Document doc = DocumentHelper.parseText(text);
    查询
    SAXReader sr = new SAXReader();
    Document doc = sr.read("xml文件路径");
    List<Element> list = doc.selectNodes("根结点/子结点");
    for(Element element : list) { System.out.println(element.selectSingleNode("字节点名").getText()); }


    增加
    String fileName = "xml文件路径";
    Document doc = DocumentHelper.createDocument(); //创建document对象
    Element cla = doc.addElement("root"); //建立根结点
    Element stu = root.addElement("stu");
    Element id = stu.addElement("id");
    Element name = stu.addElement("name");
    Element sex = stu.addElement("sex");
    Element age = stu.addElement("age");
    id.setText("要增加进入的属性值");
    name.setText("要增加进入的属性值");
    sex.setText("要增加进入的属性值");
    age.setText("要增加进入的属性值");
    XMLWriter writer = new XMLWriter(new FileOutputStream(fileName));
    writer.write(doc);
    writer.close();
    删除,修改同上。。。。。。。。。


    -------------------------------------- HTML试题解析 -------------------------------------------
    1.type 为 password 是 密码框 type 为 radio 是 单选框
      type 为 hidden 是 隐藏域 type 为 reset 是重置按钮
    2.避免用户拖动框架的显示边框,可以使用的是 noresize = "noresize";
    3.框架以百分比表示, * 代表其余的百分比。
    4.同行单元格高度一致,且水平对齐。
    5.HTML 中的特殊符号: &copy; 显示的是版权符号 &reg; 显示的是注册符号
       &times; 显示的是乘号 X
    6.submit 是提交按钮, reset 是重置按钮, image 是图片按钮。
    7.HTML中的列表分为 : 无序列表 ul、有序列表 ol、定义列表 dl; 其中带圆点的是 无序列表 ul.
    8.form 标签的type 属性用于规定input 元素的类型,checkbox 定义复选框,image 定义图像形式的提交按钮,
    submit 定义提交按钮,该按钮会把表单数据发送到服务器,text 定义单行输入字段。
    9.电子邮箱必须包含 @ 符号,,并且以 .com 结尾。


    -------------------------------------- Java基础试题解析  -------------------------------------------
    0.面向对象的封装性,即将对象封装成一个高度自治和相对封闭的个体,对象状态(属性)由这个对象自己的行为(方法)来读取和改变。
    把对同一事物进行操作的方法和相关的方法放在同一个类中,把方法和它操作的数据放在同一个类中.
    1.每个类都使用 Object 作为超类,所有对象(包括数组)都实现这个类的方法。
    2.在不明确给出超类的情况下,Java会自动把 Object 作为要定义类的超类,可以使用类型为 Object 的变量指向任意类型的对象。
    3.Object 类有一个默认构造方法 public Object(),在构造子类实例的时候,都会先调用这个默认构造方法。
    4.Object 类的变量只能用作各种值的通用持有者,要求他们进行任何专门的操作,都需要知道他们的原始类型并进行类型转换。
    5.创建对象格式: 类名 对象名 = new 类名();
    6.接口中只能定义静态常量。
    7.类是对象的集合,对象是类的实例。
    8.try —— catch —— finally 中,从上往下的catch 块,其参数类型必须按照从子类到父类的顺序,因为一旦匹配到一个类型,catch 块
    捕获这个超类及其所有子类的异常,然后忽略往后的catch,也就意味着排在后面的子类永远不会到达,Java中不可到达的代码被认为是错误的。
    9.多态中  父类引用指向子类对象,是无法调用子类独有的方法的 子有父无 编译报错。
    10.抽象类不能使用私有访问修饰符修饰;抽象方法不能使用final 进行修饰;
    11.Java集合框架中,有些类是线程同步安全的类,它们是 Vector、Hashtable、Stack、Enumeration,除了这些之外,其他的都是非线程安全的类和接口。
    线程安全类的方法是同步的,每次只能一个访问,它们是重量级对象,效率低。
    12.Map接口存储一组成对的键——值对象,其中key 不要求有序,不允许重复,value不要求有序,但允许重复。
    13.Java中,java.util.Collections 类属于 无实例类,因为Collections 类提供的方法都是 static 的,所以可以直接使用
    类名.  调用执行,不需要实例化对象。
    14.对 HashMap 而言,系统将key-value 当成一个整体进行处理,根据 Hash算法来计算key-value 的存储位置,这样就可以保证能快速存取
    Map的key-value 对,HashMap 采用一种所谓的"Hash算法"来决定每个元素的存储位置。
    15.String 类中substring() 方法用于字符串的截取,返回截取后的新字符串,但原字符串不会发生变化。
    16.JavaAPI中,集合Set接口的特点:无序的,元素是唯一的。
    17.Java中,String的值是不可变的,这就导致每次对String 的操作都会生成新的String 对象,不仅效率低下,而且大量浪费有限的内存空间。
    由于StringBuffer 的内部实现方式和String不同, 所以StringBuffer在进行字符串处理时,不生成新的对象,在内存使用上要优于
    String类,对StringBuffer对象的每次修改都会改变对象自身。
    18.String 既属于引用类型也属于基础数据类型,而且内容是静态的,在通常情况效率高些,但如果涉及到连接字符串时,对于String 每次连接都要重新
    分配内存,因此从StringBuffer好。
    19.String通过方法操作字符串时,字符串本身没有变化,操作的是该字符串的副本;
    而StringBuffer操作的是字符串的本身,因此StringBuffer 在操作字符串的时更高效.
    20.ArrayList 采用的是数组形式来保存对象的,这种方式将各元素存储在连续的内存空间中,所以优点是遍历和随机访问比较方便,最大的缺点是插入
    删除时非常麻烦,因为都需要循环移位。
    21.LinkedList 采用的将各元素存放,在独立的内存空间中,而且在每个空间中还保存下一个元素的链接索引,因此插入和删除比较方便,只需找到
    插入和删除的位置,重置相应的元素的链接索引,但是缺点是查找非常麻烦,因为其各元素的存储位置不是连续的。
    22.Java的集合框架四个基本接口的区别:
    Collection 接口是一组允许重复的对象.
    Set 接口继承Collection,但不允许重复.
    List 接口继承Collection,有序保存数据,允许出现重复的数据,并引入位置下标.
    Map 接口既不继承 Set,也不继承 Collection,存取的是键值对.
    23.TreeSet 类是 Set接口的实现类,它有序保存的数据,但不能用对应的索引获得其中的数据。
    24.Java集合框架中,HashMap 类是基于哈希表的 Map 接口的实现,此实现提供所有可选的映射操作,并允许使用null值和null键,此类不保证映射
    的顺序,特别是不保证该顺序恒久不变。
    25.进行数据写入文件时,并不是write()方法,而是flush()方法,进行刷新,将buffer中的数据写入到存储目标中。
    26.Java的Data类表示特定的瞬间,精确到毫秒,使用Data类的默认构造方法创建出的对象就可以获得当前时间,要获得当前时间的精确值,在Java中还
    可以通过System.currentTimeMillis()或System.nanoTime()方法获得。
    27.FileInputStream类中读取数据,read()方法读取字符得到的ASCII码值。
    28.使用流是为了简化数据的读写操作,让程序员能专注在有效合理的数据处理上,而不是底层的数据写入对应的物理地址、磁盘驱动器的状态等方面。
    29.要进行方法重写,前提条件是必须继承了类或实现了一个接口,其次是有可以重写的方法,最后才是符合重写要求。
    30.方法里不能使用static修饰临时变量。
    31.在静态方法中,不能直接使用类的非静态成员,否则编译不通过。需要先创建类的对象,使用 对象名.属性 或 对象名.方法 的方式调用。
    32.对字符串而言, == 用来比较两个值的地址是否相等,而 equals 是比较两个值的内容是否相等。
    33.构造方法名必须和类名一致,并且没有返回值,构造方法是在创建对象时调用,对其进行初始化工作,构造方法一般使用public 修饰,但在单例模式中,
    也可以使用private 修饰。
    34.在类中定义的的变量是类的成员变量,但非静态的普通成员变量,不可以在别的类中直接使用,而需要通过创建对象来调用,而且和变量的访问修饰符也有关系。
    在使用别的类的方法时,如果该方法是非private 的,可以被调用,普通方法需要通过 对象名调用,静态方法通过 类名调用。
    35.使用static 修饰的成员变量称为静态成员或类成员,可以使用 类名直接访问,也可以使用 类的对象访问,而未使用static修饰的成员为实例成员,
    只能使用 类的对象访问。
    36.多重继承中,初始化顺序为 1.父类属性 2.父类构造方法 3.子类属性 4.子类构造方法
    37.关键字super()明确显式地指出一个类可以使用它父类的构造函数、方法和变量,如父类和子类属性名称相同,不使用super则执行子类属性。
    38.子类对象赋值给父类引用,此时调用的方法是被子类重写的方法。
    39.当创建子类对象时,如果存在父类,将先调用父类的无参或有参构造,再执行子类的构造方法。
    40.方法重写是在两个类存在继承关系时,子类可以重写父类中的同名方法,要求参数列表相同,访问权限不能严于父类,返回值类型与被重写方法相同或是其子类。
    41.面向对象三大特性是 封装、继承、多态,其中Java的类是 单继承的,不支持多继承,即extends关键字后只能有一个类的名称,即直接父类。
    Java的类继承关系形成一个树型结构,而不是网状结构。
    42.Java的非检查异常(编译器不要求强制处置的异常): 包括 运行时异常(RuntimeException及其子类)和错误(Error);
    Java编译器不要求一定要把它捕获或者一定要继续抛出,但是对checked exception(检查异常)要求必须要在方法里面捕获或者继续抛出。
    43.try 块中代码量太多,过于庞大,会提高程序的复杂度,如果程序发生异常,排查错误,分析问题代码会需要较长的时间。
    44.父类对象转换为子类类型是不安全的,子类对象转换为父类类型是安全的。
    45.throw 用于手动抛出异常,除Java语言中定义的异常类型外,还可抛出自定义异常。
    throws 用于声明方法中可能发生的异常,说明知道方法中可能有异常但不想马上处理,而希望抛出给上级处理。
    46.throw 指抛出的一个具体的异常类型; throwable 类是Java语言中所有错误或异常的超类,只有当对象是此类(或其子类之一)的实例时,才能通过
    Java虚拟机或者关键字抛出异常; throws 是用来声明一个方法可能抛出的所有异常信息。
    47.抽象类实现某个接口,可以不实现所有接口的方法,可以由它的子类实现,而普通类即非抽象,则必须实现接口里的全部方法,接口不可以进行实例化。
    48.接口里变量只能是静态常量,必须赋值,方法必须为抽象方法,接口只能使用public 进行修饰或省略。
    49.多态的实现方式: 使用父类作为方法形参实现,使用父类作为返回值实现。
    50.Object 类的toString()方法,将返回一个此对象相关信息的字符串,具体信息为:
    包名.类名 + @ +此对象哈希码的无符号十六进制表示。
    51.抽象类中可以有构造方法,其构造方法虽然不能用做实例化对象,但是可以被子类调用,抽象类中可以有实例方法,被子类继承,抽象类中的抽象方法可以是
    public、protected、默认类型。接口中只有public型静态常量和public型抽象方法。
    52.在继承父类的子类中要访问父类public修饰符的属性和方法,可以用this或者super调用。
    53.break 只能跳出内层循环,不能跳出外层循环。
    54.编写Java程序时,package要在import之前。
    55.JavaSE 标准版和JavaEE 企业版是能够与C# 和 .NET 技术平分天下的应用软件开发技术和平台。
    56.main()方法是整个Java程序的入口,Java程序中可以包含多个Java类,但只能有一个类包含main()方法。
    57.JDK 目录结构: Bin 目录下有编译器、解释器和各种工具。
      Jre 目录是Java程序运行环境的根目录,其下有bin子目录,包括平台使用所有工具和库的可执行文件和DLL文件,
       lib子目录包括Java运行环境的代码库。
      lib 目录下都是库文件。
      Demo 目录下有各种演示例子。
      Include 目录下是win32子目录,都是本地方法文件。
    58.Java是由Sun Microsystems 公司于1995年5月推出的Java面向对象程序设计语言和Java平台的总称。
    59.Java依赖于JVM(Java虚拟机),解释字节码文件并运行,可以实现一次编写,处处运行,即其跨平台性。
    Java是一种面向对象的编程语言,支持多线程机制,多线程机制使得Java程序能够并行处理多项任务。
    60.Java中一个项目只能有一个main方法,并且在main内部不管有没代码都必须使用{}括起来。
    61.在Eclipse开发Java程序的顺序为:创建项目、编写源程序保存为.java文件、执行编译命令生成的.class文件、运行。
    62.变量名的要求和规范,变量名首先不能以数字开头,但是可以包含数字,只能包含"_","$"两个特殊符号,可以以"_","$"开头,一般是以字母开头。
    63.在Java中使用Scanner 实现控制台的输入,使用System.out实现控制台的输出,实现控制台的输入时,需要传递参数,实现换行输入需要使用
    System.out.println实现换行输出,System.out.print输出不换行。
    64.使用javac 命令才可以编译.java 文件,通过java 命令运行.class文件。
    65.Java标识符可以由字母、下划线、$及数字组成,但是不可以以数字开头,且区分大小写,不可以使用Java的关键字。
    66.在Java中,byte类型占1个字节,float和double 分别为单精度及双精度浮点数,两者都是可以有符合的。
    67.Java中的访问控制关键字为:public、protected、private以及默认,其中public为公共的,其访问控制保护最弱,
    private为私有的,其访问控制保护最强。
    68.Java中三种注释:单行注释(行注释): //
       多行注释(段落注释): /*...*(/)
    文档注释: /**...*(/)
    69.使用DOM4j解析XML文档,其解析步骤为:
    获取SAXReader 对象、读取需要解析的XML文档、开始解析。
    70.addFirst()方法为LinkedList集合特有的方法。
    71.与序列化和反序列化有关的是:Serializable 序列化接口、FileOutputStream 字节输出流、ObjectOutputStream 序列化输出的类
    transient 屏蔽不想序列化的属性
    72.ASCII编码中 65——‘A’; 97——‘a’;
    73.使用DOM4j解析XML文件时,Element 对象的attribute() 方法用来获取节点的属性。
    74.局部变量前不能放置任何访问修饰符 (private,public,和protected)。final可以用来修饰局部变量(final如同abstract和strictfp,
    都是非访问修饰符,strictfp只能修饰class和method而非variable)。
    75.abstract的methods不能以private修饰。abstract的methods就是让子类implement(实现)具体细节的,怎么可以用private把abstract
    method封锁起来呢? (同理,abstract method前不能加final)。


    ------------------------------------------- Java 基础 完结 ----------------------------------------

  • 相关阅读:
    数据结构-二叉搜索树
    多任务处理方式之一:多进程
    TCP并发服务器
    REST是什么?RESTFul又是什么?这二者的关系是怎样的?
    Python中的深浅拷贝的区别
    查找算法之 '二分法查找'
    排序算法之 '快速排序'
    CCS
    CCS
    CCS
  • 原文地址:https://www.cnblogs.com/798911215-Darryl-Tang/p/9118546.html
Copyright © 2020-2023  润新知