爆肝!!!!JavaSE知识点1.3w字总结

爆肝!!!!JavaSE知识点1.3w字总结

Java基础语法知识

关键名词

jdk

jdk(java development kit),即Java开发工具集。java

  • SUN公司为JDK工具包提供了一整套文档资料,咱们习惯上称
    之为JDK文档。
  • JDK文档中提供了Java中的各类技术的详细资料,以及JDK中提
    供的各类类的帮助说明 。
  • JDK文档是Java语言的完整说明,大多数书籍中的类的介绍都
    要参照它来完成,它是编程者常常查阅的资料。

jre

jre(java runtime enviroment),即Java运行环境编程

jvm

jvm(java virtual machine),Java虚拟机。目前主要使用的式hotsopt。小程序

Java历史

sun公司

  • 美国SUN(Stanford University Network)公司
  • 在中国大陆的正式中文名为“太阳计算机系统(中国)有限公司”
  • 在台湾中文名为“升 阳电脑公司”。

Java为何被发明

  • Green项目设计模式

  • 应用环境:像电视盒这样的消费类电子产品数组

  • 要求:安全

    • 语言自己是中立的,也就是跨平台
  • 发明者:James Gosling服务器

  • 历程:网络

▪ 1991年,Sun公司的Green项目,Oak
▪ 1995年,推出Java测试版
▪ 1996年,JDK1.0
▪ 1997年,JDK1.1
▪ 1998年,JDK1.2,大大改进了早期版本的缺陷,是一个革命性的版本,改名为Java2
▪ 1999 Java被分红J2SE、J2EE 和J2ME,JSP/Servlet技术诞生
▪ 2004年,J2SE 5.0 (1.5.0) Tiger老虎.为了表示这个版本的重要性,J2SE1.5改名为J2SE5.0。
▪ 2006年,J2SE 6.0 (1.6.0) Mustang野马.此时,Java的各类版本被改名,取消其中的数字"2":J2EE改名为Java EE, J2SE改名为
Java SE,J2ME改名为Java ME
▪ 2009年4月20日甲骨文收购Sun公司,交易价格达74亿美圆
▪ 2011年,JavaSE7.0
▪ 2014年 ,JavaSE8.0
▪ 2017年,JavaSE9.0
▪ 2018年3月,JavaSE10.0
▪ 2018年9月,JavaSE11.0
▪ 2019年3月,JavaSE12.0数据结构

第一个Java程序

public class Test{
    public static void main(String[] args){
        System.out.println("hello, world");
    }
}

标识符

定义

用来给类、变量、方法、对象等起的名称。由于在Java中一切皆对象,故不存在函数这一说,只有方法多线程

规则

  • 首字母能够是字母、下划线、美圆符号,可是不能是数字

    • // 合法
      int a; 
      int _a;
      int A;
      int $a;
      // 不合法
      int 1a;
  • 其余部分只能是字母、下划线、数字、美圆符号

    • // 合法
      int a1_$;
      // 不合法
      int a-1;
  • Java严格区分大小写

    • int a;
      int A;
      // a和A不是同一个变量
  • Java命名变量的时候建议采用驼峰标识以及变量要见名知意

    • // 建议
      String name;
      int age;
      boolean isAlive;
      // 不建议
      String s;
      int a;
      boolean b;

保留字

定义

给系统使用的关键字,好比:int,float,void, class,for,while,break等等,在定义变量的时候不能定义成:int float;

运算符

算术运算符

算术运算符包括:+,-,*,/,%。

int a = 10;
int b = 3;
a + b; // 13
a - b; // 7
a * b; // 30
a / b; // 做商, 3
a % b; // 取余, 1

比较运算符

比较运算符包括:==,!=,>,>=,<, <=。

int a = 10;
int b = 3;
a == b; // false
a != b; // true
a > b ; // true
a >= b; // true
a < b ; // false
a <= b; // false

赋值运算符

赋值运算符:int a = 10;,将10赋值给变量a。

逻辑运算符

逻辑运算符包括:&&,||,!。

int a = 10;
int b = 1;
int c = 2;
// && 两边同时为true结果返回true,不然返回false
(a > b) && (a > c); // true,a>b为true,a>c为true
(a > b) && (a < c); // false, 由于,a>b为true,a<c为fasle
// || 两边只要有一边为true,结果返回true
(a > b) || (a > c); // true,a>b为true,a>c为true
(a > b) || (a < c); // true,a>b为true,a<c为false
(a < b) || (a > c); // true,a<b为false,a>c为true
(a < b) || (a < c); // false,a<b为fasle,a<c为false
// !,对取得的布尔值取反操做,!true->false, !false->true
!(a>c); // fasle,a>c为true

// &&,|| 的短路操做
(a > b) && ((c = b) ==b); // true,c=1,由于a>b为true,继续比较右边,执行右边
(a < b) && ((c=b)==b); // false,c=2,由于a<b为false,直接返回false,不比较后面代码,也不执行后面代码
(a > b) || ((c=b)==b); // true,c=2,由于a>b为true,直接返回结果,不执行后面操做
(a < b) || ((c=b)==b); // true,c=1,由于a<b为false,继续比较右边,执行右边代码,右边结果为true

三目运算符

形如:xxx?x:y。若xxx语句的返回值为true,则返回x,不然返回y。

int a = 10>20?1:2; // a=2,由于10>20为false

位运算符

位运算符主要包括:&,|,^。

// & 将两个数转换为二进制进行比较,相同的位上都是1,则该位比较后的值为1
// | 将两个数转换为二进制进行比较,相同的位上若是存在1,则该位比较后的值为1
// ^ 将两个数转换为二进制进行比较,相同的位上若是存在1,且不一样时为1,则该位比较后的值为1

5转换成二进制:0101
3转换成二进制:0011
	0101
  & 0011
  = 0001 转换成10进制:1
	0101
  | 0011
  = 0111 转换成10进制:7
	0101
  ^ 0011
  = 0110 转换成10进制:6

数据类型

基本数据类型

byte b;
short s;
int i;
long l;
float f;
double d;
char c;
boolean b;
String string;
整型
  • byte,占1个字节,值得范围是:- 128~127
  • short,占2个字节,值得范围是:-65536~65535
  • int,占4个字节,值得范围是:-4294967296~4294967295
  • long,占8个字节,值得范围是:-18446744073709551616~18446744073709551615
浮点型
  • float,占4个字节,值的范围是:1.4E-45~3.4028235E38
  • double,占8个字节,值的范围是:4.9E-324~1.7976931348623157E308
字符型
  • char,占2个字节
布尔型

占1位。

  • true
  • false

引用数据类型

  • String

  • 数组

    • 定义方式

      • int[] numbers = new int[10];
      • int[] numbers = new int[10]{1,2,3,4,5,6,7,8,9,0};
      • int[] numbers = {1,2,3,4,5,6,7,8,9,0};
    • 使用

      • 获取

        • int[] numbers = {1,2,3};
          System.out.println(numbers[1]);
      • 修改

        • int[] numbers = {1,2,3};
          numbers[1] = 10;
    • 注意:

      • 数组的下标为:0~数组的长度-1
  • 对象

    • 类的实例化

      • class Person{
            
        }
        Person person = new Person();
        // person即为对象
  • 接口

    • 某种行为/功能的抽象,若要使用则要实现接口中的全部方法,接口相似于一种约束、规范

    • interface MyInterface{
          void method();
      }
  • 等等

