开发环境

  1. JDK:JAVA 编译环境
  2. JRE:JAVA 运行环境

根本语法

数据类型(四种八类型)

  1. 整数型:byte, short, int, long;
  2. 浮点型:float, double;
  3. 字符型:char;
  4. 布尔型:boolean.

书写标准

类名放弃首字母大写,包名放弃小写,办法名应用驼峰写法。

面向对象

在 JAVA 中,万事万物都是对象。尽管如此,理论的代码编译中操作的的确对象的援用(reference)

类也是对象

对象援用是绝对于对象独立的存在,也就是说有一个对象利用,然而不须要一个对象与之对应

Car carKey;

以上创立的只是援用,而并非对象。如果想在代码之中应用这个援用时,会返回一个没有对象关联的异样。平安的做法是,在创建对象援用时把一个对象赋给它。此时咱们须要应用new办法。

new一个对象

应用new进行对象的创立:

Sheep sheep1 = new Sheep();Sheep sheep2 = new Sheep("codesheep", 18, 65.0f);

通过new办法,通过调用类的无参或有参结构的办法来实例化了两个对象。

在创建对象的过程中,JVM解决了如下步骤

  1. 首先,new一个对象时,以Sheep sheep = new Sheep()为例,JVM会先来查看Sheep这个符号援用的类是否曾经被加载过,如果没有就要执行对应类的加载过程。在这个过程中,对象占用的内存就曾经定下来了。
  2. 申明类型援用。Sheep sheep = new Sheep()中就申明了一个Sheep类型的援用sheep
  3. 依照第一步中布局的内存调配打算,JVM会在堆上给对象分配内存。
  4. 初始化0值。例int的初始化0值就是0,对象化的初始化0值就是null。
  5. 接下来JVM会进行对象头的设置,这外面就次要包含对象的运行时数据(比方Hash码、分代年龄、锁状态标记、锁指针、偏差线程ID、偏差工夫戳等)以及类型指针(JVM通过该类型指针来确定该对象是哪个类的实例);
  6. 属性的显示初始化也好了解,比方定义一个类的时候,针对某个属性字段手动的赋值,如:private String name = "codesheep"; 就在这时候给初始化上;
  7. 最初是调用类的构造方法来进行进行构造方法内形容的初始化动作。

通过以上的步骤一个对象才得以诞生。

属性和办法

类的一个最根本的因素就是属性和办法。

属性也被称为字段,是类的重要组成部分。属性能够使任意类型的对象,也能够是最根本的数据类型。

class A{    int a;    Apple apple;}

类中还应该包含办法,办法示意的是做某些事件的形式。办法其实就是函数,只不过Java习惯把函数成为办法,这种叫法也体现了面向对象的概念。

办法的根本形成包含:

  1. 办法名称;
  2. 参数;
  3. 返回值;
  4. 办法体。

e.g.

