zoukankan      html  css  js  c++  java
  • java学习笔记

    Dos基础命令

    更换盼复:d:

    查看当前目录下的文件及文件夹

    进入文件夹 cd 文件名字

    返回上一级 cd...

    清空屏幕:cls

    删除文件:del 文件名

    删除文件夹: rd 文件夹名字

    退出:exit quit

    创建文件:copy nul 文件名.文件类型

    创建文件夹:mkdir 文件夹名

    cmd命令行窗口字符编码切换为UTF-8,命令行中执行:chcp 65001

    JAVA 接口文档package包介绍:D:Program FilesJavajdk1.8.0_241jrelib t.jar

    一、java概述与环境搭建

    1. java1995年有sum Microsystems 推出,经过24年迭代
    2. JAVA的特点是面向对象、简单、跨平台
    3. 将源文件编译成字节码文件(.class),在交与不同平台进行解释执行。
    4. JVM虚拟机、JRE运行环境、JDK开发环境
    5. DOS 命令 (见开头)
    6. 开发步骤

    a) 创建.java源文件

    b) 编写程序(class main 、逻辑代码)

    c) 编译:javac 文件名.java (文件名.后缀名)

    d) 运行:java 类名(无后缀)

    1. 同一个源文件中可以定义多个类
    2. 编译后,每个类都会生成独立的 .class 文件
    3. 一个类中,只能有一个主函数,每个类都可以有自己的主函数。
    4. public修饰的类称为公开类,要求类名必须与文件名称完全相同,包括大小写
    5. 一个源文件,只能有一个public 公开类。

    package 包:

    作用:类似于文件夹,用于管理字节码(.class)文件。

    语法: package 包名;

    位置:包名必须写在源文件的第一行

    带包编译:javac -d . 源文件名.java

    带包运行:java 包名.类名(包名+类名)

     

    采用域名倒置规则:www.baidu.com  -->  com.baidu.www

     

    二、语言基础:

    1. 前置知识:

    什么是内存:内存是瞬时状态下的存储空间,造价高、工业上的设计瓶颈。

    java虚拟机(java程序)默认分配到的物理内存是1/8

    bit -> Byte -> KB -> MB -> GB -> TB -> PB -> EB -> ZB -> YB -> BB -> NB -> DB -> CB -> XB

        2.变量

    变量定义流程:

    声明:数据类型 变量名;

    赋值: 变量名 =

    Java中变量具有严格的数据类型区分

    Java语言中,任何一个值,都有其对应类型。

    整数类型的取值范围:(默认取值为:int)

     

    浮点类型取值范围:(浮点的默认类型:double)

     

    单精度:float 将小数存入变量中时需在数值尾部加入“F”:float p= 12.51F;  否则将会报编译错误;

    近似值:

    float 32bit   1bit 符号位  8bits指数位 23bits尾数位

    double 64bit  1bit 符号位  11bits指数位  52bits尾数位

    布尔类型:

     

    字符类型:

     

    字符转义符:       例;    ’   ...

    字符串:

     

    类型转化:

    同类型转换中,需目标类型大于源类型;

    强制类型转换中(大的往小的里放),可能会出现精度丢失,

    方法:  target a = ( target )b   

    short num =123;

    byte target = (byte)num;

    赋值运算:

    包定义:明确该文件的.calss文件结构,必须放在文件的首行; package p1;

    引入包: import ...

    控制台输入:根据输入的内容进行程序的执行。

    import java.util.Scanner;

    Scanner inputInfo = new Scanner(System.in);

    System.out.println("请输入内容:");

    int num = inputInfo.nextInt();   // 输入类型为int;

    double num = inputInfo.nextDouble();// 输入类型为小数;

    String num = inputInfo.next();// 输入类型为串;

    char num = inputInfo.next().charAt(0);// 输入类型为字符;

     

    implements 接近于类实现某接口(interface)

    定于接口与类的实现:

    public interface People{

    public void say();

    }

    public class Chinese implements People{

    public void say(){

     System.out.print(‘hello’);

    }

    }

    People chinese = new Chinese()

    chinese.sya()

    extends的区别,extends 表示对父类的继承,且一个类只可单一继承,可以实现父类,也可调用父类的方法,而且可以重写覆盖父类定义的方法及属性。

    implements表示对接口的实现,通过接口关键字‘implements’实现,在接口中声明方法,在子类中实现方法。

    当方法需要实现,不可修改,固定为规定的模板时使用implements,只定义接口。而需要被实现,或者可以被修改,拓展性好,用extends ;

    函數:

    概念:实现特定功能一段代码,可反复使用。

    定义语法:

    plublic static void FunctionName(String[] args){

    }

    将需要多次复用的代码,定义在函数中,减少代码量;

    函数定义在类的函数内部,与main 相同层级;

    数值的比较equals():

    java中,进行字符串类型的对比,因字符串为引用地址类型,对比的数据值为内存地址,所以使用“==,将无法获得准确的数值,String.equals() 可对应解决字符串数值比对,其内部源码比对的是源对象,与目标对象的字符长度及每一个下标的数值是否相等;

    String.contentEquals();其作用与equals相同,但是其内部将会区分StringBuilder 类型,然后进行对比。

    a.equals(b);

    a.contentEquals(c);

    返回值与返回值类型:

    函数调用时,一些情况下无需返回结果,另一些情况下则必须返回结果。

    定义语法:

    public static 返回值类型 函数名称(形式参数列表){

    //函数体

    return value;   //返回值

    }

    数组的创建语法:

    //合并数组方法1

    int [] newArr = new int[oldArr.length+newArrList.length];

    System.arraycopy(oldArr, 0, newArr, 0, oldArr.length);

    System.arraycopy(newArrList, 0, newArr, oldArr.length, newArrList.length);

    for(int i = 0 ; i <newArr.length;i++) {

    System.out.print(newArr[i] +" ");

    }

    //合并数组方法2

    int [] newArr = java.util.Arrays.copyOf(oldArr, oldArr.length+newArrList.length);

    System.arraycopy(newArrList, 0, newArr, oldArr.length, newArrList.length);

    for(int i = 0 ; i <newArr.length;i++ ) {

    System.out.print(newArr[i] + " ");

    }

    数组的扩容:

    Java中数组在声明完长度时候是不可改变原数组的长度的,但可以使用获取原数组的长度,创建新数组时,重新设定新数组的数据内容,并添加新的数据,从而达到数组的扩容功能;

    private int[] dilatation(int[] oldArr,int addLenght) {

    return  java.util.Arrays.copyOf(oldArr, oldArr.length+addLenght);

    }

    数组的插入Insert: 将数组指定位置以后的值赋予前一个地址,在将指定位置内容进行覆盖。

    void insert( int position , int data ) {

    if(stack.length == size) {

    stack = dilatation(stack,1);

    }

    for(int i = size;i > position ; i --) {

    stack[i] = stack[i-1];

    }

    stack[position] = data;

    size++;

    }

    可变长参数:

    概念:可接受多个同类实参,个数不限,使用方式与数组相同。

    语法:数据类型: ... 形参名   必须放在参数列表最后,且只能存在一个。

    传入参数与python 方法类似,默认除开形参个数以外的内容,整合封装到... arr 之中。

    数组的排序:

    冒泡排序:相邻的两个数值比较大小,之后进行位置的互换

    java.util.Arrays.sort(arr);     JDK排序

    二维数组创建语法

    先声明,在分配空间:

    数组类型[][] 数组名;

    数组名 = new  数据类型[高维长度][低维长度]

    声明并分配空间:

    数据类型[][] 数据名 = new 数据类型 [高维长度][低维长度]

    声明并赋值:

    数据类型[][] 数据名 = new 数据类型[高维长度][];  //不规则数组,自行new 低维数组;

    声明并赋值:

    数据类型[] 数据名 = {{v1,v2,v3},{v4,v5,v6},{v7,v8,v9}};

    double 类型保留2位小数:

    String.format(“%.2f”,f);

    DecimalFormat df = new DecimalFormat("#0.00")    df.format(f)

    NumberFormat nf = NumberFormat.getNumberInstance();  nf.format(f))

    DoubleFormat f = new DoubleFormat();      f.m1()

    杨辉三角:

    public static int[][] yhArr(int rows ) {

    // 1

    // 1  1

    // 1  2  1

    // 1  3  3  1

    // 1  4  6  4  1

    // 1  5  10  10  5  1

    int[][] arr = new int[rows][];

    for(int i = 0 ; i < rows ;i++ ) {

    arr[i] = new int [i+1];

    for (int j = 0 ; j <= i ; j++) {

    arr[i][j]= (j>0 && i >1 && j!=i)?arr[i-1][j] + arr[i-1][j-1]:1;

    }

    }

    return arr;

    }

    方法的重载

    方法重载(overload)是指方法名称相同,但是形参列表不同(参数类型、参数个数、参数顺序)的方法。调用重载的方法时,Java编译器会根据实参列表寻找最匹配的方法进行调用。

    面向对象的思想里,方法重载就是对象的另一种行为存在多种实现过程,就构成了方法重载。

    在面向对象中,我们还需要学习到方法(覆盖)override

    对象与类:

    程序中的对象:

    类的定义:

    属性:通过变量表示,又称实例变量。

    语法:数据类型  属性名;

    位置: 类的内部,方法的外部。

    方法:通过函数的表示,又称为实例方法。

    语法:

    public 返回值类型 方法名(形参){

    //方法的主体

    }

    类与对象的关系:

    Extends继承中子类的super:

    thissuper:

    thisjava中指向当前实例,当调用this()是指向的是当前类的super()  (只可在无参情况)

    super 指向父类实例;

    多态:

    概念:父类引用产生多种形态,从而产生多态;

    将子类对象当成父类类别看待;

    在子类方法覆盖父类方法之后 ,在父类参数中调用被覆盖的方法时 将自动调用子类方法

    使用父类作为方法形参实现多态,使方法的参数的类型更加广泛。

    使用父类作为方法的返回值实现多态,使方法可以返回不同子类对象。

    向上转型(装箱)

    父类引用中保留真实子类对象,称为向上转型(即多态核心概念)

    Animal pet = new Dog()

    想下转型(拆箱)

    将父类引用中的真是子类对象,强转回子类本身类型,称为向下转型。

    注意:只有转回子类真是类型,才可以调用子类独有的属性和方法。

    Dogs pet = (Dog)pet;

    判断目标是否是某个类的实例,从而进行对应的拆箱:

    pet instanceof Dogs

    个人理解:多态也可以理解为多样,在将父类作为参数或者返回值时,根据类的继承关系,在调用父类时,指向的还是原子类对相关,即父类引用指向子类对象。

    总结复习

    父类的抽象:

    程序中的继承:

    程序中的继承,是类与类之间的特征和行为的赠与或获得。

    两个类之间的继承关系,必须满足is a”的关系。

    java为单继承,一个类只能有一个直接父类,但可以多层继承,属性和方法逐级叠加。

    不可继承:

    访问修饰符:

    方法的覆盖:

    覆盖原则:


    super 关键字:

    super this访问属性:

    super调用父类有参构造

    thissuper

    程序的多态:

    多态中的方法覆盖:

    多态的应用:

    类型转换异常:

    instanceof关键字:

    get/set方法编写:

    关键字:

    abstract 抽象

    什么是抽象:似是而非,像却又不是,具备某种对象的特征,但又不完整。

    抽象类:abstract 修饰类,此类不能New对象。

    Abstract修饰的类,称为抽象类。抽象类意为不完整的累、不够具体的累,抽象类对象无法独立存在,即不能new对象。

    抽象方法:

    抽象类中的抽象方法与interface 接口一样,定义的抽象方法必须要子类全部实现,否则子类就不是完整的实例子类。

    总结:


    @override  方法的覆盖关键字,指覆盖其父级方法,静态方法不可覆盖。

    static 静态:

    static 声明,将在全局方法区,共同声明同一个方法或属性,全局共用。

    静态方法时可以通过类名调用(在调用该方法时,可能从未创建对象)

    JAVA中的方法调用分为两种:

    1. 静态分派(静态方法中,允许参数列表不同的重名方法,指静态方法之间的重载)
    2. 动态分派(在具有继承关系的情况下,调用实例方法时,自底向上查找可用的方法版本,指实例方法的覆盖)

    方法调用指令5个:

    invoke spacial 私有方法、构造方法

    invoke interface 接口方法

    invoke static 调用静态方法

    invoke virtual 调用虚方法()

    invoke dynamic 调用动态链接方法

    静态方法允许直接访问静态成员

    静态方法不能直接访问非静态方法

    静态方法中不允许使用this super关键字

    静态方法可以继承,不能重写,没有多态。

    个人观点为:静态方法属性在初始化时为最优先级,切与其他实例无直接联系,而在动态方法初始完成时,实例方法还未动态生成完成。

    编译器可知,运行期不可变。

    类加载

    JVM首次使用某个类时,需通过CLASSPATH查找该类的 .class文件。

    将查找到的class文件,读取其描述信息,存入内容之中

    加载时机:

    创建对象 创建子类对象 访问静态属性 调用静态方法 Class.forName(“全限定名”);

    final

    概念:最后的,不可更改的

    final可修饰的内容:

    (最终类)

    方法(最终方法)

    变量(最终变量)

    final修饰类:此类不能被继承。

    接口的语法:

    接口相当于特殊的抽象类,定义的方式、组成部分与抽象类相似。

    与抽象类的异同:

    相同:

    可编译成字节码文件。

    不能创建对象。

    可以做作为引用类型。

    具备Object类中所定义的方法。

    不同:

    所有属性都是公开静态常量,隐式默认为:public static final 修饰

    所有方法都是公开抽象方法,隐式默认为:public abstract 修饰

    没有构造方法,公共代码块,静态代码块

    什么是接口:

    微观概念:接口是一种能力和约定。

    接口的定义:代表了某种能力。

    方法的定义:能力的具体要求。

    抽象方法(规定子类必须存在的行为,规范了其行为的具体要求);

    接口是一种能力,接口中的方法就是一种约定。

    经验:JAVA为单继承,当父类的方法种类无法满足子类需求时,可实现接口扩充子类能力。

    接口的规范:

    任何类在实现接口时,必须实现接口中所有的抽象方法,否则此类为抽象类。

    实现接口中的抽象方法时,访问修饰符必须是public.

    接口引用:

    同父类引用一样, 接口也可声明为引用,并指向实现类对象。

    注意: 

    仅可调用接口中所声明的方法,不可调用实现类中独有的方法。

    可强制转回接口的实现类型,从而调用其原有的属性方法。


    接口的多态:

    接口引用,指向实例化接口对象,从而实现接口多态。

    常见关系:

    类与类:

    单继承

    extends:父类名称

    类与接口:

    多实现

    implements 接口名称1,接口名称2,接口名称N

    接口与接口:

    多继承 extends

    父类接口1,父类接口2,父类接口N

    常量接口:

    将多个常用于表示状态或固定值的变量,以静态常量的形式定义在接口统一管理,提高代码可读性。

    枚举(规范了取值的类型):关键字 enumerate

    enum state{

    false,true,or

    }

    谁去Implements 那就是实现者

    谁去new 实现类 那就是使用者

    接口的回调:

    接口回调:先有接口的使用者,后有接口的实现者

    接口的好处

    程序的耦合度降低

    更自然的使用多态。

    设计与实现完全分离。

    更容易搭建程序框架。

    更容易更换具体实现。

    总结:

    内部类的分类:

    成员内部类、静态内部类、局部内部类、匿名内部类

    概念:在一个类内部再定义一个完整的类。

    class  Outer{

    class Inner{

    }

    }

     

    特点:

    编译之后可以生成独立的字节码文件。

    内部内可直接访问外部类的私有成员,而不破坏封装。

    可谓外部类提供必要的内部功能组件。

    成员内部类:

    在类的内部定义,与实例变量、实例方法同级别的类。

    外部类的一个实例部分,成员内部类依赖外部类对象的实现。

     

    当外类、内部类存在重名属性时,会优先访问内部类属性。

    成员内部类无法定义静态成员。

    静态内部类:

    不依赖外部类对象,可直接创建或通过类名访问,可声明静态成员。

     

    局部内部类:

    定义在外部类方法中,作用范围和创建对象范围仅限于当前方法。

    局部内部类访问外部类当前方法中的局部变量时,因无法保障变量的生命周期与自身相同,变量必须修饰为final.

    匿名内部类:

    Object

    getClass()方法

    public final Class<?> getClass(){}

    返回引用对象的实际类型

    应用:通常用于判断两个引用中的实际存储对象类型是否一致

    hashCode()方法

    public int hashCode(){}

    返回一个该对象的十进制的哈希码值

    哈希算法根据对象的地址或字符串或数字计算出来的int类型的数值

    哈希码并不是唯一,可保证相同对象返回相同的哈希码,尽量保证不同对象返回不同的哈希码。

    toString()方法

    public String toString(){}

    返回该对象的字符串表现形式

    可以根据程序需要覆盖该方法,如展示对象各个属性值。

    equals()方法

    public boolean queals(Object obj){}

    默认实现为(this == obj) , 比较两个对象地址是否相同。

    可进行覆盖,比较两个对象的内容是否相同。

    equals() 方法的覆盖步骤:

    public boolean equals(Student obj){

    if(this == obj){

    return false ;}

    if(obj== null){

    return false; }

    if(this.getClass() != obj.getClass(){

    return false}

    if(this.name.equals(s.name) && this.age == s.age &&this.sex.equals(s.sex){

    return true}

    return false;

    }

    finalize()方法

    当对象被判定为垃圾对象时,由JVM自动调用此方法,用以标记垃圾对象,进入回收队列。

    垃圾对象:没有有效的引用指向此对象时,为垃圾对象。

    垃圾回收:有GC销毁垃圾对象,释放数据存储空间。

    自动回收机制:JVM的内存耗尽,一次性回收所有垃圾对象。

    手动回收机制:使用System.gc();通知JVM执行垃圾回收。

    可达性分析算法

    包装类:

    什么是包装类?

    基本数据类型所对应的引用数据类型

    Obect 可统一所有数据,包装类的默认值是null

    包装类对应:

    类型转换与装箱、拆箱

    8种包装类提供不同类型间的转换方式:

    Number父类中提供的6中共性方法;floatValuedoubleValuebyteValue....

    parseXXX()静态方法;parseIntparseDouble....

    valueOf()静态方法: intValueOfdoubleValueOf....

    通过包装累继承得来的XXX ValueOf()方法,进行各类型之间的转换;

    注意:需保证类型兼容(取值范围兼容、值类型兼容),否则抛出NumberFormatException异常


    整数缓存区:

    Java预先创建了256个常用的整数包装类型对象。

    在实际应用当中,对已创建的对象进行复用。

    String:

    字符串为常量,创建之后不可改变

    字符串字面存储在字符串中,可以共享

    String s = “hello”; 产生一个对象,字符串池中存储。

    String s = new String(“Hello”);  产生两个对象,池 与  堆 中各一个。

    字符串实际是字符数组的包装类;

     

    常用方法:

    string.charAt(0)  通过下标获取字符串字符。

    contains(String str): 判断当前字符串中是否包含str

    toCharArray() : 将字符串转换成数组。

    indexOf(String str fromIndex i): 查找str首次出现的下标,存在,返回下标值;不存在返回-1, 第二个参数为从下标i起始查询;

    length() :返回串的长度;

    trim() :去掉串前后的空格;

    toUpperCase():将小写统一转为大写;

    toLowerCase():将大写统一转为小写;

    str1.equalsIgnoreCases(str2): 忽略大小写判断俩个串内容是否相同;

    endsWith() :判断串是否已指定内容结尾;

    startsWith() :判断串是否已指定内容开头;

    replace():替换新内容;

    Substring() :截取指定下标范围的内容;

    StringBuffer:构造一个其中不带字符的字符串缓冲区,初始容量为16个字符,运行效率慢、线程安全。

    线程安全的可变字符序列。一个类似于String的字符串缓冲区,但不能修改,虽然在任意时间点上他都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。

    StrintBuffer sb1 = new StringBuffer(“xxx”);

    public String toString(); 返回串

    StringBuilder:构造一个其中不带字符的字符串缓冲区,初始容量为16个字符,运行效率快、线程不安全。

    一个可变的字符序列。此类提供一个与StringBuffer兼容的API,但不保证同步。该类被设计用作StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用的时候。建议优先采用该类,在多数情况下,StringBuilder更快。

    StringBuilder sb2 = new StringBuilder(“xxx”);

    StringBuilderStringBuffer所有API基本相同;只是运行效率不同。


    BigDecimal 精确计算

    不可变的,任意精度的有符号十进制数。

     

    加:BigDecimal result = bg1.add(bg2);

    减:BigDecimal result2 = bg1.subtract(bg2);

    乘:BigDecimal result3 = bg1.multiply(bg2);

    除:BigDecimal result4 = bg1.divide(bg2, 2,BigDecimal.ROUND_UP);

    只有除法精确计算是需要添加保留位数,及取上或取下;

     

    集合

    概念:对象的容器,存储对象的对象,可代替数组。

    特点:容器的工具类,定义了对多个对象进行操作的常用方法。

    位置:java.util.*;

    Collection体系集合:

     

    特点:代表一组任意类型的对象,无序、无下标

    Collection层次结构中的根接口,Collection表示一组对象,这些对象也可称为Collection的元素,一些collection允许有重复的元素,而另一些则不允许。

    方法:

    boolean add(Object obj) 添加一个对象

    boolean addAll(Collection c)  讲一个集合中的所有对象添加到此集合中

    void clear() 清空所有对象

    boolean contains(Object o ) 检查此对象是否包含该对象

    boolean equals(Obejct o) 比较此集合与指定对象是否相等

    boolean isEmpty() 判断此结婚是否为空

    boolean remove(Object o) 在此集合中移除o对象

    int size() 返回此集合中的元素个数。

    Object[] toArray() 将此集合转换为数组。

    List 子接口

    特点:有序、有下标、元素可重复

    说明:有序的collection,此接口的用户可以对列表中每个元素的插入位置进行精确控制。用户可以根据元素的整数索引访问元素,并搜索列表中的元素。

    set不同,列表通常允许元素重复

    方法:

     

     

    List 实现类:

    ArrayList

    数据结构实现,查询快、增删慢;

    JDK1.2版本,运行效率快,线程不安全。

    Vector(使用方法与ArrayList相同,目前暂不建议使用):   

    数组结构实现,查询快、增删慢;

    JDK1.0版本,运行效率慢、线程安全。

    LinkedList:

    链表结构实现,增删快,查询慢。

    linklist接口的链接列表实现,实现所有可选的列表操作,并且允许元素(包括Null,除了实现List接口外,LinkedList类还未列表的开头及结尾getremoveinsert元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列。

    LinkedList 因是队列链式结构,开头与结尾的查询功能效率很高,所以添加了一些对应的方法

    list.addFirst()list.addLast()list.peekFirst()list.peekLast()list.removeFirst()list.removeLast();

     

    泛型集合:

    概念:参数化类型、类型安全的集合,强制集合元素的类型必须一致。

    特点:

    编译时即可检查,而非运行时抛出异常。

    访问时,不必类型转换(拆箱)。

    不同泛型之间引用不能相互赋值,泛型不存在多态。


    实例泛型:

    如果是泛型类,在创建对象的时候指明泛型类型;

     

    如果是泛型接口,在实现接口的是后指明泛型类型;

    静态泛型:

     

     

    Collections泛型集合

    概念:集合工具类,定义了除了存取以外的集合常用方法。

    方法:

    public static void reverse(List<?> list) 反转集合中的元素顺序

    public static void shuffle(List<?> list) 随机重置集合元素的顺序

    public static void sort(List<?> list) 升序排序(元素类型必须实现Comparable接口)

    Comparable<?> 排序接口  须实现其compareTo方法

    Set 集合

    特点:无序、无下标、元素不可重复

    方法:全部继承自Collection的所有方法

    Set的实现类:

    HashSet【重点】:

    基于HashCode实现元素不重复。

    当存入元素的哈希码相同时。会调用equals进行确认,如结果为true,则拒绝后则的存入。

    遍历HashSet的方法为foreach循环:

    for遍历写法:

    for(Student i : list)

    System.out.println(i.age);

    TreeSet:

    基于排列顺序实现元素不重复。

    实现了SortedSet接口,对集合元素自动排序。

    元素对象的类型必须实现Comparable接口,指定排序顺序

    通过CompareTo方法确定是否为重复元素。

    使用TreeSet集合时,实现接口Comparable,之后针对性重写compareTo方法,否则排序去重不能达到理想效果。

    @Override

    public int compareTo(Teacher o) {

    // TODO Auto-generated method stub

    if(salary > o.salary ) {

    return 1;

    }else if(salary < o.salary ) {

    return -1;

    }else {

    if(name.compareTo(o.name)>0) {

    return 1;

    }else if( name.compareTo(o.name)<0) {

    return -1;

    }else {

    return 0;

    }

    }

    }


    Map体系集合

    map接口的特点:

    1. 用于存储任意键值对(Key - Value
    2. 键:无序、无下标、不允许重复(唯一)
    3. 值:无序、无下标、允许重复

     

     

    接口Map<K , V>

    public interface Map<K , V>  : 将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。

    特点:一对数据(KEY-Value),无序、无下标,键不可重复,值可重复。

    方法:

    V put(K key , V value) 将对象存入到集合中,关联简直。Key重复则覆盖原值。

    Object get(Object key) 根据键值获取对应的值。

    Set<K> keySet 返回所有Key内容的set集合。

    Collection<V> values()  返回包含所有ValueCollection集合。

    Set<Map.Entry<K,V>> entrySet() 键值匹配的Set集合

    HashMap【重点】:线程不安全,运行效率快,允许用Null 作为Key 或者value

    基于哈希标的Map接口的表现。此实现提供所有可选的映射操作,并与允许使用Null值和null键。(除了非同步和允许使用Null之外,HashMap类与Hashtable大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。

    方法:listMap.containsKey(str)  查询map中是否有已存在的Key

    HashTable:GDK1.0, 线程安全,运行效率慢,不允许使用null 作为key或者value;

    Set<String> set = Country.countres.keySet(); 

    Collection<String> values = Country.countres.values();

    Set<Entry<String, String>> entry = Country.countres.entrySet();

    for(Entry<String, String> i : entry)

    System.out.println(i.getKey());

    Properties: HashTable的子类,要求Keyvalue都是String.通常用于配置文件的读取。

    Properties properties =  new Properties();

    properties.setProperty("aaa", "bbbb");

    properties.getProperty("aaa");

    TreeMap:

    实现了SortedMap接口(是MAP的子类),可以对Key自动排序。

    Map<String, String> treeMap = new TreeMap<String, String>();

    treeMap.put("CN1", "现在的年轻人");

    该方法同样存在values() keySet() entrySet() 三个角度试图

     

    总结:

    异常

    概念:程序在运行过程中出现的特殊情况。

    异常处理的必要性:任何程序都可能存在未知问题、错误;如果不对这些问题进行正确处理,则可能导致程序的中端,造成不必要的损失。

    Throwable:可抛出的,一切错误和异常的父类,位于java.lang包内。

    Erro: JVM、硬件、执行逻辑错误,不能手动处理。

    Exception: 程序在运行和配置中产生的问题,可处理。

    RuntimeException:运行时异常,可处理,可不处理。

    CheckedEception:受查异常,必须处理。

    自动抛出异常:当程序在运行时遇到不符合规范的代码时。

    手动抛出异常:语法  throw new 异常类型(“实际参数”;

    产生异常结果:相当于遇到return语句,导致程序因异常而终止。

    异常的传递:throws  声明异常,修饰符在方法参数列表后端。

    受查异常:throws 声明异常,修饰在方法参数列表后端。

    运行时异常:行时异常,可处理,可不处理.


    try {

    s1.setAge(12);

     (可能出现的异常代码)

    } catch (Exception e) {

    // TODO: handle exception

    e.printStackTrace();  //打印堆栈中出错的内容

      (相关代码的自定义处理方案,如:getMessage()printStackTrace());

    }finally{

    (无论是否出现异常,都会执行finally里的语句)

    }

    自定义异常

    需继承自ExceptionException的子类,常用的RuntimeException.

    必要提供的构造方法:

    无参数构造方法

    String message 有参构造方法

    方法覆盖:

    带有异常声明的方法覆盖:

    方法名、参数列表、返回值类型必须和父类相同。

    子类的访问修饰符合父类相同或是比父类更宽。

    子类中的方法,不能抛出比父类更多、更宽泛的异常。

    总结:

     

     

    • List:有序集合,元素可重复
    • Set:不重复集合,LinkedHashSet按照插入排序,SortedSet可排序,HashSet无序
    • Map:键值对集合,存储键、值和之间的映射;Key无序,唯一;value 不要求有序,允许重复

    Collections包下的unmodifiableXXX方法,通过这个方法返回的mapListSet,是不可以修改的

    Collections.unmodifiableMap(Map)

    Collections.unmodifiableList(List)
    Collections.unmodifiableSet(Set)

    public static void main(String[] args) {

    List<Character> oldList = new ArrayList<Character>();

    for (char i = 'A'; i < 'Z'; i++) {

    oldList.add(i);

    }

    List<Character> unChangeList = Collections.unmodifiableList(oldList);

    测试过后:调用addremove方法均会抛出错误java.lang.UnsupportedOperationException
    线程

    单词:  Runnable 可运行 就绪状态 可运行状态 就绪

    什么是进程:

     

    什么是线程:

     

    线程的组成:

     

    启用线程的方法:

    方法1

    class MyThread extends Thread{

    @Override

    public void run() {

    for (int i = 0; i < 100; i++) {

    System.out.println("线程1 "+Thread.currentThread().getId()+":"+i+"已开启");

    }

    }

    }

    MyThread myThread = new MyThread(null);

    myThread.start();

    方法2

    class PrimeRun implements Runnable{

    @Override

    public void run() {

    // TODO Auto-generated method stub

    for (int i = 0; i < 100; i++) {

    System.out.println("线程id: "+Thread.currentThread().getId()+"-"+i+"已开启");

    }

    }

    }

    PrimeRun primeRun = new PrimeRun();

    PrimeRun p2 = new PrimeRun();

    p2.start();

    线程的状态(基本)

     

     

    方法:

    休眠: public static void sleep( long millis)  当前线程主动休眠 millis毫秒。

    放弃:  public static void yield()  当前线程主动放弃时间片,会到就绪状态,竞争下一次时间片。

    结合:  public final void join() 允许其他线程加入当前线程中,并优先执行。

    线程的状态(等待):

     

    线程的安全问题:

     

    需求:A线程将“HELLO”存入数组的第一个空间;B线程将“World”存入数组的第一个空位。

    线程不安全:

    当多线程并发访问临界资源时,如果破坏原子操作,可能造成数据不一致。

    临界资源:共享资源(同一个对象),一次仅允许一个线程使用,才可保证其正确性。

    原子操作:不可分隔的多步操作,被视为一个整体,其顺序和步骤不可打乱或缺省。

    同步方式(1

    同步代码块:

    synchronized临界资源对象{ //对离临界对象资源加锁

    //代码块

    }

    注:

    每个对象都有一个互斥锁标记,用来分配给线程的。

    只有拥有对象互斥标记的线程,才能进入对该对象加锁的同步代码块。

    线程退出同步代码块时,会释放相应的互斥锁标记。

     

    线程的状态(阻塞)

     

     

    同步的规则:

     


    线程的通知:

    等待:

    public final void wait();

    public final void wait(long timeout);

    必须在堆obj加锁的同步代码块中。在一个线程中,调用obj.wait()时,此线程会释放拥有的所有锁标记。同时此线程处在无限期等待的状态中,释放锁,进入等待队列。

    通知:

    public final void notify();

    public final void notifyAll();

    必须在堆obj加锁的同步代码块中,从objWaiting中释放一个或全部线程。对自身没有任何影响。

    经典问题:

     

    关键字:synchronized  或者同步代码块 synchronized(){///}

    总结:

     

    守护线程:thread.setDaemon(true);守护线程拥有自动结束自己生命周期的特性,而非守护线程不具备这个特点

    通常来说,守护线程经常被用来执行一些后台任务,但是呢,你又希望在程序退出时,或者说 JVM 退出时,线程能够自动关闭,此时,守护线程是你的首选。


    Runtime.getRuntime().addShutdownHook(

    new Thread(()-> System.out.println("The jvm exit Success!"))

    );  //查看java虚拟机退出时机

    Thread thread = new Thread(()->{//创建线程

    while(true) { //不断执行

    try {

    Thread.sleep(1000);

    System.out.println("I am running~~");

    } catch (Exception e) {

    e.printStackTrace();

    // TODO: handle exception

    }

    }

    }) ;

    thread.setDaemon(true);//设置守护线程

    thread.start();

    try {

    thread.sleep(2000);

    } catch (InterruptedException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }finally {

    System.out.println("main thread to exit!"); //打印主线程结束时机

    }


    线程池概念

    现有问题:

    线程是宝贵的内存资源、单个线程约1MB空间,过多分配易造成内存溢出。

    频繁的创建及销毁线程会增加虚拟机回收效率、资源开销,造成程序性能下降。

    线程池:

    线程容器,可设定线程分配的数量上限。

    将预先创建的线程对象存入池中,并重用线程池中的线程对象。

    避免频繁的创建和销毁。

     

    将任务提交给线程池,由线程池分配线程、运行任务,并在当前任务结束后复用线程。

    获取线程池
    常用的线程池接口和类(所在包 java.util.concurrent:

    Executor:线程池的顶级接口。

    ExecutorService:线程池接口,可通过submit(Runnable task) 提交任务代码。

    Executors工厂类:通过此类可以获得一个线程池。

    通过newFixedThreadPool(int nThreads) 获取固定数量的线程池。参数:指定线程池中线程的数量。

    通过newCachedThreadPool() 获得动态数量的线程池,如不够则创建新的,没有上线。

    ExecutorService serve = Executors.newFixedThreadPool(3);   //调用固定线程池

    ExecutorService serve = Executors.newCachedThreadPool();   //调用缓存线程池

    Runnable task = new MyTask();  //生成任务

    erve.submit(task); //执行

     

     shutdown();结束所有线程。

       isTerminated(); 判断所有线程是否结束;

    Callable接口

    public interface Callable<V>{

    public V call{} throws Exception;

    }

    JDK5加入,与Runnable接口类似,实现之后代表一个线程任务。

    Callable具有泛型返回值、可以声明异常。

    Future<V>接口

    概念:异步接受ExecutorService.submit()所返回的状态结果,当中包含了call()的返回值。

    V  代表futureget方法返回的结果类型,get方法以阻塞形式等待Future中的异步处理结果(call())

    Future代表异步计算的结果,他提供了检查是否完成线程,及等待计算结果,并获取计算的结果。

     

    接口实现:

    class CallTask implements Callable <Integer>{

    @Override

    public Integer call() throws Exception {

    int value = 1 ;

    for(int i = 0 ; i < 10 ; i++ ) {

    value += i;

    System.out.println("task"+Thread.currentThread().getId()+": "+i);

    };

    return value;

    }

    }

    调用:

    ExecutorService serve = Executors.newCachedThreadPool();

    Callable<Integer> task = new CallTask();

    Future<Integer> result = serve.submit(task);  //返回Future类型结果;

    result.get(); //获得返回的结果;

    同步:

    形容一次方法调用,同步一旦开始,调用者必须等待该方法返回,才能继续。

    异步:

    形容一次方法调用,异步一旦开始,像是一次消息传递,调用者告知之后立刻返回。二者竞争时间片,并发执行。

     

    Lock接口

    JDK5加入,与synchronized比较,显示定义,结构更灵活。

    提供更多使用性方法,功能更强大、性能更优越。

    常用方法:

    void lock() //获取锁,如锁被占用,则等待。

    boolean tryLock()   //尝试获取锁(成功返回true.失败返回false,不阻塞)

    void unlock()   //释放锁

     

    重入锁

    ReentrantLock:Lock接口的实现类,与synchronized一样具有互斥锁功能。

     

    读写锁

    ReentrantReadWriteLock:

    一种支持一写多读的同步锁,读写分离,可分别分配读锁、写锁。

    支持多次分配读锁,使多个操作可以进行。

    互斥规则:

    -写:互斥,阻塞。

    -写:互斥,读阻塞写、写阻塞读。

    -读:不互斥、不阻塞。

    在读操作远远高于写操作的环境中,可以保障线程安全的情况下,提高运行效率。

     

    线程安全的集合

    Collection集合体系下,除Vector 以外的线程安全集合。

     

    Collections中的工具方法

    Collections工具中提供了多个可以获得线程安全集合的方法。

     

    JDK1.2提供,接口统一,维护性高,但性能没有提升,均已synchronized实现

    CopyOnWriteArrayList

    ArrsyList的一个线程安全辩题,其中所有可变操作(addset等等) 都是通过对底层数据进行一次新的复制来实现。

    线程安全的ArrayList,加强版读写分离。

    写有锁,读无锁,读与写之间不阻塞,优于读写锁。

    写入时,先copy一个容器副本、在添加新元素,最后替换引用。

    使用方法与ArrayList无异。

     

    接口引用,更容易实现更换引用类   List list = new CopyOnWriteArrayList(); =>  List list = new ArrayList()  更换子类无差异。

    CopyOnWriteArraySet

     

    ConcurrentHashMap

    初始容器默认为16段(Segment,使用分段锁设计。

    不对整个Map加锁,而是为每个Segment加锁。

    当多个对象存入同一个Segment时,才需要互斥。

    最理想状态为16个对象分别存入16Setment,并行数量16.

    使用方式与HashMap无异。

     

    总结

     

    线程池概念

     

    获取线程池

     

     

    CopyOnWriteArrayList

     

    CopyOnWriteArraySet


    Queue接口(队列)

    Collection的子接口,表示队列FIFOFirst In First Out

     

    ConcurrentLinkedQueue;

    Queue的一个线程安全的队列。

    线程安全、可高效率都城的队列,高并发下性能最好的队列。

    无锁、CAS (compare and Swap)比较交换算法,修改的方法包含三个核心参数(V,E,N)   

    V:要更新的变量、E:预期值、N:新值。

    只有当V==EV=N;否则表示内容已经被更新过,则取消当前操作。

     

    BlockingQueue接口(阻塞队列)

    Queue的子接口,阻塞的队列,

    阻塞队列

    ArrayBlockingQueue:

    数组结构实现,有界限列。(手工固定上线)

     

    LinkedBlockingQueue:

    链表结构实现,无界队列。(默认上线Integer.MAX_VALUE

     

    总结:

    什么是流

    概念:内存与存储设备之间传输数据的通道。

     

    流的分类

    按方向【重点】:

    输入流:将<存储设备>中的内容读入到<内存>中。

    输出流:将<内存>中的内容读入到<存储设备>中。

     

    按单位:

    字节流:以字节为单位,可以读写所有数据。

    字符流:吃字符为单位,只能读写文本数据。

    按功能:

    节点流:具有实际传输数据的读写功能。

    过滤流:在节点流基础上增强功能。(装饰器、装饰类)

    字节流:

    过字节流的父类(抽象类):

    InputStream:字节输入流;  此抽象类是表示字节输入流的所有类的超类。

     

    OutputStream:字节输出流;  此抽象类是表示输出字节流的所有类的超类。

     

    FileOutputStrean:

    public void write(byte[] b )   一次写多个字节,将b数组中所有字节,写入输入流。

    FileOutputStream output = new FileOutputStream("Files\test1.txt");

    for (int i = 'a'; i < 'z'+1; i++) {

    output.write(i);

    }

    byte[] bs = new byte[] {65,66,67,68,69,70};

    output.write(bs,1,3);  

    FileInputStream:

    public int read(byte[] b  从流中读取多个字节,将读到内容存入b数组中,返回实际读到的字节数;如果达到文件的尾部,则返回-1;

    FileInputStream input = new FileInputStream("Files\test1.txt"); // 创建输入流

    byte[] cache = new byte[1024*256]; //设置缓存数组大小

    for (int i = 0; ;) {  // 循环  或者 while true

    int n = input.read(cache);  // 读取数据并缓存入cache

    if(n == -1) {break;}; // 退出循环条件

    for (int j = 0; j < n; j++) {  //打印读取到的数据

    System.out.print((char)cache[j] + " ");

    }

    System.out.println();

    }

    字节过滤流:

    缓冲流:BufferedOutputStream / BufferedInputStream

    提高IO效率,减少访问磁盘的次数。

    数据缓存在缓冲区,flush是讲缓存区的内容写入文件中,也可以直接close

     

    OutputStream os = new FileOutputStream("Files\buffertest.txt"); //节点流

    BufferedOutputStream bos = new BufferedOutputStream(os); //过滤流

    bos.write('X');  //写入缓存之中

    bos.flush();  //刷新缓冲(将缓冲中的数据,一次性写入文件中,并清空缓冲区)

    bos.close();  // 级联执行flush()

    BufferedInputStream 输入流的使用方法与建立数组缓存相同,且缓存大小默认为8192

    InputStream fps = new FileInputStream("Files\buffertest.txt");

    BufferedInputStream bis = new BufferedInputStream(fps);

    while (true) {

    int s = bis.read();

    if(s == -1) {

    break;

    }

    System.out.print((char)s+" ");

    }

    对象过滤流:

    ObjectOutputStream / ObjectInputStream

     

    使用流传输对象的过程称为序列化、反序列化。

     

    因为String等常用类型 父类已实现接口 Serializable 所以可以直接使用序列化存储功能

    当文件读取到尾部时,使用EOFException作为终止循环判断条件:

    InputStream ips = new FileInputStream("Files\object.txt");

    ObjectInputStream oiStream = new ObjectInputStream(ips);

    while (true) {

    try {

    Student student = (Student) oiStream.readObject();

    System.out.println(student.toString());

    } catch (EOFException e) {

    break;

    }

    }

    字符编码

     

    当编码方式和解码方式不一致时,会出现乱码

    字符流

    字符流的父类(抽象类):

    Reader:字符输入流,用于读取字符流的抽象类。

    Writer:字符输出流,写入字符流的抽象类。

    FileWriter:

    public void write(String str)  一次写多个字符,将b数组中所有字符,写入输出流。

    Writer writer = new FileWriter("Files\writeIndex2.html");

    writer.write(cache);

    writer.close();

    FileReader:

    public int read(char[] c) 从流中读取多个字符,将读到的内容存入c数组,返回实际读到的字符数;如果达到文件的尾部,则返回-1

    char[] cache = new char[1024*128];

    Reader read = new FileReader("Files\index.html");

    int n = 0;

    while (true) {

    n = read.read(cache);

    if(n == -1) {break;};

    }

    字符过滤流

     

    字符节点流

     

    使用步骤:

    创建节点流

    [创建过滤流 设置字符编码集]

    封装过滤流

    读写数据

    关闭流

     

     

    总结:

     

    File

    概念:代表物理盘符中的一个文件夹或文件。

     

    listFiles( fileFilter ) 方法:

    该方法无参数时将返回所在文件目录下的所有文件,加入参数时,参数将实现接口 FileFilter,并覆盖方法accept(File file)

    for (File string : dirFile.listFiles(new myFilter())) { System.out.println(string); }

    class myFilter implements FileFilter{

    @Override

    public boolean accept(File file) { //自定义判断条件,通过返回true,不通过false;

    if(file.isFile()&& file.getName().endsWith(".html")) {

    return true;

    }

    return false;

    }}

    什么是网络

    由点和线构成,表示诸多对象间的相互联系。

    什么是计算机网络

    为实现资源共享和信息传递,哦谈过通信线路连接起来的若干主机(Host

    互联网:(Internet)点与点相连。

    万维网:www world wide web 端与端的相连

    物联网:IOT  internet of things 物与物相连

    网络编程:让计算机与计算机之间建立连接、进行通信。

    网络模型:

    OSIoper system interconnection) 开放式系统互联

     

    第一层:物理层为设备之间的数据通信提供传输信号和物理介质。(双绞线、光导纤维)。

    第二层:链路层在物理层上,通过规程或协议(差错控制)来控制传输数据的正确性,MAC

    第三层:网络层负责定义了能够表示所有网络节点的逻辑地址。(IP地址)

    第四层:传输层负责是否选择差错恢复协议、数据流重用、错误顺序重排,(TCPUDP

    第五层:会话层负责使用应用建立和维持会话,是通信在失效时继续恢复通信(断点续传)

    第六层:表示层负责定义转换数据格式及加密,允许选择以二进制或ASCII 格式传输。

    第七层:应用层负责文件访问和管理,可靠运输服务、远程操作服务。(HTTPFTPSMTP)

    TCP/IP模型

    一组用于实现网络互联的通信协议,将协议分成四个层次。

     

    第一层:接口层负责建立电路连接,是整个网络的物理基础,点醒的洗衣包括以太网、ADSL等等。

    第二层:网络层负责分配地址和传送二进制数据,主要协议是IP协议。

    第三层:传输层负责传送文本数据,主要是协议是TCPUDP协议。

    第四层:应用层负责传送各种最终形态的数据,是直接与用户打交道的层,典型协议是HTTPFTP等。

     

     

    IP:

     

     


    Port:

     

    InetAddress

     

     

     

    基于TCP的网络编程

    Socket编程:

    Socket(套接字)是网络中的一个通信节点。

    分为客户端Socket与服务器ServerSocket.

    通信要求:IP地址 + 端口号。

    开发步骤:

     

    类对象

    类的对象:基于某个类 new出来的对象,也称为实例对象。

    类对象:类加载的产物,封装了一个类的所有信息(类名、父类、接口、属性、方法、构造方法)

     


    获取类对象

    通过类的对象,获取类对象

    Student s = new Student();

    Class c = s.getClass();

    通过类名获取类对象

    Class c = 类名.class

    通过静态方法获取类对象

    Class c = Class.forName(“包名.类名”);

    工厂设计模式

    通开发中有一个非常重要的原则是“开闭原则”,对拓展开放、对修改关闭。

    工厂模式主要负责对象创建的问题。

    可通过反射进行工厂模式的设计,完成动态的对象创建。

    使用反射创建类:

    Class c = Teacher.class;

    Teacher s2 = (Teacher)c.newInstance();

    s2.name = "joba";

    // 构造新对象

    Teacher s4 = (Teacher)createObject("Teacher");

    // 获得新对象的类型

    Class<? extends Teacher> c4 = s4.getClass();

    // 通过类型获得类方法

    Method m = c4.getMethod("exam" , int.class);

    // 执行有参方法,传入参数

    Object result = m.invoke(s4 , 80);

    // 打印返回的结果

    System.out.println(result);

    如果方法为私有方法  需使用

    Method m = c4.getDeclaredMethod("calc", Double.class);

    m.setAccessible(true);

    m4.invoke(m, 100D);

    单例模式

    单例(Singleton: 只允许创建一个该类的对象。(天生线程安全)

    创建单例对象所获得的对象为同一个:

    1.饿汉式:天生线程安全、类加载创建(不好,不用的时候也被迫创建,占用一点点资源)

    Singleton s = Singleton.getInstance();

    System.out.println(s);  //singleton_16.Singleton@15db9742

    Singleton s1 = Singleton.getInstance();

    System.out.println(s1); //singleton_16.Singleton@15db9742

    class Singleton{

    private static final Singleton instance = new Singleton();

    private Singleton() {};

    public static Singleton getInstance() {

    return instance;

    }

    }

    2.懒汉式:使用时在创建、天生线程不安全(加锁)

    class Singleton{

    private static Singleton instance = null;

    private Singleton(){}

    public static Singleton getInstance() {

    if(instance == null) {

    instance = new Singleton();

    }

    return instance;

    }

    }

    3.懒汉式:用时在创建、天生线程安全

    class Singleton{

    private Singleton(){}

    private static class Holder{

    static final Singleton instance = new Singleton();

    }

    public static Singleton getInstance() {

    return Holder.instance;

    }

    }

    总结:

     

  • 相关阅读:
    java上传视频文件
    java+HTML5实现断点续传
    web+上传大文件断点续传
    javaweb项目断点续传
    CKEditor从word粘贴问题
    netback的tasklet调度问题及网卡丢包的简单分析
    linux下开启ftp的21号port
    Dubbo--简单介绍
    OpenCV2马拉松第15圈——边缘检測(Laplace算子,LOG算子)
    【打CF,学算法——一星级】Codeforces Round #313 (Div. 2) A. Currency System in Geraldion
  • 原文地址:https://www.cnblogs.com/bomdeyada/p/14356566.html
Copyright © 2011-2022 走看看