流程控制语句

顺序结构

从上到下依次按顺序执行

分支结构

  • if

    if(条件){
        执行语句
    }
    // 但条件的返回结果为true时执行执行语句,不然不执行
    // 应用
    int a = 10;
    if(a < 20){
        a = 30;
    }
    // 由于 a<20为true,执行语句,a=30
  • if...else

    if(条件){
        执行语句
    }else{
        执行语句2
    }   
    // 若条件的返回结果为true,则执行语句,不然执行语句2
    // 应用
    int a = 10;
    if(a>10){
        a = 8;
    }else{
        a = 20;
    }
    // 由于a>10为false,所以执行a=20
  • if...else if...else

    • if(条件1){
          执行语句1
      }else if(条件2){
          执行语句2
      }else{
          执行语句3
      }
      // 若知足条件1,则执行语句1,不然若知足条件2,则执行语句2,不然执行语句3
      // 应用
      int a = 10;
      if(a > 10){
          a = 8;
      }else if(a > 5){
          a = 4
      }else{
          a = 100;
      }
      //a = 4,由于a>10为false,a>5为false,执行a=4
  • switch

    switch(变量){
        case value1:
            执行语句1
            break;
        case value2:
            执行语句2
            break;
        default:
            执行语句3
            break;
    }
    // 变量的值若是等于某一个case后面的值则执行相应的语句,而后跳出语句,不然就执行default里的语句,而后退出
    // 这里变量以及case的值只能为:整数、字符、字符串
    // 应用
    int a = 10;
    switch(a){
        case 10:
            System.out.println("10");
            break;
        case 20:
            System.out.println("20");
            break;
        default:
            System.out.println("no");
            break;
    }
    // 打印10

循环结构

  • do...while

    • do{
          执行语句
      }while(条件);
      // 循环执行语句,直到不知足条件,至少作一次
      int a = 0;
      do{
          System.out.print(i);
          i++;
      }while(i<20);
  • while

    while(条件){
        执行语句
    }
    // 但知足条件时循环执行语句,直到不知足条件
    int a = 0;
    while(a < 10){
        System.out.println(a);
        a++;
    }
  • for

    for(初始化变量;知足的条件;更新变量){
        执行语句
    }
    // 对于初始化变量,每次执行语句后更新变量,直到不知足条件
    for(int a;a<10;a++){
        System.out.println(a);
    }
  • 加强for循环

对于一个集合、数组或者map,若其中的元素的类型都一致,则可使用使用forech(加强for循环来遍历)

for(类型 变量:集合){
    执行语句
}
// 应用
int[] numbers = {1,2,3,4,5};
for(int number:numbers){
    System.out.println(number);
}

流程控制语句的语法规则

  • break

    • 跳出当前循环

      for(int i=0;i<10;i++){
          if(i==5){
              break;
          }
          System.out.println(i);
      }
      //打印0-4后,更新变量,i=5,此时跳出for循环
  • continue

    • 跳过本次循环

      • for(int i=0;i<10;i++){
            if(i % 2 !=0){
                continue;
            }
            System.out.println(i);
        }
        // 打印0-9全部的偶数
  • return

    • 返回结果值

      • public int addOne(int number){
            return number + 1;
        }
        
        System.out.println(addOne(10));
        // 返回11
    • 结束程序

      • for(int i=0;i<10;i++){
            if(i ==5){
                return;
            }
        }
        
        // 当i==5时,结束程序

面向对象

编程思想

面向过程编程(POP, Procedure Oriented Programming)

典型的是C语言。经过分析出解决问题所须要的步骤,而后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就能够了。以把大象放入冰箱为例,咱们首先定义一个拿到大象的函数,而后定义一个开冰箱的函数,而后定义一个放大象的函数,而后定义一个关冰箱的函数,最后一次调用就能够实现功能了。

在考虑问题时,以一个具体的流程(事务过程)为单位,考虑它的实现。

面向对象编程(OOP,Object Oriented Programming)。

典型的C++、C#、Java等编程语言。经过将现实世界中的物体抽象成一个具体的类,经过调用类的相关方法来完成一系列行为。仍是以把大象放入冰箱为例,咱们先定义一我的的类,有拿大象、放大象、开冰箱、关冰箱的方法(也就是人能够作这些事情),再定义一个大象类,再定义一个冰箱类,而后建立相应的对象调用相关的方法便可。

在考虑问题时,以对象为单位,考虑它的属性及方法。

面向接口编程(IOP,Interface Oriented Programming)

定义(规范,约束)与实现(名实分离的原则)的分离。

接口的自己反映了系统设计人员对系统的抽象理解。

面向切面编程(AOP,Aspect Oriented Programming)

经过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP能够对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度下降,提升程序的可重用性,同时提升了开发的效率。

函数时编程(Function Programming)

典型的是Python、JavaScript语言。

函数式编程是种编程方式,它将电脑运算视为函数的计算。函数编程语言最重要的基础是λ演算(lambda calculus),并且λ演算的函数能够接受函数看成输入(参数)和输出(返回值)。主要思想是把运算过程尽可能写成一系列嵌套的函数调用。

类和对象

类是对象的抽象,对象是类的实例化

在现实生活中,人(Person)表示一种生物,很抽象,具体的人:张三,就是一个对象,一个具体的人,一个独立的个体。

// 定义一个类
class Person{
    
}
// 实例化一个对象(建立一个对象)
Person zhangsan = new Person();
如何建立对应的对象

经过new关键字实现。

构造器

一个类的构造方法,用于对一个对象的初始化,好比说咱们在买电脑的时候都会选择电脑的:cpu、内存、硬盘、显示屏等等,这些至关于初始化。

class Computer{
    private String cpu; 
    private String arm;
    private String disk;
    private String screen;
    
    public Computer(String _cpu, String _arm, String _disk, String _screen){
        cpu = _cpu;
        arm = _arm;
        disk = _disk;
        screen = _screen;
    }
}
// 利用构造器建立对象
Computer myComputer = new Computer("Intel", "英伟达","sanxing", "英伟达");

默认状况下建议写一个无参构造器。

this

指代当前对象。能够在构造方法中使用,用来区分参数和成员变量,在普通方法中使用表示调用当前的属性或者当前类的方法,能够省略。

class Computer{
    private String cpu; 
    private String arm;
    private String disk;
    private String screen;
    
    public Computer(String cpu, String arm, String disk, String screen){
        this.cpu = cpu;
        this.arm = arm;
        this.disk = disk;
        this.screen = screen;
    }
}
// 利用构造器建立对象
Computer myComputer = new Computer("Intel", "英伟达","sanxing", "英伟达");
static

表示静态的,更准确的说是表示类的什么什么,被static修饰的方法、函数、类(内部类)在类加载的时候就建立了,而没有被修饰的则是属于对象,只有当建立对象的时候才建立,由于,static修饰的属性、方法、类的建立是先于普通属性、方法的,所以:静态方法中不能存在普通的属性、方法、对象。

被static修饰的属性、方法,类能够直接调用。

class Person{
    static boolean isPerson = true;
    
    static void sleep(){
        
    }
}
// 调用
System.out.println(Person.isPerson);
System.out.println(Person.sleep());
final