public int getResult(){    // ...    return 1;}

其中getResult就是办法名,()示意承受的参数,return示意办法的返回值,{}中的为办法体。

构造方法

在Java中,有一种非凡的办法被称为构造方法(或构造函数、结构器)。在Java中,通过提供这个结构器,来确保每个对象都被初始化。构造方法只能在对象创立期间调用一次,保障了对象初始化的进行。构造方法比拟非凡,它没有参数类型和返回值,它的名称要和类名称保持一致,并且构造方法能够有多个。

e.g.

//一堆初始化办法的初始化类class Apple{    int sum;    String color;        public Apple(){}    public Apple(int sum){}    public Apple(String color){}    public Apple(int sum, String color){}}//开始class createApple{    public static void main(String[] args){        Apple apple1 = new Apple();        Apple apple2 = new Apple(1);        Apple apple3 = new Apple("red");        Apple apple4 = new Apple(2,"color");    }}

以上,在Apple类中,定义了四个构造方法。其中,不加任何参数的构造方法被称为默认的构造方法,即:

Apple apple1 = new Apple();

如果类中没有定义任何构造方法,JVM会主动生成一个默认的构造方法。默认的构造方法以被称为默认结构器或者无参结构器。然而如果定义了任何一个构造方法,JVM将不再提供默认结构器。

办法重载

在 Java 中一个很重要的概念是办法的重载,它是类名的不同表现形式。之前说的构造函数,实际上也是重载的一种。

每个重载的办法都有举世无双的参数列表(其中包含参数的类型,程序,参数数量等),此为 Java 来辨别重载指标办法的规范。

重载的条件

  1. 办法名称必须雷同;
  2. 参数列表必须不同 (个数不同、类型不同、参数类型排列程序不同等);
  3. 办法的返回类型能够雷同也能够不同;
  4. 仅仅返回类型不同不足以成为办法的重载;
  5. 重载是产生在编译时的,因为编译器能够依据参数的类型来抉择应用哪个办法。
public class Apple{    int sum;    String color;        public Apple(){}    public Apple(int sum){}        //重载        public int getApple(int num){        return 1;    }        //重载    public String getApple(String color){        return "color";    }}

办法的重写

办法重写尽管与重载名字很类似,然而齐全不同。办法重写的形容是对子类和父类之间的。而重载指的是同一类中。

重写的准则:

  1. 重写的办法必须要和父类保持一致,包含返回值的类型,办法名,参数列表也都一样;
  2. 重写的办法能够应用@Override注解来进行标注;
  3. 子类中重写办法的拜访权限不能低于父类中办法的拜访权限。
class Fruit{        public void eat(){        System.out.println('eat fruit');    }}class Apple extends Fruit{        @Override    public void eat(){        System.out.println('eat apple');    }}

初始化

类初始化

创建对象援用时,如果没有相应的类,则实际上是调用了这个对象的无参构造方法来进行的初始化,如下:

class Car{    public Car(){}}

实际上就是初始化了一个类,默认进行,由 JVM 主动增加。

成员的初始化

Java会尽量保障每个变量在应用前都会取得初始化,初始化波及两种初始化。

  1. 一种是编译器默认指定的字段初始化,根本数据类型的初始化。

    | 类型 | 初始值 |
    | :-----: | :------: |
    | boolean | false |
    | char | /u0000 |
    | byte | (byte)0 |
    | short | (short)0 |
    | int | 0 |
    | long | 0L |
    | float | 0.0f |
    | double | 0.0d |

    其余对象类型的初始化,String也是一种对象,对象的初始值都是null,其中也包含根本类型的包装类。

  2. 一种是指定数值的初始化,e.g.

    int a = 11

    也就是说,指定a的初始化值不是0,而是11.其余根本类型和对象类型也是一样的。

结构器初始化

能够利用结构器来对某些办法和某些动作进行初始化,确定初始值,e.g.

public class Counter{    int i;    public Counter(){        i = 11;            //结构器对i的初始化值解决,对i初始化为11.    }}

初始化程序

须要探讨的初始化程序:

  • 动态属性:static 结尾定义的属性;
  • 静态方法块:static{}
  • 一般属性:非static定义的属性;
  • 一般办法块:{}包起来的代码块;
  • 构造函数:类名雷同的办法;
  • 办法:一般办法。
public class LifeCycle{    //动态属性    private static String staticField = getStaticField();    //静态方法块    static {        System.out.println(staticField);        System.out.println("静态方法块初始化");    }    //一般属性    private String field = getField();    //一般办法块    {        System.out.println(field);    }    //构造函数    public LifeCycle(){        System.out.println("构造函数初始化");    }        public static String getStaticField(){        String statiFiled = "Static Field Intial";        return statiFiled;    }        public static String getField(){        String filed = "Field Initial";        return filed;    }    //主函数    public static void main(String[] args){        new LifeCycle();    }}

执行程序:

  1. 动态属性初始化;
  2. 静态方法块初始化;
  3. 一般属性初始化;
  4. 一般办法块初始化;
  5. 构造函数初始化。

数组初始化

数组是雷同类型的、用一个标识符名称风撞到一起的一个对象序列或根本类型数据序列。数组是通过方括号下表操作符[]来定义应用的。e.g.

//以下两段含意雷同int[] a1;int a1[];//赋值操作int arrary[4] = {1, 2, 3, 4};        //间接给每个元素赋值int arrary[4] = {1, 2};        //给一部分赋值,前面的都是0int arrary[] = {1,2};        //由参数的各述决定数组的个数

可变参数列表

Java 中对数组的一种比拟冷门的用法就是可变参数,可变参数的定义如下:

public int add(int... numbers){    int sum = 0;    for(int num : numbers){        sum += num;    }    return sum;}

而后,能够应用以下办法进行可变参数的调用:

add();        //不传参数add(1);        //传递一个参数add(2,1);        //传递多个参数add(new Integer[] {1, 3, 2});        //传递数组

对象销毁

Java 与 C 语言不同的一个重要特色就是 Java 不须要本人手动治理对象的销毁工作,而是由 JVM来治理和销毁。尽管不须要手动销毁,然而仍须要晓得对象作用域这个概念。

对象作用域

绝大多数语言都有作用域(scope)这个概念。作用域决定了其外部定义的变量名的可见性和生命周期。在Java 中,作用域通常由{}的地位来决定,e.g.

{    int a = 11;    {        int b =12;    }}

a 变量会在两个{}作用域无效,而 b 变量的值只能在它本人的{}内无效。

尽管存在作用域,然而不容许以下写法:

{    int x = 11;    {        int x = 12;    }}

这种写法在 C 中是能够的,然而在 Java 中不容许,因为老头认为这样写会导致程序凌乱。

this 和 super

this super 都是 Java 中的关键字

this 标识的以后对象, this 能够调用办法、调用属性和指向对象自身。this 在 Java 中的应用个别有三种。

e.g.

public class Apple{        int i = 0;        Apple eatApple(){        i++;        return this;            //退出this,调用eatApple()总会返回对象本身    }        public static void main(String[] args){        Apple apple = new Apple();        apple.eatApple().eatApple();    }}//this润饰属性public class Banana{    private int num;        public Banana(int num){        this.num = num;            }        public static void main(String[] args){        new Banana(10);        //传递"10"给全局变量num    }}//this充当全局关键字,this()必须放在构造方法的第一行,否则编译不通过public class Apple{    private int num;    private String color;        public Apple(int num){        this(num,"红色");            }        public Apple(String color){        this(1,color);    }        public Apple(int num, String color){        this.num = num;        this.color = color;    }}

如果 this 是指向本身的一个援用,那么 super 就是指向父类的一个援用。super 关键字和 this 一样,能够应用 super.object 来援用父类成员。

e.g.

public class Fruit{    int num;    String color;        public class Apple extends Fruit{                @Override        public void eat(){            super.num = 10;            System.out.println("eat" + num + "Apples");        }    }}

应用 super 来调用父类的构造函数同this

两个办法都有的特色:

  1. 调用地位都是构造函数第一行,非构造函数地位自定;
  2. 调用次数:一个构造函数只可调用一次。

访问控制权限

访问控制权限又称为封装,它是面向对象三大特色中的一种。访问控制类的外围是只对须要的类可见

Java 中成员的拜访权限总共有四种:public, protected, default, private.

privatedefaultprotectedpublic
同一类
同一包中的类
子类
其余包中的类

标识能够拜访。

继承

继承是所有oop 语言都不可短少的一部分。只有一个类被创立,那么它就隐式继承自 Object 父类,只不过没有指定。如果你显示指定了父类,那么你继承于父类,而你的父类继承于object 类。

//继承关键字:extendsclass Father{}class Son extends Father{}

Son类会保留有Father的属性,如果Son类没有实现本人的办法的话,那么默认就是用的父类Father的办法。如果子类实现了本人的 feature 办法,那么就相当于是重写了父类的 feature 办法。

多态

多态指的是同一个行为具备不同的表现形式。是指一个类实例(object )的雷同办法在不同情景下具备不同表现形式。封装和继承是多态的根底,也就是说多态只是一种表现形式而已。

多态实现的三个充要条件

  1. 继承
  2. 重写父类办法
  3. 父类援用指向子类对象

e.g.

public class Fruit{    int num;        public void eat(){        System.out.println("eat Fruit");    }}public class Apple extends Fruit{        @Override    public void eat(){        super.num = 10;        System.out.println("eat " + num + " Apple");    }        public static void main(String[] args){        Fruit fruit = new Apple();        fruit.eat();    }}

如代码所示,Fruit fruit = new Apple() Fruit类型的对象指向了Apple对象的援用,此处便是父类援用指向子类对象,因为Apple继承于Fruit,并且重写了eat办法,所以可能体现出多种状态的模式。

组合

指:将对相援用置于新类中。组合也是进步类复用性的一种办法。如果想让类具备更多的拓展性能,要做到多用组合,少用继承

public class SoccerPlayer{        private String name;    private Soccer Soccer;}public class Soccer{        private String soccerName;}

如上 SoccerPlayer 中援用了 Soccer 类,通过援用 Soccer 类,调用其中的属性和办法。组合和继承石油区别的,如下:

特色组合继承
关系组合是一种has - a 的关系,能够了解为有一个集成式一种 is - a 的关系,能够了解为是一个
耦合性组合的单方是一种松耦合的关系继承单方紧耦合
是否存在多态组合不具备多态和向上转型继承是多态的根底,能够实现向上转型
期间组合是运行期绑定继承是编译期绑定

代理

大抵形容:A想要调用B类的办法,A不间接调用,A会在本人的类中创立一个B对象的代理,再由代理调用B的办法。

e.g.

public class Destination {        public void todo(){        System.out.println("control...");    }        public class Device{                private String name;        private Destination desitination;        private DeviceController deviceController;        public void control(Destination destination){            destination.todo();        }     }        public class DeviceController{                private Device name;        private Destination destination;                public void control(Destination destination){            destination.todo();        }    }}

向上转型

向上转型代表了父类和子类之间的关系,其实父类和自磊之间不仅仅有向上转型,还有向下转型,他们的转型后范畴不同。

  • 向上转型:通过子类对象(小范畴)转化为父类对象(大范畴),这种转换是主动实现的,不必强制。
  • 向下转型:通过父类对象(大范畴)转化为子类对象(小范畴),这种转换不是主动实现的,须要强制指定。

static

static 是 Java 中的关键字,它的意思是动态的,static 能够用来润饰成员变量和办法, static 用在没有创建对象的状况下调用 办法/变量。

  • 用static申明的成员变量为动态策动可能员变量,也就是类变量。类变量的生命周期和类雷同,在整个应用程序执行期间都无效。

    static String name = "aaa";
  • 应用 static 润饰的办法称为静态方法,静态方法可能间接实用类名.办法名进行调用。因为静态方法不依赖于任何对象就能够间接拜访,因而对于静态方法来说,是没有this关键字的,实例变量都会有this关键字的成果。在静态方法中不能拜访类的非动态成员变量和非静态方法。

    static void printMessage(){    System.out.println("aaa is aaa");}

static 除了润饰副属性和办法外,还有动态代码块的性能,可用于类的初始化操作。进而晋升程序的性能。

public class StaicBlock{    static{        System.out.println("I am sb");    }}

因为动态代码块随着类的加载而执行,所以很多时候只须要进行一次初始化操作放在static代码块中进行。

final

  • final 润饰类时,示意这个类不能被继承,final 类中的成员变量能够依据须要设为 final ,然而要留神 final 类中的所有成员办法都被隐式地指定为 final 办法。
  • final 修式办法时,表明这个办法不能被任何子类重写,因而,如果只有在想明确禁止该办法在子类中被笼罩的状况下能力将办法设置为final。
  • final 润饰变量分为两种状况,一种是润饰根本数据类型,示意数据类型的值不能被批改;一种是润饰援用类型,示意对其初始化之后便不能再让其指向另一个对象。

接口和抽象类

接口

技术黑箱与统一标准。

在 Java 中,接口是由 interface关键字来示意的,比方咱们能够向上面定义一个接口

public interface 123(){        void writeWell();}

接口的特色:

  • interface接口是一个齐全形象的类,不会提供任何办法的实现,只是会进行办法的定义。
  • 接口中只能是用来那个中拜访修饰符,一种是public,它对整个我的项目可见;一种是default缺省值,它只具备包拜访权限。
  • 接口只提供办法的定义,接口没有实现,然而接口能够被其余类实现。也就是说,实现接口的类须要提供办法的实现,实现接口应用implements关键字来显示,一个接口能够有多个实现。
class 123 implements 123Job{        @Override    public void writeWell(){        Sysyem.out.println("123");    }}
  • 接口不能被实例化,所以接口中不能有任何构造方法,定义构造方法编译会出错。
  • 接口的实现比方实现接口的全副办法,否则必须定义为抽象类。

抽象类

抽象类是一种形象能力弱于接口的类,在Java中,抽象类应用abstract关键字来示意。如果把接口形容为为狗这个动物,那么抽象类能够说是毛色是红色、小型的种类,而实现类能够是具体的类,比如说是泰迪,博美。能够如下图定义抽象类

public interface Dog {        void FurColor();    }abstract class WhiteDog implements Dog {    public void Fur Color(){        System.out.println("Fur is white.");    }    abstract void SmallBody();}

在抽象类中,具备如下特色

  • 如果一个类中有形象办法,那么这个类肯定是抽象类。应用关键字abstract润饰的办法肯定是形象办法,具备形象办法的类肯定是抽象类。实现类办法中只有办法具体的实现。
  • 抽象类中不肯定只有充想办法,抽象类中也能够有具体的办法。能够抉择是否实现这些办法。
  • 抽象类中的束缚不想接口那么严格,能够在抽象类中定义 构造方法、形象办法、一般属性、办法、动态属性、和静态方法
  • 抽象类和接口一样不能被实例化,实例化只能实例化具体的类

异样!

异样是程序常常会呈现的,发现错误的最佳时机切实编译阶段,也就是在试图运行程序之前。然而在编译期间并不能找到所有的谬误,有一些NullPointerExceptionClassNotFoundException异样在编译期间是找不到的,这些异样是RuntimeExcption运行时异样,这些异样往往在运行时能力被发现。

咱们写 Java 程序常常会呈现两种问题,一种是 java.lang.Exception ,一种是 java.lang.Error,都用来示意出现异常状况,上面针对这两种概念进行了解。

意识 Exception

Exception位于java.lang包下,它是一种顶级接口,继承于Throwable类,Exception类及其子类都是 Throwable 的组成条件,是程序呈现的正当状况。

在意识 Exception 之前,有必要先理解一下什么是 Throwable

什么是 Throwable

Throwable 类是 Java 语言中所有errorsexceptions的父类。只有继承于 Throwable 的类活着其子类才可能被抛出,还有一种形式是带有 Java 中的 @throw 注解也能够抛出。

java标准中,对非受查一场合受查异样的定义是这样的

The unchecked exception classes are the run-time exception classes and the error classes.

The checked exception classes are all exception classes other than the unchecked exception classes. That is, the checked exception classes are Throwable and all its subclasses other than RuntimeException and its subclasses and Error and its subclasses.

也就是说,除了RuntimeException和其子类,以及Error和其子类,其余所有异样都是checkedException

那么依照这种逻辑,咱们能够对 Throwable 及其子类进行演绎剖析。

由此可见,Throwable 位于异样和谬误的最顶层,咱们查看 Throwable 类中发现它的办法和属性有很多,当初只总结其中比拟罕用的几个:

//返回抛出异样的详细信息public String getMesage();public String getLocalizedMessage();//返回异样产生的简要形容public String toString();//打印异样到规范输入流上public void printStackTrace();public void printStackTrace(PrintStream s);public void printStackTrace(PrintWriter s);//记录栈帧的以后状态public synchronized Throwable fillInStackTrace();

此外,因为 Throwable 的父类也是 Object,所以罕用的办法还有继承父类的getClass()getName()办法。

常见的Exception

当初晓得Exception的父类是Throwable,并且Exception有两种异样,一种是RuntimeException;一种是CheckedException,这两种异样都应该去捕捉

上面列出一些 Java 中常见的异样及其分类。

RuntimeException

序号异样名称异样形容
1ArrayIndexOutOfBoundsException数组越界异样
2NullPointerException空指针异样
3IllegalArgumentException非法参数异样
4NegativeArraySizeException数组长度为负
5IllegalStateException非法状态
6ClassCastException类型转换异样

UncheckedException

序号异样名称异样形容
1NoSuchFieldException示意该类没有指定名称
2NoSuchMethodException示意该类没有指定办法
3IllegalAccessException不容许拜访某个类
4ClassNotFoundException类没有找到

与Exception无关的Java关键字

Java中会怎么解决这些异样?有如下关键字:throws, throw, try, finally, catch

throws和throw

Java中异样也是一个对象。若要被自定义抛出或者应用程序抛出,必须借助throwsthrow语句来定义异样。

throws 与 throw通常是成对呈现的,如

static void catchException() throws Exception{        throw new Exception();    }

throw 语句用在办法体外部,表述抛出异样,由办法体内的语句解决。throws 语句用在办法申明后,示意再抛出异样,由该办法的调用者来解决。

throws次要是申明这个办法会抛出这个类型的异样,使它的使用者晓得要捕捉这个异样。throw 是具体向外抛异样的动作,所以它是抛出一个异样实例。

try finally catch

这三个关键字次要由一下组合:

try...catch

try...finally

try...catch...finally

//try...catch 示意对某一段代码可能抛出异样进行的捕捉static void cacheException() throws Exception{        try {        System.out.println("1");    }catch (Exception e){        e.printStackTrace();    }}//try...finally示意对一段代码不论执行状况如何,都会走到finally中的代码static void cacheException() throws Exception{    for (int i=0, i<5, i++){        System.out.println("enter: i=" + i);        try{            System.out.println("execute: i=" + i);            continue;        }finally{            System.out.println("leave: i =" + i);        }    }}

Error

Error是程序无奈解决的谬误,示意运行应用程序中较重大问题。大多数谬误与代码编写者执行的操作无关,而示意代码运行时 JVM 呈现的问题。这些谬误大多数是不可查看的,因为它们在应用程序的管制和解决能力之外,而且绝大多数是程序运行时不容许呈现的状况。e.g. OutOfMeoryErrorStackOverFlowError异样的呈现会有基种状况。

外部类

以上的所有都是一般类的定义。而外部类与其不同。

外部类的定义:能够将一个类的定义放在另一个类的外部,这就是外部类。

创立外部类

public class OuterClass{    private String name;    private int age;        class InnerClass{        public InnerClass(){            name = "abc";            age = 15;        }    }}

在这段代码中,InnerClass就是OuterClass的一个外部类。每个外部类都能独立地继承一个(接口的)实现,所以无论外部类是否曾经继承了某个(接口的)实现,对于外部类都没有影像。外部类领有外部类的拜访权

外部类不仅仅可能定义在类的外部,还能够定义在办法和作用域外部,这种被称为部分外部类,除此之外,还有匿名外部类、外部类以及实现Java中的多重继承。上面是定义外部类的办法:

  • 一个在办法中定义的类(部分外部类)
  • 一个定义在作用域中的类,这个作用域在办法的外部(成员外部类)
  • 一个实现了接口的匿名类(匿名外部类)
  • 一个匿名类,它拓展了非默认结构器的类
  • 一个匿名类,执行字段初始化操作
  • 一个匿名类,它通过实例初始化实现结构

因为每个类都会产生一个.class文件,其中蕴含了如何创立该类型的对象的全副信息。应用$来示意外部类的信息,比方OuterClass$InnerClass.class

汇合

Iterable接口

实现此接口容许对象称为 for-each 循环的指标,也就是加强 for 循环,也是 Java 中的一种语法糖

List<Object> list = new ArrayList();for (Object obj: list){}

除了实现此接口的对象外,数组也能够用 for-each 循环遍历,如下:

Object[] list = new Object[10];for (Object obj: list){}

其余遍历形式

jdk 1.8之前Iterator只有 iterator 一个办法,就是

Iterator<T> iterator();

实现此接口的办法可能创立一个轻量级的迭代器,用于平安地遍历元素,移除元素,增加元素。这外面波及一个fail-fast机制。

也能够应用迭代器的办法进行遍历:

for(Iterator it = coll.iterator(); it.hasNext();){    System.out.println(it.next());}

顶级接口

Collection是一个顶级接口,它次要用来定义汇合的约定。

List接口是一个顶级接口,它继承了Collection接口,同时也是ArrayListLinkedList等汇合元素的父类。

Set接口位于与List接口同级的档次上,它同时也继承了Collection接口。Set扣扣提供了额定的规定。它对add,equals,hashCode办法提供了额定的规范。

Queue适宜List,Set接口并列的Collection的三大接口之一。Queue的设计用来在解决之前放弃元素的拜访秩序。除了Collection根底的操作之外,队列提供了额定的插入,读取,查看操作。

SortedSet接口间接继承于Set接口,应用Comparable对元素进行天然排序或者应用Comparator在创立时对元素提供定制的排序规定。set的迭代器将按升序元素程序遍历汇合。

Map是一个反对key-value存储的对象,Map不能蕴含反复的key,每一个key最多映射一个value。这个接口代表了Dictionary类。Dictionary类是一个抽象类而不是接口。

ArraryList

ArraryList是实现了List接口的可扩容数组(动静数组),它的外部是给予数组实现的。它的具体定义如下:

public class ArraryList<E> extends AbstractList<E> implements List<E>,RandomAccess, Cloneable, java.io.Serializable {...}
  • ArraryList能够实现所有可抉择的列表操作,容许所有的元素,包含空值。ArraryList还提供了外部存储list的办法,它可能齐全代替Vector,只有一点例外,ArraryList不是线程平安的容器。
  • ArraryList有一个容量的概念,这个数组的容量就是List用来存储元素的容量。
  • ArraryList不是线程平安的容器,如果多个线程中至多有两个线程批改了ArraryList的构造的话就会导致线程平安问题,作为代替条件能够应用线程平安的List,应应用Collections.synchronizedList

    List list = Collections.synchronizedList(new ArraryList(...))
  • ArraryList具备fail-fast疾速失败机制,可能对ArraryList作出失败检测。当在跌待汇合的过程中该汇合在结构上产生扭转的时候,就有可能会产生fail-fast,即抛出ConcurrentModificationException异样。

Vector

VectorArraryList一样,都是基于数组来实现的,只不过Vector是一个线程平安的容器,它对外部的每个办法都简略粗犷的上锁,防止多线程引发的安全性问题,但通常这种同步形式须要的开销比拟大,因而,拜访元素的效率远远低于ArraryList

扩容上,ArraryList扩容后的数组长度会减少50%,而Vector的扩容长度后数组会增加一倍。

LinkedList类

LinkedList是一个双向链表,容许存储任何元素。特色如下

  • LinkedList所有的操作都能够体现为双向性的,索引到链表的操作将遍历从头到尾,视哪个间隔近为遍历程序。
  • 留神这各市县不是线程平安的,如果多个线程并发拜访链表,并且至多其中的一个线程批改了链表构造,那么这个链表必须进行内部桎梏。或者应用

    List list = Collection.synchronizedList(new LinkedList(...))

Stack

栈堆是咱们常说的后入先出容器。它继承了Vector类,提供了罕用的pushpop操作,以及在栈顶的peek办法,测试stack是否为空的empty办法,喝一个寻找与栈顶间隔的search办法。

第一次创立栈,不蕴含任何元素。一个更欠缺,可靠性更强的LIFO栈操作由Deque接口和他的实现提供,应该优先应用这个类。

Deque<Integer> stack = new ArraryDeque<Integer>()

HashSet

HashSetSet接口的实现类,由HashMap反对(实际上HashSetHashMap的一个实例)。它不能保障汇合的迭代程序。这个类容许null元素。

  • 留神这个实现不是线程平安的,如果多线程并发拜访HashSet,并且至多一个线程批改了set,必须进行内部桎梏。或者应用Collections.synchronizedSet()办法重写。
  • 这个实现反对fail-fast机制。

TreeSet

TreeSet是一个基于TreeMapNavigableSet实现。这些元素应用它们的天然排序或者在创立时提供的Comparator进行排序,具体取决于应用的构造函数。

  • 此实现为基本操作,add,removecontains提供了log(n)的工夫老本。
  • 留神这个实现不是线程平安的。如果多线程并发拜访TreeSet,并且至多一个线程扭转了Set,必须进行内部加锁。或者应用

    SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...))

LinkedHashMap类

LinkedHashMapMap接口的Hash表和链表的实现。这个实现与HashMap不同之处在于它保护了一个贯通其所有条目标双向链表。这个链表定义了遍历程序,通常是插入map中的程序。

  • 它提供了一个非凡的LinkedHashMap(int, float, bloolean)结构器来创立LinkedHashMap,其遍历程序是其最初一次拜访的程序。
  • 能够重写removeEldestEntry(Map.Entry)办法以便在将新映射增加到map时强制删除过期映射的策略。
  • 这个类提供了所有可抉择的map操作,并且容许null元素。因为保护链表的额定开销,性能可能会低于HashMap,有一条除外:遍历LinkedHashMap中的collection-views须要与map.size成正比,无论其容量如何。

Hashtable类

IdentityHashMap类

WeakHashMap类

Collection类

Collection不属于Java框架继承树上的内容,它属于独自的分支,Collection是一个包装类,它的作用就是为了汇合框架提供某些性能实现,此类只包含静态方法操作或者返回collections

同步包装

同步包装讲主动同步(线程安全性)增加到任意汇合。六个外围汇合接口(Collection,Set,List,Map,SortedSet,SortedMap)中的每一个都有一个动态工厂办法。

public static Collection synchronizedCollection(Collection c);public static Set synchronizedSet(Set s);public static List synchronizedList(List list);public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m);public static SortedSet synchronizedSortedSet(SortedSet s);public static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m);

不可批改的包装

不可批改包装的包装器通过拦挡批改汇合的操作并抛出UnSupportedOperationException,次要用在上面两个情景:

  • 构建汇合后使其不可扭转。在这种状况下,最好不要去获取返回collection的援用,这样有利于保障不变性
  • 容许某些客户端以只读形式拜访你的数据结构。你保留对返回的collecton的援用,但散发对包装器的援用。通过这种形式,客户能够查看但不能批改,同时放弃齐全拜访权限。

这些办法是:

public static Collection unmodifiableCollection(Collection<? extends T> c);public static Set unmodifiableSet(Set<? extends T> s);public static List unmodifiableList(List<? extends T> list);public static <K,V> Map<K, V> unmodifiableMap(Map<? extends K, ? extends V> m);public static SortedSet unmodifiableSortedSet(SortedSet<? extends T> s);public static <K,V> SortedMap<K, V> unmodifiableSortedMap(SortedMap<K, ? extendsV> m);

线程平安的Collections

泛型

JDK1.5中,提出一个新的概念,那就是泛型:

泛型其实就是一种参数化的汇合,它限度了太你家进汇合的类型。泛型的实质就是一种参数化的类型。多态能够看作是泛型的机制。一个类继承了父类,那么就能通过它的父类找到对应的子类,然而不能通过其余类来找到具体要找的这个类。泛型的设计之初就是心愿对象或办法具备最宽泛的表达能力。

上面是一个没有泛型的栗子

List arrayList = new ArrayList();arrayList.add("cxuan");arrayList.add(100);for(int i = 0; i< arrayList.size();i++){     String item = (String)arrayList.get(i);     System.out.println("test = ", item);}

因为Integer类型不能强行转换为String类型所以会报谬误:

java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

用泛型改写:

List<String> arrayList = new ArrayList<String>();arrayList.add(100);

泛型的应用

泛型很多用法,用好泛型很牛

用泛型示意类

泛型能够加在类下面,来示意这个类的类型

//此处T能够随便写成任何标识public class GenericDemo<T>{ //value 这个成员变量的类型为T,T的类型由内部指定    private T value;        public GenericDemo(T value) {        this.value = value;    }        public T getValue(){ //泛型办法getKey的返回类型为T,T的类型由内部制订        return value;    }        public void setValue(T value){        this.value = value    }}

用泛型标识接口

泛型接口与泛型类的定义及应用基本相同。

//定义一个泛型接口public interface Generator<T>{    public T next();}

个别泛型接口罕用于生成器(generator)中,生成器相当于对象公擦汗惆怅,是一种专门用来创建对象的类。

泛型办法

能够应用泛型来示意办法

public class GenericMethods{    public <T> void f(T x){        System.out.println(x.getClass().getName());    }}

泛型通用符

List是泛型类,为了示意各种泛型List的父类,能够应用类型通配符,类型通配符应用问号(?)示意,它的元素类型能够匹配任何类型。例如:

public static void main(String[] args){    List<String> name = new ArraryList<String>();    List<Integer> age = new ArraryList<Integer>();    List<Number> number = new ArraryList<Number>();    name.add("cxuan");    age.add(18);    number.add(314);    generic(name);    generic(age);    generic(number);}public static void generic(List<?> data){    System.out.println("Test cxuan :" + data.get(0));}

上界通配符<? extends ClassType>该通配符为ClassType的所有子类型。它示意的是任何类型都是ClassType类型的子类。

下届通配符<? super ClassType>改通配符为ClassType的所有超类型,它示意的是任何类型的父类都是ClassType

反射

反射是Java中一个十分重要同时也是一个高级特色,基本上 Spring 等一系列框架都是基于反射的思维写成的。

Java 反射机制是在程序的运行过程中,对于任何一个类,都能晓得它的所有属性和办法;对于任何一个对象,都可能晓得调用它的任意属性和办法,这种动静获取信息以及动静调用对象办法的性能被称为java语言的反射机制。

反射机制次要提供了一下几个性能:

  • 在运行时判断任意一个对象所属的类
  • 在运行时结构任意一个类的对象
  • 在运行时判断任意一个类所有的成员变量和办法
  • 在运行时调用任意一个对象的办法

由此,反射就像是一个掌控全局的角色,不论你程序怎么运行,我都可能晓得你这个类有哪些属性和办法,你这个对象由谁调用。

在java中,应用java.lang.reflect包实现了反射机制。

上面是一个简略的反射类:

public class Person{    public String name;    public int age;        public Person(){        super();    }        public Person(String name, int age){        super();        this.name = name;        this.age = age;    }        public String showInfo(){        return "name=" + name + ", age=" + age;    }}public class Student extends Person implements Study{    public String className;    private String address;        public Student(){        super();    }        public Student(String name, int age, String className, String address){        super(name, age);        this.className = className;        this.address = address;    }        public Student(String className){        this.className = className;    }        public String toString(){        return "姓名:" + name + ",年龄" + age + ",班级" + className + ",住址:" + address;    }        public String getAddress(){        return address;    }        public void setAddress(String address){        this.address = address;    }}public class TestRelect {    public static void main(String[] args){        Class student = null;        try{            student = Class.forName("com.cxuan.reflection.Student");        }catch (ClassNotFoundException e){            e.printStackTrace();        }                //获取对象的所有私有属性        Field[] fields = student.getFields();        for (Fidld f : fields){            System.out.println(f);        }        System.out.println("----------------");        //获取对象所有属性,但不蕴含继承的        Field[] declaredFields = student.getDeclaredFields();        for (Field df : declareFields) {            System.out.println(df);        }                //获取对象的所有公共办法        Method[] methods = student.getmethods();        for (Method m : methods){            System.out.println(m);        }                //获取对象所有办法,但不蕴含继承的。        Method[] declaredMethods = student.getDeclaredMethods();        for (Method dm : declaredMethods){            System.out.println(dm);        }                //获取对象所有的公共构造方法        Constructor[] constructors = student.getConstructors();        for (Contructor c : constructors){            System.out.println(c);        }                //获取对象所有的构造方法        Constructor[] declaredConstructors = student.getDeclaredConstructors();        for (Constructor dc : declaredConstructors){            System.out.println(dc);        }                Class c = Class.forName("com.cxuan.reflection.Student");        Student stu1 = (Student)c.newInstance();        //办法1:实例化默认构造方法,调用set赋值        stu1.setAddress("山东");        System.out.println(stu1);                //办法2:获得全副的构造函数,应用构造函数赋值        Constructor<Student> constructor = c.getConstructor(String.class, int.class, String.class, String.class);        Student stu2 = (Strudent) constructor.newInstance("cxuan", 24, "1班", "山东");        System.out.println(stu2);                /**        *获取办法并执行办法        */        Method show = c.getMethod("showInfo");        //获取showInfo()办法        Object object = show.invoke(stu2);        //调用showInfo()办法    } }

Class类

Field类

Method类

ClassLoader类

枚举

枚举可能是咱们应用次数比拟少的个性,在Java中,枚举应用enum关键字来示意,枚举其实是一项十分有用的个性,能够了解为具备特定性质的类。enum不仅仅java有,CC++也有枚举的概念。

public enum Family{        FATHER,    MOTHER,    SOM,    DAUGHTER;}

如上创立了一个Family的枚举类,它具备4个值,因为枚举类型都是常量,所以都用大写字母来示意。那么enum创立进去了,如何援用?

public class EnumUse{        public static void main(String[] args){        Family s = Family.FATHER;    }}

枚举个性

enum类当创立实现后,编译器会主动为enum增加toString()办法,可能不便显示enum实例的具体名字是什么。除了toString()办法,编译器还会增加ordinal()办法,这个办法用来示意enum常量的申明程序,以及values()办法显示程序的值。

public static void main(String[] args){        for(Family family : Family.values()){        System.out.println(family + ", ordinal" + fmamily.ordinal());    }}

enum能够进行动态导入包,动态导入包能够做到不必输出枚举类名.常量,能够间接应用常量,应用enumstatic关键字能够做到动态导入包。

枚举和一般类一样

枚举和一般类一样,除了枚举中可能方百年快捷的定义常量,咱们日常开发应用的public static final xxxx其实都能够用枚举来定义。在枚举中可能定义属性和办法。

public enum OrdinalEnum{    WEST("live in west"),    EAST("live in east"),     SOUTH("live in south"),    NORTH("live in north");        String description;     OrdinalEnum(String description){        this.description = description;     }        public String getDescription() {         return description;     }        public void setDescription(String description) {         this.description = description;    }        public static void main(String[] args) {         for(OrdinalEnum ordinalEnum : OrdinalEnum.values()){             System.out.println(ordinalEnum.getDescription());         }    }}