表示最终的,不可更改,有三种形式

  • 修饰在属性上,表示属性的值不可更改,若属性的值是一个引用,则不能再被赋予其余的引用,可是引用中的属性能够更改
  • 修饰在方法上,表示该方法不能被重写(从新实现)
  • 修饰在类上,表示类不可被继承
package

打包:区分同名的文件,分布在不一样的目录。

将不一样的功能代码整合在一块儿。

import

导包:方便引用其余包的类

访问修饰符

规定方法、类、属性的访问范围。

分类:

  • private,只能当前类中使用
  • default,只能在当前包、类中使用
  • protected,能够在本类、本包以及继承该类的类中使用
  • public,同一个项目下的任何地方均可以使用
方法的重载

在同一个类中,能够定义多个同名方法,可是,这些方法必须知足如下三个条件之一:

  • 参数类型不同

  • 参数个数不同

  • 参数顺序不同

    class Demo{
        public void method(){
            
        }
        public void method(String str){
            
        }
        public void method(String str,int number){
            
        }
        public void method(int number,String name){
            
        }
    }

面向对象三大特性

封装
广义的封装

在代码中能够将某个代码块变成方法,抽象出某些工具类

狭义的封装
  1. 将属性设置成私有,不能被外部直接访问
  2. 提供共有的set和get方法,使外部能够进行调用
  3. 能够实现更加复杂细致的内部逻辑判断
  4. 保护类的内部实现细节,只提供公共的对外访问接口,保护类的安全
public class Test2 {
    private String string;
    private int number;

    public String getString() {
        return string;
    }

    public void setString(String string) {
        this.string = string;
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }
}
继承
  • 解释说明

    • 子类能够拥有父类的某些属性和方法,可是私有的除外
    • java中式严格意义上的单继承
    • 使用extends关键字来实现继承
  • 重写

    • 当父类中的某些方法不能知足子类的须要的时候,子类能够重写父类的方法,要求跟父类的方法名称一致
    • 子类方法的访问修饰符>父类的访问修饰符
    • 建议添加@override注解,在编译时提示错误
  • super

    • 表示的是父类的对象
    • 在建立对象的时候,能够在子类中直接经过super关键字调用父类的构造方法
    • 在子类方法中可使用super.的方法调用父类的方法和属性
  • public class Test2 extends Test4{
        @Override
        public void method() {
            super.method1();
            System.out.println("Test2->method");
        }
        
    }
    
    class Test4{
        public void method(){
            System.out.println("Test4->method");
        }
        
        public void method1(){
            System.out.println("Test4->method1");
        }
    }
多态
  • 通俗解释:对于同一个指令,不一样的对象给予的不一样反应
  • 前提
    1. 必须有继承关系
    2. 子类必须重写父类方法
    3. 父类引用指向子类对象
  • 父类和子类对象的转换:
    • 子类到父类,自动转换
    • 父类到子类,强制转换,且经过inatanceof判断
public class Test2{
    public static void main(String[] args) {
        personSpeak(new Boy()); // 传入子类自动转换成父类
        personSpeak(new Girl());
        personSpeak((Person) new Object()); // 父类到子类强制转换,Object类是全部类的父类
    }
    
    static void personSpeak(Person person){
        person.speak();
    }
    

}

abstract class Person{
    abstract void speak();
}

class Boy extends Person{

    @Override
    void speak() { // 重写父类方法
        System.out.println("男孩说话");
    }
}

class Girl extends Person{

    @Override
    void speak() {
        System.out.println("女孩说话");
    }
}
接口
  • 接口表明一种能力,实现接口,则表示具有了某种功能
  • 接口表明一种规范,在实现接口的时候必须遵循相应的规范,好比说从新实现方法的时候参数的要求、返回值的要求等等
  • 接口能够在必定程度上实现java的多继承,java只支持单继承,但能够实现多个接口,能够变相的实现多继承
  • 接口中的方法都是public abstract这样的访问修饰符,不能包含具体的方法实现
  • 子类若是实现了某个接口,那么接口中的全部方法都要被重写,且实现具体的逻辑,若是没有实现的话,那么子类要么是子接口要么是抽象类
  • 接口中的属性都是常量值
public class Test2{
    public static void main(String[] args) {
        new Singer().singSong(new Boy());
    }
    

}

interface Sing{
    final boolean isSing = true;
    void singSong(Person person);
}


class Singer extends Person implements Sing{

    @Override
    public void singSong(Person person) {
        this.speak();
    }

    @Override
    void speak() {

    }
}
抽象类
  1. 抽象类跟接口相似,能够定义抽象方法,也能够包含具体的实现
  2. 抽象类和抽象方法须要使用abstract关键字来进行修饰
  3. 抽象类的子类必须重写抽象类中的抽象方法,若是不重写的话,那么该子类也会成为一个抽象类
  4. 抽象类更能表示多态,对于子类来讲须要实现相同的功能且实现细节同样的则公用方法,对于子类来讲须要各自实现细节的就重写方法
// 案例:人都要睡觉;人要说话,可是不一样国家的人说的话不同,中国人说中文,美国人说美语
abstract class Person{
    
    public void sleep(){
        System.out.println("是我的都睡觉");
    }
    
    abstract void speak();
}

class Chinese extends Person{

    @Override
    void speak() {
        System.out.println("中国人说做文");
    }
}

class American extends Person{

    @Override
    void speak() {
        System.out.println("美国人说美语");
    }
}
内部类
  • 静态内部类
  • 方法内部类
  • 匿名内部类
  • 成员内部类
public class Demo1 {

    public static void main(String[] args) {
        // 静态内部类
        StaticInnerClass staticInnerClass = new Demo1.StaticInnerClass();
        // 成员内部类
        InnerClass innerClass = new Demo1().new InnerClass();
        // 方法内部类,生命周期指在方法内
        Object o = method();
        // 匿名内部类
        MyInterface myInterface = new MyInterface() {};
    }

    static class StaticInnerClass{

    }

    class InnerClass{

    }

    public static Object method(){
        class MethodInnerClass{

        }
        
        return new MethodInnerClass();
        
    }
}

interface MyInterface{
    
}

异常

定义

表示程序在运行过程当中出现的非正常状况,编写代码的过程当中尽量少的减小异常出现的状况

分类

  • Throwable
    • Error 代码级别没法解决的异常状况
    • Exception
      • 运行时异常:在程序运行过程当中,因为输入的参数值的不一样,可能会发生也可能不会发生
      • checked异常 :编译时异常,在ide中会显示的检查出来

异常的处理

捕获异常
  • try...catch

    try{
        可能出现异常的语句
    }catch(可能出现的异常){
        捕捉异常后执行的语句
    }
    // 
    try{
        int x = 1 /0;
    }catch(ArithmeticException e){
        e.printStack();
    }
  • try...catch...finally

    try{
        可能发生异常的代码
    }catch(发生的异常){
        捕捉异常后执行的语句
    }finally{
        无论是否发生异常都要执行的语句
    }
    
    //
    try{
        int x = 1 /0;
    }catch(ArithmeticException e){
        e.printStack();
    }finally{
        System.out.println("finally")
    }
  • 注意

    1. 当发生异常时,在try代码块中异常语句后面的语句不会再执行

    2. try、catch、finally以及try...catch...finally以外的代码是互相独立的,在try中定义的变量在其余的部分没法访问,改变了仅做用于try部分,其余catch、finally状况相似,可是外部定义的变量在try、catch、finally中可使用

    3. 在进行异常捕获的时候,return语句的不一样位置会形成结果的不一样

      1. 首先讨论try...catch...finally后面有代码的状况

        //此时注意一个关键的点:checked异常,即return语句后面不能再跟语句
        // 例如
        return;
        System.out.println("after return");// 这条语句ide直接报错,至关于多余的
        // 故return的语句只能有一下几种状况
        //1
                try{
                    System.out.println("1");
                    System.out.println(1 / 0);
                    return;
                }catch (Exception e){
                    System.out.println("2");
        //            return;
                }finally {
                    System.out.println("3");
        //            return;
                }
                System.out.println("4");
            }
        // 此时return语句永远都不会被执行,也就不会报错。
        //2
                try{
                    System.out.println("1");
        //            System.out.println(1 / 0);
                    return;
                }catch (Exception e){
                    System.out.println("2");
        //            return;
                }finally {
                    System.out.println("3");
        //            return;
                }
                System.out.println("4");
        //此时,当程序执行到return语句时,并不会当即执行,而是先挂起,等执行完finally中的语句以后再执行return语句结束程序,故try、catch、finally以外的其余代码不会再执行
        //其余的catch、finally中都不能再存在return语句了
      2. try...catch...finally后面没有代码的状况

        //第一种状况
        try{
                    System.out.println("1");
                    System.out.println(1 / 0);
                    return;
                }catch (Exception e){
                    System.out.println("2");
        //            return;
                }finally {
                    System.out.println("3");
        //            return;
                }
        // 此时return语句永远不会执行
        // 第二种状况,此时return语句有没有都没有关系
        try{
                    System.out.println("1");
        //            System.out.println(1 / 0);
                    return;
                }catch (Exception e){
                    System.out.println("2");
        //            return;
                }finally {
                    System.out.println("3");
        //            return;
                }
        //第三种状况
        try{
                    System.out.println("1");
                    System.out.println(1 / 0);
        //            return;
                }catch (Exception e){
                    System.out.println("2");
                    return;
                }finally {
                    System.out.println("3");
        //            return;
                }
        //此时,仍是跟前面同样的,return先挂起,执行完finally中的代码后再结束程序
        //第三种状况
        public class Demo {
            public static void main(String[] args) {
                System.out.println(method());
        
            }
        
            public static int method(){
                try{
                    System.out.println("1");
                    System.out.println(1 / 0);
        //            return;
                }catch (Exception e){
                    System.out.println("2");
                    return 1;
                }finally {
                    System.out.println("3");
        //            return 2;
                }
        //        System.out.println("4");
                return 0;
            }
        }
        // 此时会执行最近的return语句
      3. 综上:

        1. return语句会被挂起,等执行完finally中的语句后再执行
        2. 当存在两个return语句时且都能被执行时,优先执行finally中的return
抛出异常
throws

将异常状况抛出给调用者

注意,若是整个程序的运行过程当中都没有异常的处理的话,最终异常会抛给jvm,不太友好,通常都要对异常进行处理

import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class Demo1 {
    public static void main(String[] args) throws FileNotFoundException {
        FileInputStream fileInputStream = new FileInputStream("test.txt");
    }
}

自定义异常

java中提供了很是多的异常类,可是在某些项目中须要本身定义独特的异常处理方式,此时须要自定义异常

  1. 继承Exception
  2. 编写构造方法,能够传入本身想打印的异常信息
  3. 调用的时候经过throw向外抛出异常
public class MyException extends Exception{
    public MyException(){
        System.out.println("自定义异常");
    }
}
public class Demo1 {
    public static void main(String[] args) throws MyException {
        throw new MyException();
    }
}

另外,还能够自定义异常信息

public class Demo1 {
    public static void main(String[] args) throws Exception {
        throw new Exception("test");
    }
}

经常使用类

包装类

  1. 基本数据类型都由对应的包装类

    • int:Integer
    • byte:Byte
    • short:Short
    • long:Long
    • float:Float
    • double:Double
  2. 自动拆箱和自动装箱

  3. 举例

    public class Demo {
        public static void main(String[] args) {
            // 此时自动调用:Integer.valueOf(),若数字大于-128且小于127,直接返回值,不然新建一个对象
            Integer integer1 = 1000;
            Integer integer2 = 1000;
            int i1 = 1000;
            int i2 = 1000;
            System.out.println(integer1 == integer2); // 由于两个变量不是同一个对象所以结果为false
            System.out.println(integer1.equals(integer2));// true
            System.out.println(i1 == i2); // true
            System.out.println(i1 == integer2); // true
        }
    }

String

  • 不可变字符串:String

  • 可变字符串:

    • 线程安全:StringBuffer
    • 线程不安全:StringBuilder
  • 举例

    public class Demo1 {
        public static void main(String[] args) {
            StringBuffer stringBuffer = new StringBuffer("hello,world");
            // 增
            stringBuffer.insert(0, "@");
            stringBuffer.append("#");
            // 删
            stringBuffer.delete(0,1);
            // 改
            stringBuffer.setCharAt(0, '$');
            stringBuffer.replace(0,1,"x");
            // 查
            stringBuffer.indexOf("a");
            stringBuffer.substring(0,1);
            System.out.println(stringBuffer);
    
    
        }
    }

Date

日期经常使用类

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Demo2 {
    public static void main(String[] args) {
        DateFormat dateFormat = new SimpleDateFormat("YY-MM-dd HH-mm-ss"); // 建立格式化日期类
        System.out.println(dateFormat.format(new Date()));
    }
}

Calender

返回格林威治时间

import java.util.Calendar;
import java.util.GregorianCalendar;

public class Demo3 {
    public static void main(String[] args) {
        Calendar calendar = new GregorianCalendar();
        System.out.println(calendar.getTime());
        System.out.println(calendar.getTimeZone());
        System.out.println(calendar.getFirstDayOfWeek());
        System.out.println(calendar.getWeekYear());
    }
}

Math

数学经常使用类

public class Demo4 {
    public static void main(String[] args) {
        System.out.println(Math.max(10,20));
        System.out.println(Math.abs(-1));
        System.out.println(Math.ceil(1.1));
        System.out.println(Math.PI);
        System.out.println(Math.E);
    }
}

Random

import java.util.Random;

public class Demo5 {
    public static void main(String[] args) {
        System.out.println(new Random().nextInt(10));
        System.out.println(new Random().nextDouble());
    }
}

Enum(枚举类)

枚举类也是一个类,能够定义属性和方法,甚至能够写构造方法,填写具体的枚举类对象的时候,能够带参数,可是要跟构造方法进行匹配

初级用法
public class Demo6 {
    public static void main(String[] args) {
        System.out.println(Gender.FEMALE);
    }
}
public enum Gender {
    MALE,FEMALE;
}
高阶用法

每一个枚举的子枚举均可以看做是枚举的子类,能够定义相关方法以及相应的set/get方法来获取子枚举携带的一些信息

public enum WEEK_DAY {
    MONDAY(0),
    TUESDAY(1),
    WEDNESDAY(2),
    THURSDAY(3),
    FRIDAY(4),
    SATURDAY(5),
    SUNDAY(6);

    private int value;
    public void method(int i){
        System.out.println(i);
    }

    public int getValue(){
        return this.value;
    }



    WEEK_DAY(int i) {
        this.value = i;
    }
}

public class Demo6 {
    public static void main(String[] args) {
        System.out.println(WEEK_DAY.FRIDAY.getValue());
    }
}

集合

定义

一个用来储存数据的容器

数组

形如:int[],String[]的数据结构

特色:

  1. 数据的类型必须是一致的
  2. 数组必须在声明的时候显示的给出长度
  3. 数组在插入和删除的时候,频繁的移动元素,效率比较低
  4. 数组在查找元素的时候能够按照下标查找

Collection

具备的基本操做:

  1. 添加,存储的是对象的引用
    1. add
  2. 容器中元素的个数
    1. size
  3. 删除
    1. remove
    2. clear
    3. removeAll
    4. retainAll
  4. 判断元素是否存在集合中
    1. contains
    2. isEmpty
  5. 遍历元素
    1. iterator
List
特色

不惟一,有序

ArrayList

ArrayList实现了长度可变的数组,在内存中分配连续的空间

  • 优势:遍历元素和随机访问元素的效率比较高
  • 缺点:添加和删除须要大量移动元素效率低,按照内容查询效
    率低
LinkedList

LinkedList采用链表存储方式

  • 优势:插入、删除元素时效率比较高
  • 缺点:遍历和随机访问元素效率低下

LinkedList特有方法

    1. addFirst(Object obj) 添加头
    2. addLast(Object obj) 添加尾
    3. offerFirst(Object obj) 1.6版本以后的加头,尾巴
    4. offerLast(Object obj) 1.6版本以后的加头,尾巴
    1. removeFirst() 删除头 获取元素并删除元素
    2. removeLast() 删除尾
    3. pollFirst() 1.6版本以后的删头,删尾
    4. pollLast() 1.6版本以后的删头,删尾
    1. getFirst() 获取头 获取元素但不删除
    2. getLast() 获取尾
    3. peekFirst() 1.6版本以后的获取头,获取尾
    4. peekLast() 1.6版本以后的获取头,获取尾
List接口特有方法
    1. add(index,element) 在指定索引的位置上插入元素
    2. addAll(index,Collection) 在指定的引的位置上插入整个集合的元素
    3. addAll(Collection) 在结束插入整个集合的元素
    1. remove(index)
    1. set(index,element)
    2. 使用element替换指定索引位置上的元素
  1. 查(获取元素)
    1. get(index)
    2. subList(from,to)
    3. listIterator();
Set
特色:惟一,无序
HashSet
  • 采用Hashtable哈希表存储结构

  • 优势:添加速度快,查询速度快,删除速度快

  • 缺点:无序

  • LinkedHashSet

    • 采用哈希表存储结构,同时使用链表维护次序
    • 有序(添加顺序)
Hash表原理

  • 代码验证HashSet的无序性不惟一性
  • 使用HashSet存储自定义对象,重写hashCode方法与equals方法

  • 关键代码

    HashSet hs=new HashSet();//建立HashSet对象
    hs.add(new Person("张三",20));
    hs.add(new Person("李四",22));
    hs.add(new Person("王五",23));
    hs.add(new Person("李四",22));
    • HashSet存储进了相同的对象,不符合实际状况
    • 解决方案: 重写equals方法与hashCode方法
    • HashSet的操做
    @Override
    public int hashCode() {
    System.out.println(this.name+".....hashCode");
    return 60;
    }
    • hashCode都相同,不符合实际状况,继续升级

      • 修改hashCode方法

        @Override
        public int hashCode() {
        System.out.println(this.name+".....hashCode");
        return this.name.hashCode()+age;
        }
  • 总结:

    • HashSet是经过元素的两个方法,hashCode和equals方法来保证元素的惟一性的 。若是元素的HashCode值相同,才会判断equals是否为true ,若是元素的hashCode值不一样,不会调用equals方法
TreeSet
  • 采用二叉树(红黑树)的存储结构
  • 优势:有序(排序后的升序)查询速度比List快
  • 缺点:查询速度没有HashSet快
Comparable 接口

全部能够“排序”的类都实现了java.lang.Comparable 接口 compareTo(Object obj) 方法。

该方法:

返回 0 表示 this == obj
返回正数 表示 this > obj
返回负数 表示 this < obj

实现了Comparable 接口的类经过实现 comparaTo 方法从而肯定该类对象的排序方式。

public class StrLenComparator implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
if (o1.length()>o2.length()) {
return 1;
}
if (o1.length()<o2.length()) {
return -1;
}
return o1.compareTo(o2);//长度相同, 按字母
}
}
public static void sortDemo(){
List<String> list=new ArrayList<String>();
..添加元素
sop(list);
Collections.sort(list);//按字母排序
sop(list);
//按照字符串长度排序
Collections.sort(list,new StrLenComparator());
sop(list);
}
Iterator接口

全部实现了Collection接口的容器类都有一个iterator方法用以返回一个实现了Iterator接口的对象。

Iterator对象称做迭代器,用以方便的实现对容器内元素的遍历操做。

Iterator接口定义了以下方法:

boolean hasNext(); //判断是否有元素没有被遍历
Object next(); //返回游标当前位置的元素并将游标移动到下一个位置
void remove(); //删除游标左面的元素,在执行完next以后该
//操做只能执行一次

全部的集合类均未提供相应的遍历方法,而是把遍历交给迭代器完成。迭代器为集合而生,与门实现集合遍历

Iterator是迭代器设计模式的具体实现

Iterator方法:

  • boolean hasNext():判断是否存在另外一个可访问的元素
  • Object next():返回要访问的下一个元素
  • void remove():删除上次访问返回的对象

可使用Iterator遍历的本质 :实现Iterable接口

ListIterator

在迭代过程当中,准备添加或者删除元素

ArrayList al=new ArrayList();
al.add("java1");//添加元素
al.add("java2");
al.add("java3");
//遍历
Iterator it=al.iterator();
while(it.hasNext()){
Object obj=it.next();
if (obj.equals("java2")) {
al.add("java9");
}
sop("obj="+obj);
}
ListIterator的做用:解决并发操做异常

在迭代时,不可能经过集合对象的方法(al.add(?))操做集合中的元素,会发生并发修改异常。 因此,在迭代时只能经过迭代器的方法操做元素,可是Iterator的方法是有限的,只能进行判断(hasNext),取出(next),删除(remove)的操做,若是想要在迭代的过程当中进行向集合中添加,修改元素等就须要使用 ListIterator接口中的方法

ListIterator li=al.listIterator();
while(li.hasNext()){
Object obj=li.next();
if ("java2".equals(obj)) {
li.add("java9994");
li.set("java002");
}
}

Map

接口存储一组键值对象,提供key到value的映射

Map相关方法
  1. 添加
    1. put(key,value) 添加元素
  2. 删除
    1. clear() 清除全部
    2. remove(key) 根据key去移除
  3. 判断
    1. containsKey(key)是否包含指定的key
    2. containsValue(value) 是否包含指定的值
    3. isEmpty() 判断集合中元素是否为 空
  4. 遍历
    1. get(key)
    2. size()
    3. values()
    4. entrySet()
    5. keySet()

Collections工具类

Collections和Collection不一样,前者是集合的操做类,后者是集合接口

Collections提供的静态方法 :

  1. addAll():批量添加
  2. sort():排序
  3. binarySearch():二分查找
  4. fill():替换
  5. shuffle():随机排序
  6. reverse():逆序

集合总结


集合和数组的比较

数组不是面向对象的,存在明显的缺陷,集合弥补了数组的一些缺点,比数组更灵活更实用,可大大提升软件的开发效率,并且不一样的集合框架类可适用不一样场合。具体以下:

  1. 数组能存放基本数据类型和对象,而集合类中只能存放对象
  2. 数组容易固定没法动态改变,集合类容量动态改变
  3. 数组没法判断其中实际存有多少元素, length只告诉了数组的容量,而集合的size()能够确切知道元素的个数
  4. 集合有多种实现方式和不一样适用场合,不像数组仅采用顺序表方式
  5. 集合以类的形式存在,具备封装、继承、多态等类的特性,经过简单的方法和属性便可实现各类复杂操做,大大提升了软件的开发效率

Collection和Collections的区别

  1. Collection是Java提供的集合接口,存储一组不惟 一,无序的对象。它有两个子接口List和Set。
  2. Java还有一个Collections类,专门用来操做集合类,它提供了一系列的静态方法实现对各类集合的搜索、排序、线程安全化等操做。

ArrayList和LinkedList的联系和区别

  1. ArrayList实现了长度可变的数组,在内存中分配连续空间。遍历元素和随机访问元素效率比较高
  2. LinkedList采用链表存储方式。插入、删除元素效率比较高

Vector和ArrayList的联系和区别

  1. 实现原理相同,功能相同,都是长度可变的数组结构,不少时候能够互用
  2. 二者的主要区别以下
    1. Vector是早期的JDK接口, ArrayList是替代Vector的新接口
    2. Vector线程安全, ArrayList重速度轻安全,线程非安全
    3. 长度须要增加时, Vector默认增加一倍, ArrayList增加50%(1.5+1)

HashMap和Hashtable的联系和区别

  1. 实现原理相同,功能相同,底层都是哈希表结构,查询速度快,在不少状况下能够互用

  2. 二者的主要区别以下 :

    1. Hashtable是早期的JDK提供的接口, HashMap是新版的JDK提供的接口
    2. Hashtable继承Dictionary类, HashMap实现Map接口
    3. Hashtable是线程安全, HashMap线程非安全
    4. Hashtable不容许null值, HashMap容许null值

IO

流的基本概念

流是指一连串流动的字符,是以先进先出方式发送信息的通道 。

  1. XXX->程序-->输入流

  2. 程序->XXX-->输出流

Java流的分类

输入输出流是相对于计算机内存来讲的,而不是相对于源和目标

字节流是 8 位通用字节流,字符流是 16 位 Unicode 字符流

  1. 功能不一样

    1. 节点流:能够直接从数据源或目的地读写数据

    2. 处理流(包装流):不直接链接到数据源或目的地,是其余流进行封装。目的主要是简化操做和提升性能

    3. 节点流和处理流的关系

      1. 节点流处于io操做的第一线,全部操做必须经过他们进行

      2. 处理流能够对其余流进行处理(提升效率或操做灵活性)

文件的读写

  1. 用FileInputStream和FileOutputStream读写文本文件

    1. 使用FileInputStream 读文本文件

      1. 引入相关的类

      2. 构造文件输入流FileInputStream对象

      3. 读取文本文件的数据

      4. 关闭文件流对象

        import java.io.FileInputStream;
        import java.io.FileNotFoundException;
        import java.io.IOException;
        
        public class Demo {
            public static void main(String[] args) {
                FileInputStream fileInputStream;
                byte[] bytes = new byte[1024];
                try {
                    fileInputStream= new FileInputStream("test.txt");
                    fileInputStream.read(bytes);
                    System.out.println(new String(bytes));
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                fileInputStream.close();
            }
        }
    2. 使用FileOutputStream 写文本文件

      1. 引入相关的类

      2. 构造文件数据 流输出对象

      3. 将数据写入文 本文件

      4. 关闭文件流对象

        import java.io.FileOutputStream;
        import java.io.IOException;
        import java.nio.charset.StandardCharsets;
        
        public class Demo2 {
            public static void main(String[] args) throws IOException {
                FileOutputStream fileOutputStream = new FileOutputStream("test.txt");
                String string = "aaaaa";
                fileOutputStream.write(string.getBytes(StandardCharsets.UTF_8));
                fileOutputStream.close();
            }
        }
  2. 用BufferedReader和BufferedWriter读写文本文件

    1. 使用 BufferedReader 读文本文件

      import java.io.*;
      
      public class Demo3 {
          public static void main(String[] args) throws IOException {
              FileReader fileReader = new FileReader("test.txt");
              BufferedReader bufferedReader = new BufferedReader(fileReader);
              String result = "";
              while ((result = bufferedReader.readLine())!=null){
                  System.out.println(result);
              }
              bufferedReader.close();
              fileReader.close();
          }
      }
    2. 使用 BufferedWriter 写文件

      import java.io.BufferedWriter;
      import java.io.FileWriter;
      import java.io.IOException;
      
      public class Demo4 {
          public static void main(String[] args) throws IOException {
              FileWriter fileWriter = new FileWriter("test.txt");
              BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
              String string = "aaaaaaaa\naaaaaa\taaaa\nsdsdsds";
              bufferedWriter.write(string);
              bufferedWriter.close();
              fileWriter.close();
          }
      }

二进制文件的读写

使用DataInputStream和DataOutputStream读写二进制文件以及基本数据类型数据的读写

  1. 写入数据

    DataOutputStream dos=new DataOutputStream(new FileOutputStream("data.txt"));
    dos.writeInt(234);
    dos.writeBoolean(false);
    dos.writeDouble(9943.00);
    dos.writeUTF("中国");
    dos.close();
  2. 读取数据

    DataInputStream dis=new DataInputStream(new FileInputStream("data.txt"));
    int num=dis.readInt();
    boolean isFind=dis.readBoolean();
    double price=dis.readDouble();
    String str=dis.readUTF();
    System.out.println(num+"\t"+isFind+"\t"+price+"\t"+str);

对象的读写

使用ObjectInputStream和ObjectOutputStream读写对象(序列化与反序列化)

注意:传输的对象须要实现Serializable接口

  1. 序列化

    ObjectOutputStream oos=new ObjectOutputStream(new
    FileOutputStream("obj.txt"));
    oos.writeObject(new Person("张三",19));
    oos.close();
  2. 反序列化

    ObjectInputStream ois=new ObjectInputStream(new
    FileInputStream("obj.txt"));
    Person p=(Person)ois.readObject();
    System.out.println(p);
  3. 注意:

    1. 类必须实现Serializable接口
    2. 给类加个序列化编号,给类定义一个标记,新的修改后的类还能够操做曾经序列化的对象
    3. 静态是不能被序列化的,序列化只能对堆中的进行序列化 ,不能对“方法区”中的进行序列化
    4. 不须要序列化的字段前加 transient

总结

  1. 文件操做:FileReader, FileWriter
  2. 字符操做:FileInputStream, FileOutputStream
  3. 基本数据类型操做:DataInputStream, DataOutputStream
  4. 操做对象:ObjectInputStream ,ObjectOutputStream

线程

核心概念

  1. 程序:Program,是一个指令的集合
  2. 进程:Process,(正在执行中的程序)是一个静态的概念
    1. 进程:Process,(正在执行中的程序)是一个静态的概念
    2. 每一个进程都是独立的,由3部分组成cpu,data,code
    3. 缺点:内存的浪费, cpu的负担
  3. 线程:是进程中一个“单一的连续控制流程”
    1. 线程又被称为轻量级进程(lightweight process)
    2. 一个进程可拥有多个并行的(concurrent)线程
    3. 一个进程中的线程共享相同的内存单元/内存地址空间->能够访问相同的变量和对象,并且它们从同一堆中分配对象->通讯、数据交换、同步操做
    4. 因为线程间的通讯是在同一地址空间上进行的,因此不须要额外的通讯机制,这就使得通讯更简便并且信息传递的速度也更快

多线程的实现

  1. 在Java中负责线程的这个功能的是Java.lang.Thread 这个类

  2. 能够经过建立 Thread 的实例来建立新的线程

  3. 每一个线程都是经过某个特定Thread对象所对应的方法run( )来完成其操做的,方法run( )称为线程体

  4. 经过调用Thead类的start()方法来启动一个线程

  5. 具体实现:

    1. 继承Thread类
    2. 重写run方法
    3. 建立对象,调用start()方法启动线程
    public class ThreadDemo01 extends Thread {
    //重写父为的run方法
    @Override
    public void run() {
    for(int i=0;i<10;i++){
    System.out.println("第"+i+"次threadrun........");
    }
    }
    public static void main(String[] args) {
    //建立对象,就建立好一个线程
    ThreadDemo01 d=new ThreadDemo01();
    //d.run();//启动线程使用start方法
    d.start();
    for(int i=0;i<5;i++){
    System.out.println("main-->"+i);
    }
    }
    }
  6. 线程的执行

    1. xxx.run();仅仅是对象调方法,而是建立了线程但并无运行
    2. xxx.start();//开启线程并执行该线程的run方法
  1. 操做步骤

    1. 实现Runnable接口
    2. 重写run方法
    3. 建立对象,调用start()方法启动线程
    public class RunableDemo implements Runnable {
    @Override
    public void run() {
    for(int i=0;i<10;i++){
    System.out.println("第"+i+"次threadrun........");
    }
    }
    public static void main(String[] args) {
    //建立对象,就建立好一个线程
    RunableDemo rd=new RunableDemo();
    Thread t=new Thread(rd);
    t.start();
    for(int i=0;i<5;i++){
    System.out.println("main-->"+i);
    }
    } }
  1. 继承Thread类方式的缺点:那就是若是咱们的类已经从一个类继承(如小程序必须继承自 Applet 类),则没法再继承 Thread类
  2. 经过Runnable接口实现多线程
    1. 优势:能够同时实现继承。实现Runnable接口方式要通用一些
      1. 避免单继承
      2. 方便共享资源 同一份资源 多个代理访问

线程的状态

  1. 新生状态 :用new关键字创建一个线程后,该线程对象就处亍新生状态 ;处亍新生状态的线程有本身的内存空间,经过调用start()方法进入就绪状态
  2. 就绪状态 :处亍就绪状态线程具有了运行条件,但还没分配到CPU,处于线程就绪队列,等待系统为其分配CPU;当系统选定一个等待执行的线程后,它就会从就绪状态进入执行状态,该动做称为“CPU调度”
  3. 运行状态 :在运行状态的线程执行本身的run方法中代码,直到等待某资源而阻塞或完成任何而死亡 ;若是在给定的时间片内没有执行结束,就会被系统给换下来回到等待执行状态
  4. 阻塞状态 :处于运行状态的线程在某些状况下,如执行了sleep(睡眠)方法,或等待I/O设备等资源,将让出CPU并暂时中止本身运行,进入阻塞状态;在阻塞状态的线程并能进入就绪队列。只有当引发阻塞的缘由消除时,如睡眠时间已到,或等待的I/O设备空闲下来,线程便转入就绪状态,从新到就绪队列中排队等待,被系统选中后从原来中止的位置开始继续执行
  5. 死亡状态 :死亡状态是线程生命周期中的最后一个阶段。线程死亡的缘由有三个,一个是正常运行的线程完成了它的所有工做;另外一个是线程被强制性地终止,如经过stop方法来终止一个线程【不推荐使用】 ;三是线程抛出未捕获的异常

线程操做的相关方法

阻塞状态(sleep/yield/join方法)

有三种方法能够暂停Thread执行:

  1. sleep:
    不会释放锁, Sleep时别的线程也不能够访问锁定对象。
  2. yield:
    让出CPU的使用权,从运行态直接进入就绪态。让CPU从新挑选哪个线程进入运行状态。
  3. join:
    当某个线程等待另外一个线程执行结束后,才继续执行时,使调用该方法的线程在此以前执行完毕,也就是等待调用该方法的线程执行完毕后再往下继续执行

多线程的安全性问题

public class TicketImplements implements Runnable {
private int tick=5;
public void run() {
while(true){
if (tick>0) {
Thread.sleep(10);
System.out.println(Thread.currentThread().getName()+"卖票:"+tick--);
}
}
}
public static void main(String[] args) {
TicketImplements ti=new TicketImplements();
new Thread(ti).start();
new Thread(ti).start();
new Thread(ti).start();
new Thread(ti).start();
}

线程的同步不死锁

多线程的运行出现了安全问题

使用同步解决多线程的安全性问题

  1. 同步代码块

    public void run() {
    while(true){
    synchronized (this) {//一般将当前对象做为同步对象
    if (tick>0) {
    Thread.sleep(10);
    System.out.println(Thread.currentThread().getName()+"卖
    票:"+tick--);
    }
    }
    }
    }
    1. 同步的前提

      1. 必须有两个或两个以上的线程
      2. 必须是多个线程使用同一资源
      3. 必须保证同步中只能有一个线程在运行
    2. 将须要同步的代码放到方法中

      public void run() {
      while(true){
      sale();
      }
      }
      public synchronized void sale(){
      //一般将当前对象做为同步对象
      if (tick>0) {
      Thread.sleep(10);
      System.out.println(Thread.currentThread().getName()+"卖票:"+tick--);
      }
      }
    3. 同步监视器

      1. synchronized(obj){}中的obj称为同步监视器
      2. 同步代码块中同步监视器能够是任何对象,可是推荐使用共享资源做为同步监视器
      3. 同步方法中无需指定同步监视器,由于同步方法的监视器是this,也就是该对象自己
    4. 同步监视器的执行过程

      1. 第一个线程访问,锁定同步监视器,执行其中代码
      2. 第二个线程访问,发现同步监视器被锁定,没法访问
      3. 第一个线程访问完毕,解锁同步监视器
      4. 第二个线程访问,发现同步监视器未锁,锁定并访问

死锁

  1. 同步能够保证资源共享操做的正确性,可是过多同步也会产生死
  2. 死锁通常状况下表示互相等待,是程序运行时出现的一种问题

线程通讯

Java提供了3个方法解决线程之间的通讯问题

网络编程

网络的概念

一组相互链接的计算机

网络编程的三要素

  1. IP地址:惟一标识网络上的每一台计算机,两台计算机之间通讯的必备要素
  2. 端口号:计算机中应用的标号(表明一个应用程序)0-1024系统使用或保留端口 ,有效端口0-65536
  3. 通讯协议:通讯的规则TCP,UDP

网络模型

OSI参考模式:开放系统互连参考模型(Open System Interconnect)

TCP/IP参考模型:传输控制/网际协议 Transfer Controln Protocol/Internet Protocol

IP地址的表示方法

  1. IP 地址: 32位, 由4个8位二进制数组成
  2. IP表示方法:点分十进制
  3. 举例
    1. 二进制:11000000.10101000.00000001.11001000
    2. 十进制:192.168.1.200
  4. IP地址 = 网络ID +主机ID
    1. 网络ID:标识计算机或网络设备所在的网段
    2. 主机ID:标识特定主机或网络设备

**IP地址所对应的对象->InetAddress **

得到百度主机名:

InetAddress ia2=InetAddress.getByName("www.baidu.com");
System.out.println("其它主机名称:"+ia2.getHostAddress());

端口

  1. 端口:port
    端口是虚拟的概念,并非说在主机上真的有若干个端口。经过
    端口,能够在一个主机上运行多个网络应用程序。

传输协议

  1. UDP:至关于収短信(有字数限制),
    不须要创建链接,
    数据报的大小限制在64k内,
    效率较高,不安全,容易丢包
  2. TCP:至关于打电话,须要创建链接,
    效率相对比较低,数据传输安全,
    三次握手完成。
    (点名->答到->确认)

Socket套接字

  1. 网络上的两个程序经过一个双向的通讯链接实现数据的交换, 这个链接的一端称为一个socket。
  2. Java中使用Socket完成TCP程序的开収,使用此类能够方便的创建可靠的、 双向的、 持续性的、 点对点的通信链接
  3. 在Socket的程序开发中,服务器端使用ServerSocket等待客户端的链接,对于java的网络程序来说,每个客户端都使用一个Socket对象表示

基于TCP协议的Socket编程

进行网络通讯时, Socket须要借助数据流来完成数据的传递工做

  1. 客户端

    1. 创建链接
    Socket socket=new Socket("localhost",8800);
    1. 打开Socket关联的输入输出流
    OutputStream os=socket.getOutputStream();
    1. 数据流中读写信息
    String info="用户名: Tom;用户密码: 123456";
    os.write(info.getBytes());
    socket.shutdownOutput();
    1. 关闭全部的数据流和Socket

      os.close();
      socket.close();
  2. 服务端

    1. 创建链接,处理发送到指定端口的数据

      ServerSocket server=new ServerSocket(8800);
    2. 获取客户端对象

      Socket socket=server.accept();
    3. 数据流中读写信息

      InputStream is=socket.getInputStream();
      byte[] buf=new byte[1024];
      int len=is.read(buf);
      syso(new String(buf,0,len))
      socket.shutdownInput();
    4. 关闭全部的数据流和Socket

      is.close();
      socket.close();
      server.close()

Socket中实现对象的传递

序列化对象

User user=new User();//User是用户类
user.setLoginName("Tom");
user.setPwd("123456");
oos.writeObject(user);

基于UDP的网络编程

通讯双发不须要创建链接 ,通讯双方彻底平等

import java.io.IOException;
import java.net.*;


public class Client {
    public static void main(String[] args) throws IOException, InterruptedException {
        DatagramSocket datagramSocket = new DatagramSocket(new InetSocketAddress(InetAddress.getByName("localhost"),8888));
        datagramSocket.connect(InetAddress.getByName("localhost"), 9999);
        ReadThread readThread = new ReadThread(datagramSocket);
        WriteThread writeThread = new WriteThread(datagramSocket);
        readThread.start();
        writeThread.start();
    }
}

public class Client2 {
    public static void main(String[] args) throws IOException, InterruptedException {
        DatagramSocket datagramSocket = new DatagramSocket(new InetSocketAddress(InetAddress.getByName("localhost"),9999));
        datagramSocket.connect(InetAddress.getByName("localhost"), 8888);
        ReadThread readThread = new ReadThread(datagramSocket);
        WriteThread writeThread = new WriteThread(datagramSocket);
        readThread.start();
        writeThread.start();
    }
}

import java.nio.charset.StandardCharsets;

public class ReadThread extends Thread{
    private DatagramSocket datagramSocket;
    private byte[] bytes = new byte[1024];
    private byte[] bytes1;
    DatagramPacket datagramPacket = new DatagramPacket(this.bytes, 0,1024);

    public ReadThread(DatagramSocket datagramSocket){
        this.datagramSocket = datagramSocket;
    }
    @Override
    public void run() {
        super.run();
        while (true){
            try {
                this.datagramSocket.receive(this.datagramPacket);
                this.bytes1 = new String(this.bytes, 0, this.bytes.length).getBytes(StandardCharsets.UTF_8);
                System.out.println(new String(this.bytes1, 0, this.bytes1.length));
                Thread.sleep(2);
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

import java.util.Scanner;

public class WriteThread extends Thread{
    private DatagramSocket datagramSocket;
    private String message = "";
    private byte[] bytes = new byte[1024];
    private Scanner scanner = new Scanner(System.in);

    public WriteThread(DatagramSocket datagramSocket){
        this.datagramSocket = datagramSocket;
    }

    @Override
    public void run() {
        super.run();
        while (true){
            synchronized (WriteThread.class){
                System.out.print("输入:");
                this.message = this.scanner.nextLine();
            }
            DatagramPacket datagramPacket = null;
            try {
                datagramPacket = new DatagramPacket(message.getBytes(StandardCharsets.UTF_8),0, message.length(), new InetSocketAddress(InetAddress.getByName("localhost"),datagramSocket.getPort()));
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
            try {
                datagramSocket.send(datagramPacket);
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                try {
                    Thread.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Lambda表达式

Lambda表达式的介绍

Lambda表达式是 Java8 中最重要的新功能之一。使用 Lambda 表达式能够替代只有一个抽象函数的接口实现,告别匿名内部类,代码看起来更简洁易懂。 Lambda表达式同时还提高了对集合、框架的迭代、遍历、过滤数据的操做

Lambda表达式的特色

  1. 函数式编程
  2. 参数类型自动推断
  3. 代码量少,简洁

Lambda表达式案例

Lambda表达式应用场景

任何有函数式接口的地方

函数接口

只有一个抽象方法(Object类中的方法除外) 的接口是函数式接口

  1. Supplier 表明一个输出
  2. Consumer 表明一个输入
  3. BiConsumer 表明两个输入
  4. Function 表明一个输入,一个输出(通常输入和输出是不一样类型的)
  5. UnaryOperator 表明一个输入,一个输出(输入和输出是相同类型的)
  6. BiFunction 表明两个输入,一个输出(通常输入和输出是不一样类型的)
  7. BinaryOperator 表明两个输入,一个输出(输入和输出是相同类型的)

方法的引用

方法引用是用来直接访问类或者实例的已经存在的方法或者构造方法,方法引用提供了一种引用而不执行方法的方式,若是抽象方法的实现刚好可使用调用另一个方法来实现,就有可能可使用方法引用

方法引用的分类

  1. 静态方法引用:若是函数式接口的实现刚好能够经过调用一个静态方法来实现,那么就可使用静态方法引用
  2. 实例方法引用:若是函数式接口的实现刚好能够经过调用一个实例的实例方法来实现,那么就可使用实例方法引用
  3. 对象方法引用:抽象方法的第一个参数类型恰好是实例方法的类型,抽象方法剩余的参数刚好能够当作实例方法的参数。若是函数式接口的实现能由上面说的实例方法调用来实现的话,那么就可使用对象方法引用
  4. 构造方法引用:若是函数式接口的实现刚好能够经过调用一个类的构造方法来实现,那么就可使用构造方法引用
相关文章
相关标签/搜索