Java基础小结

1. Java简介

1.1 语言起源

  • Java是SUN1995年推出的一门高级编程语言
  • 2004年,J2SE1.5发布,成为Java语言发展史上的又一里程碑
  • 2009年,Oracle收购SUN,取得Java的版权
  • 2011年,Oracle公司发布java7的正式版

1.2 Java语言重要特性之跨平台

  • 跨平台:即不依赖于操做系统,也不依赖硬件环境。
  • Java的跨平台的原理:Java的跨平台是经过Java虚拟机(JVM)来实现的。

1.3 Java的三大平台

平台 简介
Java SE Java SE(Java Platform,Standard Edition)。Java SE 之前称为J2SE。它是容许开发和部署在桌面、服务器、嵌入式环境和实时环境中使用的Java 应用程序。Java SE 包含了支持Java Web 服务开发的类,并为Java Platform,Enterprise Edition(Java EE)提供基础。
Java EE Java EE(Java Platform,Enterprise Edition)。这个版本之前称为J2EE。企业版本帮助开发和部署可移植、健壮、可伸缩且安全的服务器端 Java 应用程序。Java EE 是在Java SE 的基础上构建的,它提供Web 服务、组件模型、管理和通讯API,能够用来实现企业级的面向服务体系结构(service-oriented architecture,SOA)和Web 2.0 应用程序。
Java ME Java ME(Java Platform,Micro Edition)。这个版本之前称为J2ME,也叫K-JAVA。Java ME 为在移动设备和嵌入式设备(好比手机、PDA、电视机顶盒和打印机)上运行的应用程序提供一个健壮且灵活的环境。Java ME 包括灵活的用户界面、健壮的安全模型、许多内置的网络协议以及对能够动态下载的连网和离线应用程序的丰富支持。基于Java ME 规范的应用程序只需编写一次,就能够用于许多设备,并且能够利用每一个设备的本机功能。
Java Card* 支持一些Java小程序(Applets)运行在小内存设备(如智能卡)上的平台

2. Java基础部分(基本语法,Java特性等)

2.1 标识符

  • 什么是标识符

就是程序员在定义Java程序时,自定义的一些名字html

  • 标识符定义规则
  1. 标识符由26个英文字符大小写(a~zA~Z)、数字(0~9)、下划线(_)和美圆符号($)组成。
  2. 不能以数字开头,不能是关键字
  3. 严格区分大小写
  4. 标识符的能够为任意长度
  • 标识符命名规范
  1. 包名: 多个单词组成时全部字母小写(例:package com.zeng)
  2. 类名和接口: 多个单词组成时全部单词的首字母大写(例:HelloWorld)
  3. 变量名和函数名: 多个单词组成时第一个单词首字母小写,其余单词首字母大写(例:lastAccessTime、getTime)。
  4. 常量名: 多个单词组成时,字母所有大写,多个单词之间使用(_)分隔(例:INTEGER_CACHE)

2.2 常量和变量

2.2.1 常量

常量的分类java

  1. 整数常量:全部整数
  2. 小数常量:全部小数
  3. 布尔常量:只有true和false
  4. 字符常量:使用‘’引发来的单个字符
  5. 字符串常量:使用“”引发来的字符序列
  6. null常量:只有一个值null

char类型程序员

  1. char类型表示的是单个字符类型。
  2. 注意:特殊字符的转义序列:转义字符
    • 特殊字符使用”\”把其转化成字符的自己输出,那么使用”\”的字符称做为转义字符。
    • 常见转义字符
      • 转义字符 名称 Unicode
      • \b Backspace (退格键) \u0008
      • \t Tab (Tab键盘) \u0009
      • \n Linefeed (换行) \u000A
      • \r Carriage Return(回车) \u000D
      • \ Backslash (反斜杠) \u005C
      • ' Single Quote (单引号) \u0027
      • " Double Quote (双引号) \u0022

Boolean类型算法

2.2.2 变量

变量的概述 用于存储可变数据的容器。编程

  • 变量的数据类型
  1. 整型
    • byte 表明一个字节的大小 8bit -128~127
    • short 表明两个字节的大小 16bit -2^(15)~2^(15)-1
    • int 表明四个字节的大小 32bit -2^(31)~2^(31)-1
    • long 表明八个字节的大小 64bit -2^(63)~2^(63)-1
    • 若是一个数值没有采起特殊的处理,那么该整数默认的类型是int。
    • 可使用数值后面添加L或小写l改变默认的整数类型。
  2. 浮点型
    • float 表明四个字节的大小 32bit
    • double 表明八个字节的大小 64bit
    • java程序中全部的小数默认的类型是double类型,因此须要使用特殊的符号改变默认的小数类型。
  3. 字符型
    • char 表明两个字节的大小 16bit
      原理:将字符映射为码表中对应的十进制数据加以存储。
  4. 布尔型
    • boolean 占一个字节。只有true与false两个值。
  • 变量的声明
  • 格式: 数据类型 变量名字1 , 变量名字2 ,……, 变量名字n;
  • 备注:变量名的首字母都通常都是以小写字母开始。
  • 变量的初始化
  • 初始化方式1: 数据类型 变量名字 = 数值。
  • 初始化方式2: 数据类型 变量名字 , 变量名字 = 数值

2.3 数据类型

  • 基本数据类型
  • 引用数据类型
  • 数据类型的转换
    1. 自动类型转换(也叫隐式类型转换)
      • 要实现自动类型的转换,须要知足两个条件
        • 第1、两种类型彼此兼容
        • 第2、目标类型取值范围必须大于源类型
      • 全部的数字类型,包括整形和浮点型彼此均可以进行转换。
    2. 强制类型转换(也叫显式类型转换)
      • 当两种类型彼此不兼容,或者目标类型取值范围小于源类型(目标是byte,源是int)没法自动转换,此时就须要进行强制类型转换。
    3. 表达式的数据类型自动提高
      • 算术表达式,逻辑表达式
      • 全部的byte型、short型和char的值将被提高到int型。
      • 若是一个操做数是long型,计算结果就是long型;
      • 若是一个操做数是float型,计算结果就是float型;
      • 若是一个操做数是double型,计算结果就是double型。
    4. java基本数据类型转换

2.4 运算符

  • 算数运算符 小程序

  • 赋值运算符数组

    运算符 运算 范例 结果
    = 赋值 a=3,b=2 a=3,b=2
    += 加等于 a=3,b=2;a+=b; a=5,b=2;
    -= 减等于 a=3,b=2,a-=b; a=1,b=2;
    *= 乘等于 a=3,b=2,a*=b; a=6,b=2
    /= 除等于 a=3,b=2,a/=b; a=1,b=2;
    %= 模等于 a=3,b=2,a%=b; a=1,b=2
  • 比较运算符安全

    运算符 运算 范例 结果
    == 相等于 4 == 3 false
    != 不等于 4 != 3 true
    < 小于 4 < 3 false
    > 大于 4 > 3 true
    <= 小于等于 4 <= 3 false
    >= 大于等于 4 >= 3 true
    instanceof 检查是不是类的对象 "hello" instanceof String true
    • 注意的细节

      使用比较运算符的时候,要求两种数据类型必须一致
      byte、short、char 会自动提高至int服务器

  • 逻辑运算符网络

  • 注意

    1. “&”和“&&”的区别
      单与时,左边不管真假,右边都进行运算;双与时,若是左边为真,右边参与运算,若是左边为假,那么右边不参与运算。
    2. “|”和“||”的区别
      同理,双或时,左边为真右边不参与运算。
    3. “ ^ ”异或与“|”或的不一样之处
      当左右都为true时,结果为false
  • 位运算符

    位运算符 运算符含义
    & 与(AND)
    | 或(OR)
    ^ 异或
    ~ 取反
    当参与取反的数值是正数时,把对应的值加上负号,再-1;
    当参与取反的数值是负数时,把对应的值加上负号,再-1;
    负数的表现形式就是对应的正数取反,再加1。负数的最高位确定是1.
  • 移位运算符

    运算符 运算 范例 注意
    << 左移 3 << 2 --> 3*2*2=12 空位补0,被移除的高位丢弃,空缺位补0
    >> 右移 3 >> 1 --> 3/2=1 被移位的二进制最高位是0,右移后,空缺位补0; 最高位是1,空缺位补1
    >>> 无符号右移 3 >>> 1 --> 3/2=1 被移位二进制最高位不管是0或者是1,空缺位都用0补
  • 三元运算符

    格式 (条件表达式) ? 表达式1 :表达式2;

  • 运算符的优先级与结合性

2.5 流程控制语句

  • if else
  • switch
    • switch语句选择的类型只有四种:byte,short,int, char。
      • jdk 1.7容许switch中有String变量和文本
    • case之间与default没有顺序。先判断全部的case,没有匹配的case执行default。
    • switch语句中止的条件是遇到了break关键字或者结束switch语句的大括号。
    • 若是匹配的case或者default没有对应的break,那么程序会继续向下执行,运行能够执行的语句,直到遇到break或者switch结尾结束。
    • switch case中的值必需要与switch表达式的值具备相同的数据类型。并且case后跟的值必须是常量,不能跟变量。
  • while,do while
  • for循环
    • for和while区别
      1. for里面的两个表达式运行的顺序,初始化表达式只读一次,判断循环条件,为真就执行循环体,而后再执行循环后的操做表达式,接着继续判断循环条件,重复整个过程,直到条件不知足为止。
      2. while与for能够互换,区别在于for为了循环而定义的变量在for循环结束时就在内存中释放。而while循环使用的变量在循环结束后还能够继续使用。
      3. 最简单无限循环格式:while(true) , for(;;),无限循环存在的缘由是并不知道循环多少次,而是根据某些条件来控制循环。推荐使用while(true)
  • break、continue关键字

方法(函数)

  • 格式
修饰符 返回值类型 函数名(参数类型 形式参数1,参数类型 形式参数2,…)
	{
		执行语句;
		return 返回值;
	}
复制代码

返回值类型: 运行这段程序得出的一个运算结果类型,若是函数没有返回值,则用void来表示该函数没有返回值。
函数名:仅仅是一个标识符,能够随意起名字。
形式参数:是一个变量,用于存储调用函数传递进来的实际参数。
实际参数:传递给形式参数的具体数值。
返回值: 返回给调用者。

  • 特色
    • 定义函数能够将功能代码进行封装
    • 便于对该功能进行复用
    • 函数只有被调用才会被执行
    • 函数的出现提升了代码的复用性
    • 对于函数没有具体返回值的状况,返回值类型用关键字void表示,那么该函数中的return语句若是在最后一行能够省略不写。
    • 注意:函数中只能调用函数,不能够在函数内部定义函数。
  • 重载
    • 定义

      在同一个类中,有一个以上的同名函数,只要函数的参数列表或参数类型不同便可,与返回值无关, 这些统称为方法的重载。

    • 缘由

      为了加强方法的阅读性,优化了程序设计。

2.6 数组

2.7 注释

  • 注释的做用

经过注释提升程序的可读性,使java程序的条理更加清晰,易于区分代码行与注释行。另外一般在程序开头加入做者,时间,版本,要实现的功能等内容注释,方便后来的维护以及程序员的交流。

  • 注释的种类
    • 单行注释(line comment)用//表示,编译器看到//会忽略该行//后的全部文本
    • 多行注释(block comment)用/**/表示,编译器看到/*时会搜索接下来的*/, 忽略掉/**/之间的文本。
    • 文档注释用/** */表示,是java特有的注释,其中注释内容能够被JDK提供的工具 javadoc 所解析,生成一套以网页文件形式体现的该程序的说明文档。
    • 文档注释
      1. 须要使用sun给咱们提供的javadoc工具生成一个html的说明文档。
      2. 只能抽取public的属性或者方法内容。
      3. 格式: javadoc –d 指定存储文档的路径 -version –author(可选) 目标文件

3. 关键字

3.1 常见的关键字

3.2 关键字分类

3.3 全部关键字

  • 备注:goto是Java的保留关键字,意思是Java并无使用goto,之后是否使用未定

4. 面向对象

4.1 面向对象思想

4.1.1 面向对象的描述

  • 【面向对象】(Object Oriented,简称OO),是一种以事物为中心的编程思想;
  • 【面向对象程序设计】(Object Oriented Programming,简称OOP),是一种程序开发的方法。它将对象做为程序的基本单元,将程序和数据封装其中,以提升软件的重用性、灵活性和扩展性。
  • 【面向过程】(Procedure Oriented,简称PO)是一种以过程为中心的编程思想,强调的是功能行为。

4.1.2 面向对象的特征

  • 【封装】(encapsulation):

    把客观事物封装成抽象的类,而且类能够把本身的数据和方法只让可信的类或对象操做,对不可信的进行信息隐藏。

  • 【继承】(inheritance):

    继承是指一种能力:它可使用现有的类的全部功能,并在无需从新编写原来的类的状况下对这些功能进行扩展。

  • 【多态】(polymorphism)

    定义时的类型和运行时的类型不同,此时就成为多态。
    是容许你将父对象设置成一个或更多的他的子对象相等的技术,赋值以后,父对象就能够根据当前赋值给它的子对象的特性以不一样的方式运做。
    简单的说,就是一句话:容许将子类类型的指针赋值给父类类型的指针。

4.1.3 面向对象的五大基本原则

  1. 单一职责原则(SRP)

    一个类的功能要单一,不能一应俱全

  2. 开放封闭原则(OCP)

    一个模块在扩展性方面是开放的,对更改性方面是封闭的

  3. 里氏替换原则(LSP)

    子类应当替换父类,并出现个在父类可以出现的全部位置

  4. 依赖倒置原则(DIP)

    具体依赖抽象,上层依赖下层

  5. 接口隔离原则(ISP)

    模块间要经过抽象接口隔开,而不是经过具体的类强行耦合起来

4.2 类与对象

4.2.1 【类】

实际就是对某种类型事物的共同特性与行为的抽取

4.2.2 【对象】

在现实生活中存在的一个具体的事物

4.3 封装

封装的好处

  1. 隐藏了类的具体实现
  2. 操做简单
  3. 提升对象数据的安全性

4.4 继承

4.4.1 特色

  1. 描述类和类之间的关系
  2. 下降类和类之间的重复代码

4.4.2 extends关键字

4.4.3 继承细节

  • 类名的设定

    被继承的类称之为父类(基类),继承的类称之为子类

  • 子类并不能继承父类中全部的成员
    • 父类定义完整的成员:静态成员、非静态、构造函数。静态变量和静态方法均可以经过子类名.父类静态成员的形式调用
    • 全部的私有成员不能继承
    • 构造函数不能继承

4.4.4 super关键字

  • 做用
    1. 主要存在于子类方法中,用于指向子类对象中的父类对象
    2. 访问父类的属性
    3. 访问父类的函数
    4. 访问父类的构造函数
  • 注意
    1. this和super很像,this指向的是当前对象的调用,super指向的是当前调用对象的父类。this和super只能在有对象的前提下使用,不能在静态上下文使用
    2. 子类的构造函数第一行会默认调用父类无参的构造函数,隐式语句
    3. 若是显式调用父类函数,编译器自动添加的调用父类无参构造函数就会消失。构造函数间的调用只能放在第一行,只能调用一次。super和this不能同时存在构造函数第一行

4.4.5 重写(override)

  • 定义

    在继承中,能够定义和父类名称相同且参数列表一致的函数,称之为函数的重写

  • 前提

    必需要有继承关系

  • 特色
    1. 当子类重写父类的函数,那么子类的对象若是调该函数,调用的必定是重写后的函数;
    2. 可经过super关键字进行父类方法的调用;
    3. 子类可经过继承将父类的方法加强
  • 细节
    1. 函数名、参数列表必须相同
    2. 子类重写父类的函数时,函数的访问权限必须大于或等于父类的访问权限,不然编译报错
    3. 子类返回值类型必须是父类函数返回值类型或该返回值类型的子类,不能返回比父类更大的数据类型

4.4.6 子类对象查找属性或方法时的顺序

原则:就近原则 若是子类的对象调用方法,默认先使用this进行查找,若是当前对象没有找到属性或方法,找当前对象中维护的super关键字指向的对象,若是尚未找到则编译报错,找到直接调用

4.4.7 重载和重写的区别

  • 重载

    前提 全部重载函数必须在同一个类中
    特色 函数名相同,参数列表不一样,与其余无关(访问控制符、返回值类型)
    不一样 个数不一样、顺序不一样、类型不一样

  • 重写

    前提 继承
    特色 函数名、参数列表必须相同;子类的返回值类型要等于或小于父类的返回值类型

4.4.8 instanceof关键字

  • 做用

    比较运算符:用来判断一个对象是否属于指定类的对象

  • 用法 对象 instanceof 类
  • 注意

    使用instanceof关键字作判断时,两个类之间必须有关系

4.4.9 final关键字

  • 修饰成员属性

    说明成员属性是常量,不能被修改,且必须赋初值

  • 修饰类
    1. 该类是最终类,不能被继承
    2. 防止代码功能被重写
    3. 该类没有必要扩展
  • 修饰方法
    1. 该方法是最终方法,不能被重写
    2. 当一个类被继承,那么全部的非私有函数都将被继承,若是函数不想被子类继承并重写,能够用该final修饰
    3. 当一个类中的函数都被修饰为final时,能够将类定义为final的
    4. 编译时尝试将该函数内联,提升运行效率
  • 修饰形参
    1. 当形参被修饰为final,那么该形参在所属的方法中不能被修改
    2. 项目中主要用于一些只用来遍历未知数据的函数。将位置变量声明为final的。加强数据的安全性

4.4.10 Java取消多继承

  • 多继承虽然能使子类同时拥有多个父类的特征,但其缺点也是显著的,主要有两方面
    1. 若是在一个子类继承的多个父类中拥有相同名字的实例变量,子类在引用该变量时将产生歧义,没法判断应该使用哪一个父类的变量;
    2. 若是在一个子类继承的多个父类中拥有相同方法,子类中又没有覆盖该方法,那么调该方法时将产生歧义,没法判断应该调用哪一个父类的方法
  • 注意
    1. 子类将继承父类全部的数据域和方法。静态方法能够继承,可是不能重写;私有方法能够继承,只是不能调用
    2. java类是单继承,接口能够实现多继承

4.5 多态

  • 多态的概念

    所谓多态就是指一个类实例的相同方法在不一样情形下有不一样的表现形式,多态机制使具备不一样内部结构的对象能够共享相同的外部接口

  • 多态体现
    1. 父类和子类有相同的成员变量,多态下访问的是父类的成员变量;
    2. 当父类和子类具备相同的非静态方法(就是子类重写父类的非静态方法),多态下访问的是子类的成员方法;
    3. 当父类和子类具备相同的静态方法(就是子类重写父类的静态方法),多态下访问的是父类的静态方法

4.6 成员变量和局部变量

  • 成员变量属于对象,它存储在堆内,堆内的实体,当没有引用指向其时,才垃圾回收清理;
  • 局部变量存在栈内存中,当再也不使用时,立刻就会被释放。

4.7 匿名对象

  • 概念

    没有名字的实体,也就是该实体没有对应的变量名引用

  • 用途
    1. 当对象对方法进行一次调用的时候,可使用匿名对象对代码进行简化
    2. 匿名对象能够做为实参进行传递
  • 注意

    匿名对象的属性没法获取,由于没有引用变量指向该对象

4.8 构造方法

  • 构造方法与普通函数的区别
    1. 通常函数是用于定义对象应该具有的功能。而构造函数定义的是,对象在调用功能以前,在创建时,应该具有的一些内容,也就是对象的初始化内容。
    2. 构造函数是在对象创建时由JVM调用,对对象初始化。通常函数是对象创建后,当对象调用该功能时才会执行。
    3. 普通函数可使用对象屡次调用,构造函数只在对象建立时调用。
    4. 构造函数的函数名要与类名同样,而普通的函数只要符合标识符的命名规则便可。
    5. 构造函数没有返回值类型。
  • 构造函数注意的细节
    1. 当类中没有定义构造函数时,系统会指定给该类加上一个空参数的构造函数。这个是类中默认的构造参数。当类中若是定义类构造函数,这时默认的构造函数就没有了
    2. 在一个类中能够定义多个构造函数,以进行不一样的初始化。多个构造函数存在于类中,是以重载的形式体现的,由于构造函数的名称都相同
  • 构造代码块
    • 做用

      给全部的对象进行统一的初始化

    • 与构造函数的区别

      构造代码块是给全部对象进行统一初始化,构造函数给对应的对象进行初始化

  • 静态代码块

    随着类的加载而加载。只执行一次,优先于主函数。用户给类进行初始化

4.9 this关键字

  • 概念

    this关键字表明的是对象的引用。即this指向一个对象,所指向的对象就是调用该函数的对象引用。

  • 注意
    1. this只能在非静态(没有static修饰的)函数中使用;
    2. 构造函数相互调用必须放在构造函数的第一个语句,不然编译报错;
    3. 能够解决构造函数中对象属性和函数形参的同名问题。

4.10 static关键字

  • 做用

    实现对象之间重复属性的数据共享

  • 使用

    主要用于修饰类的成员

    • 成员变量
      1. 非静态成员变量:须要建立对象来访问
      2. 静态成员变量:使用类名直接调用,也能够经过对象访问
    • 成员方法
      1. 静态函数
        静态函数中不能访问非静态成员变量,只能访问静态变量
        静态方法不能够出现this,super关键字
        由于静态优先于对象存在
      2. 非静态函数
        非静态函数中能够访问静态成员变量
    • 静态代码块
  • 特色
    1. 静态会随着类的加载而加载,随着类的消失而消失。声明周期很长
    2. 优先于对象而存在
    3. 被全部实例(对象)所共享
    4. 能够直接被类名调用
  • 优缺点
    • 优势:对对象的共享数据进行单独空间的存储,节省空间
    • 缺点:生命周期过长,访问出现局限性(静态只能访问静态)
  • 静态变量(类变量)和实例变量的区别
    • 存放位置
      1. 类变量随着类的加载而加载存在于方法区中
      2. 实例变量随着对象的创建而存在于堆内存中
    • 声明周期
      1. 类变量生命周期最长,随着类的消失而消失
      2. 实例变量生命周期随着对象的消失而消失
  • 应用

    自定义数据工具箱

4.11 内部类

基础

  • 成员内部类
    • 访问方式
      1. 内部类能够直接访问外部类的成员属性和成员方法(包括private成员和静态成员)
      2. 外部类须要访问内部类的成员属性时,须要建立内部类的对象
        • 在外部类的成员函数中建立内部类的对象,经过内部类对象直接访问内部类的成员
        • 在其余类中直接建立内部类的对象:
          • 第一种方式:Outer outer = new Outer(); Outer.Inner inner = outer.new Inner();// 必须经过Outer对象来建立
          • 第二种方式:Outer.Inner inner1 = outer.getInnerInstance();
      3. 若是要访问外部类的同名成员,须要如下面的形式进行访问
        • 外部类.this.成员变量
        • 外部类.this.成员方法
      4. 内部类能够拥有private访问权限、protected访问权限、public访问权限和包访问权限
    • 优点

      成员内部类做为外部类的成员,那么能够访问外部类的任意成员

    • 特色
      1. 私有的成员内部类:不能在其余类中直接建立内部类对象来访问
      2. 静态的成员内部类:若是内部类中包含静态成员,那么Java规定内部类必须声明为静态的
      3. 访问静态内部类的格式:Outer.Inner in = new Outer.Inner()
  • 局部内部类
    • 访问方式

      能够直接在包含局部内部类的方法中建立局部内部类的对象,调用局部内部类的成员

    • 特色
      1. 不能使用任何的访问修饰符
      2. 会生成两个.class文件,一个是Outer.class,另外一个是Outer$LocalInner.class
      3. 局部内部类只能访问方法中声明的final类型的变量(能够访问获取值,可是不能修改,系统会默认添加final属性)
    • 缘由
      1. 由于局部内部类最终会被编译为一个单独的类,其所访问的局部变量会成为这个类的属性
      2. 若是访问的一个值类型局部变量,就会形成这个类的属性与所访问的局部变量不是同一个,会形成数据不一样步
      3. 因此强制要求局部变量必须为final,避免数据不一样步
  • 匿名内部类

    就是没有类名字的内部类
    通常使用匿名内部类的方法来编写事件监听代码
    匿名内部类也是不能有访问修饰符和static修饰符的
    匿名内部类是惟一一种没有构造器的类

    • 做用

      简化内部类书写

    • 前提:

      必须继承一个类或者是实现一个接口

    • 注意细节

      使用匿名内部类时,若是须要调用匿名内部类的两个方法或者两个方法以上,可使用变量指向该对象

  • 静态内部类

    静态内部类是不须要依赖于外部类的,这点和类的静态成员属性有点相似,而且它不能使用外部类的非static成员变量或方法

深刻理解内部类

  • 为何局部内部类和匿名内部类只能访问局部final变量?

    背景:当test方法执行完毕以后,变量a的生命周期就结束了,而此时Thread对象的生命周期极可能尚未结束,那在再Thread的run方法中继续访问变量a就变成了不可能了,可是又要实现这样的效果,怎么办呢?Java采用了【复制】的手段来解决这个问题

    方案:也就是说若是局部变量的值在编译期间就能够肯定,则直接在匿名内部里面建立一个拷贝。若是局部变量的值没法在编译期间肯定,则经过构造器传参的方式来对拷贝进行初始化赋值。
    解决:java编译器就限定必须将入参变量限制为final变量

4.12 抽象类

当描述一个类的时候,若是不能肯定功能函数如何定义,那么该类就能够定义为抽象类,功能函数应该描述为抽象函数

  • 特色
    1. 有抽象函数的类,该类必定是抽象类
    2. 抽象类中不必定要有抽象函数
    3. 抽象类不能使用new建立对象
    4. 编译器强制子类实现抽象类父类的未实现的方法
    5. 能够不实现,前提是子类的也要声明为抽象的
  • 优势
    1. 提升代码的复用性
    2. 提升代码的扩展性,便于后期的代码维护
  • 构造函数

    抽象类中必定有构造函数,主要为了初始化抽象类中的属性,一般由子类实现

  • 注意细节
    1. 抽象类能够没有抽象方法
    2. 抽象类能够继承普通类与抽象类
    3. 抽象类不能直接使用类名建立实例,可是有构造方法,构造方法是让子类进行初始化
    4. 抽象类必定有构造方法
    5. abstract与其余修饰符的关系
      • final与abstract不能共存:
        final:它的做用是修饰类表明不能够继承,修饰方法不可重写;
        abstract:修饰类就是用来被继承的,修饰方法就是用来重写的;
      • static与abstract不能共存:
        abstract修饰的方法没有具体的方法实现,因此不能直接调用
        static修饰的方法能够用类名调用
      • private与abstract不能共存:
        private修饰的只能在本类中使用
        abstract方法是用来被子类进行重写的,有矛盾

4.13 接口

Java中的接口主要是用来拓展定义类的功能,能够弥补Java中单继承的缺点

  • 接口的定义格式
interface 接口名{
	属性;
	抽象方法;
}
复制代码
  • 注意

    接口中的全部属性,默认的修饰符是public static final
    接口中的全部方法,默认的修饰符是public abstract

  • 接口的特色
    1. 类实现接口能够经过implements实现,实现接口的时候必须把接口中的全部方法实现,一个类能够实现多个接口;
    2. 接口中定义的全部属性默认是public static final的,即静态常量,因此定义的时候必须赋值;
    3. 接口中定义的方法不能有方法体,接口中定义的方法默认添加public abstract;
    4. 有抽象函数的不必定是抽象类,也能够是接口;
    5. 因为接口中的方法默认都是抽象的,因此不能被实例化;
    6. 对于接口而言,可使用子类来实现接口中未被实现的功能函数;
    7. 若是实现类中要访问接口中的成员,不能使用super关键字。由于二者之间没有显式继承关系,何况接口中成员属性是静态的。可使用接口名直接访问。
    8. 接口没有构造方法。
  • 接口与类之间的关系

    接口与类之间是实现关系。非抽象类实现接口时,必须把接口里面的全部方法实现。类与接口之间是能够多实现的(即一个类能够实现多个接口)。

4.14 接口和抽象类的区别

4.15 包机制

  • 使用

    package 包名

  • 包的优势
    1. 防止类文件冲突;
    2. 使源文件与类文件分离,便于软件最终发布。
  • 注意细节
    1. 一个Java类只能定义在一个包中;
    2. 包语句确定是描述类的第一条语句。
  • 包机制引起的问题

    有了包以后,每次访问类都须要把包名和类名写全。

    • 解决办法: import 包名.类名
  • 注意细节

    from xx import *;
    使用“*”不能导入包中子类包的class文件; import语句能够是多条的。

4.16 访问修饰符

  • 修饰类成员
    1. 成员使用private修饰,只在本类中使用;
    2. 若是一个成员没有使用任何修饰符,就是default,该成员能够被包中的其余类访问;
    3. 成员被protected修饰,能够被包中其余类访问,而且位于同一个包中的子类也能够访问;
    4. public修饰的成员能够被全部类访问。
  • 修饰类
    1. 类只有两种:public和默认(成员内部类可使用private);
    2. 父类不能够是private和protected,子类没法继承;
    3. public类能够被全部类访问;
    4. 默认类只能被同一个包中的类访问。

4.17 jar包

jar包就是打包文件
jar包是一种打包文件java active file,与zip兼容,称之为jar包

  • jar命令
    1. jar工具存放在jdk的bin目录中(jar.exe);
    2. jar工具:主要用于对class文件进行打包(压缩);
    3. dos中输入jar查看帮助
  • 详细命令
    jar cvf test.jar cn
      1:jar cf test.jar cn 在当前目录生成test.jar 文件,没有显示执行过程
      2:jar cvf test.jar cn 显示打包中的详细信息
      3:jar tf test.jar  显示jar文件中包含的全部目录和文件名
      4:jar tvf test.jar 显示jar文件中包含的全部目录和文件名大小,建立时间详细信息
      5:jar xf test.jar  解压test.jar到当前目录,不显示信息
      6:jar xvf test.jar 解压test.jar到当前目录,显示详细信息
      7:可使用WinRaR进行jar解压
      8;将两个类文件归档到一个名为 test2.jar 的归档文件中:
      	jar cvf test2.jar Demo3.class Demo4.class
      9:重定向
      	1:tvf能够查看jar文件内容,jar文件大,包含内容多,dos看不全。
      	2:查看jdk中的rt.jar 文件 jar tvf rt.jar
      	3:jar tvf rt.jar>d:\rt.txt
    复制代码

5 集合部分

5.1 什么是集合?

存储对象的容器,集合中能够存储任意类型的对象,并且长度可变

5.2 集合和数组的区别

  • 数组和集合类都是容器
  • 数组长度是固定的,集合长度是可变的。
  • 数组中能够存储基本数据类型,集合只能存储对象;
  • 数组中存储数据类型是单一的,集合中能够存储任意类型的对象。

5.3 集合类的特色

用于存储对象,长度是可变的,能够存储不一样类型的对象

5.4 集合的分类

5.4.1 集合类的继承实现关系

5.4.2 Collection

Collection描述的是集合公有的功能(CURD)

  • Collection接口的共性方法
    • 增长

      add 将指定对象存储到容器中; add 方法的参数类型是Object 便于接收任意对象
      addAll 将指定集合中的元素添加到调用该方法和集合中

    • 删除

      remove() 将指定的对象从集合中删除
      removeAll() 将指定集合中的元素删除

    • 修改

      clear() 清空集合中的全部元素

    • 判断

      isEmpty() 判断集合是否为空
      contains() 判断集合何中是否包含指定对象
      containsAll() 判断集合中是否包含指定集合
      equals()判断两个对象是否相等

    • 获取

      int size() 返回集合容器的大小

    • 转成数组

      toArray() 集合转换数组

  • List:有存储顺序,可重复
  • List特有的方法
    • 增长

      void add(int index, E element) 指定位置添加元素
      boolean addAll(int index, Collection c) 指定位置添加集合

    • 删除

      E remove(int index) 删除指定位置元素

    • 修改

      E set(int index, E element) 返回的是须要替换的集合中的元素

    • 查找

      E get(int index) 注意: IndexOutOfBoundsException
      int indexOf(Object o) // 找不到返回-1
      lastIndexOf(Object o)

    • 取子集合

      List subList(int fromIndex, int toIndex) // 不包含toIndex

  • ArrayList(数组实现,查找快,增删慢)
    • 原理
      1. 数组的内存空间地址是连续的。
      2. ArrayList底层维护了一个Object[] 用于存储对象,默认数组的长度是10。能够经过 new ArrayList(20)显式的指定用于存储对象的数组的长度。当默认的或者指定的容量不够存储对象的时候,容量自动增加为原来的容量的1.5倍。
      3. 因为ArrayList是数组实现, 在增和删的时候会牵扯到数组增容, 以及拷贝元素. 因此慢。数组是能够直接按索引查找, 因此查找时较快。
  • LinkedList(链表实现,增删快,查找慢)
    • 原理
      1. 因为LinkedList在内存中的地址不连续,须要让上一个元素记住下一个元素.因此每一个元素中保存的有下一个元素的位置.虽然也有角标,可是查找的时候,须要从头往下找,显然是没有数组查找快的。可是,链表在插入新元素的时候,只须要让前一个元素记住新元素,让新元素记住下一个元素就能够了.因此插入很快。
      2. 因为链表实现, 增长时只要让前一个元素记住本身就能够, 删除时让前一个元素记住后一个元素, 后一个元素记住前一个元素. 这样的增删效率较高。
      3. 但查询时须要一个一个的遍历, 因此效率较低。
    • 特有的方法
      1. addFirst(E e)
      2. addLast(E e)
      3. getFirst()
      4. getLast()
      5. removeFirst()
      6. removeLast()
      7. element() 获取但不移除列表的头;若是集合中没有元素,获取或者删除元素抛出:NoSuchElementException
        • push()
        • pop()
      8. 队列(双端队列)
        • offer()
        • poll()
        • descendingIterator() 返回逆序的迭代器对象
  • ArrayList和LinkedList的存储查找的优缺点
    • ArrayList 是采用动态数组来存储元素的,它容许直接用下标号来直接查找对应的元素。可是,可是插入元素要涉及数组元素移动及内存的操做。

      总结:查找速度快,插入操做慢。

    • LinkedList 是采用双向链表实现存储,按序号索引数据须要进行前向或后向遍历,可是插入数据时只须要记录本项的先后项便可,因此插入速度较快
  • Set:无存储顺序,不可重复
    • 对象的相等性:hashCode和equals
      1. equals为true==>hashCode相等,两个对象相等
      2. hashCode不相等==>equals为false,两个对象不相等
      3. hashCode相等==>equals不必定为true,两个不一样的对象可能会有相同的hash值(哈希碰撞)
    • ==和equals的区别
      1. ==是运算符,用于比较两个变量是否相等,基本类型用==,比较的是它们的值,对象用==,比较的是内存地址,对象类型不一样返回false
      2. equals是进行逻辑比较,因此一般须要重写该方法来提供逻辑一致性的比较
  • HashSet

    线程不安全,存取速度快,底层是以哈希表实现的

    • HashSet不存入重复元素:

      元素的哈希值是经过元素的hashcode方法 来获取的, HashSet首先判断两个元素的哈希值,若是哈希值同样,接着会比较equals方法 若是 equls结果为true ,HashSet就视为同一个元素。若是equals 为false就不是同一个元素。

      哈希值相同equals为false的元素是怎么存储呢,就是在一样的哈希值下顺延(能够认为哈希值相同的元素放在一个哈希桶中)。也就是哈希同样的存一列。

    • HashSet的add()方法的返回值是Boolean类型,元素重复则添加失败,返回false;元素不重复则添加成功,返回true。

  • TreeSet

    红-黑树的数据结构,默认对元素进行天然排序(String),若是在比较的时候两个对象返回值为0,那么元素重复。

    • 红黑树

      红黑树是一种特定类型的二叉树

      红黑树的算法规则:左小右大

    • TreeSet的排序规则

      1)让存入的元素自定义比较规则
      2)给TreeSet指定排序规则

      • 方式一:元素自身具有比较性 元素自身具有比较性,须要元素实现Comparable接口,重写compareTo方法,也就是让元素自身具有比较性,这种方式叫作元素的天然排序也叫作默认排序。
      • 方式二:容器具有比较性 当元素自身不具有比较性,或者自身具有的比较性不是所须要的。那么此时可让容器自身具有。须要定义一个类实现接口Comparator,重写compare方法,并将该接口的子类实例对象做为参数传递给TreeMap集合的构造方法。
      • 注意 当Comparable比较方式和Comparator比较方式同时存在时,以Comparator的比较方式为主;
        在重写compareTo或者compare方法时,必需要明确比较的主要条件相等时要比较次要条件。(假设姓名和年龄一直的人为相同的人,若是想要对人按照年龄的大小来排序,若是年龄相同的人,须要如何处理?不能直接return 0,由于可能姓名不一样(年龄相同姓名不一样的人是不一样的人)。此时就须要进行次要条件判断(须要判断姓名),只有姓名和年龄同时相等的才能够返回0.)
  • LinkedHashSet

    会保存插入的顺序

  • Vector:线程安全
    • 比较

      ArrayList: 单线程效率高;
      Vector: 多线程安全的,因此效率低。

    • 特有的方法

      void addElement(E obj) 在集合末尾添加元素
      E elementAt( int index) 返回指定角标的元素
      Enumeration elements() 返回集合中的全部元素,封装到Enumeration对象中

  • Enumeration 接口

    boolean hasMoreElements() 测试此枚举是否包含更多的元素。
    E nextElement() 若是此枚举对象至少还有一个可提供的元素,则返回此枚举的下一个元素。

5.4.3 迭代器

对 Collection 进行迭代的类,称其为迭代器

  • Iterable

    Collection的父接口. 实现了Iterable的类就是可迭代的.

  • Iterator

    Iterator iterator() 返回该集合的迭代器对象

    • Iterator接口定义的方法
      1. boolean hasNext() 判断集合中是否有元素,若是有元素能够迭代,就返回true。
      2. E next() 返回迭代的下一个元素,注意: 若是没有下一个元素时,调用next元素会抛出NoSuchElementException
      3. void remove() 从迭代器指向的集合中移除迭代器返回的最后一个元素(可选操做)。
      4. 使用迭代器清空集合
      Iterator it = coll.iterator();
       while (it.hasNext()) {
           it.next();
           it.remove();
       }
      复制代码
    • 细节
      1. 若是迭代器的指针已经指向了集合的末尾,那么若是再调用next()会返回NoSuchElementException异常
      2. 若是调用remove以前没有调用next是不合法的,会抛出IllegalStateException
      3. 注意在对集合进行迭代过程当中,不容许出现迭代器之外的对元素的操做,由于这样会产生安全隐患,java会抛出异常并发修改异常(ConcurrentModificationException),普通迭代器只支持在迭代过程当中的删除动做。
      • ConcurrentModificationException: 当一个集合在循环中即便用引用变量操做集合又使用迭代器操做集合对象, 会抛出该异常。
    • List特有的迭代器【ListIterator】
      1. public interface ListIterator extends Iterator
      2. ListIterator listIterator()
      3. 方法
        • add(E e) 将指定的元素插入列表(可选操做)。该元素直接插入到 next 返回的下一个元素的前面(若是有)
        • void set(E o) 用指定元素替换 next 或 previous 返回的最后一个元素
        • hasPrevious() 逆向遍历列表,列表迭代器有多个元素,则返回 true。
        • previous() 返回列表中的前一个元素。
      4. 与Iterator对比
        • Iterator在迭代时,只能对元素进行获取(next())和删除(remove())的操做。
        • 对于 Iterator 的子接口ListIterator 在迭代list 集合时,还能够对元素进行添加(add(obj)),修改set(obj)的操做。

5.4.4 Map

  • Map和Collection的对比
    1. Map一次存一对元素, Collection 一次存一个。Map 的键不能重复,保证惟一。
    2. Map 一次存入一对元素,是以键值对的形式存在.键与值存在映射关系.必定要保证键的惟一性.
  • HashMap

    底层是哈希表数据结构,要保证键的惟一性,必须覆盖hashCode方法和equals方法

  • HashTable

    底层是哈希表数据结构

  • HashMap和HashTable的区别
    1. 线程同步
      • HashMap线程不一样步
      • HashTable线程同步
    2. null做为键和值
      • HashMap能够存入null键、null值;
      • HashTable不能够
    3. 继承实现
      • HashMap继承AbstractMap,实现Map
      • HashTable继承Dictionary,实现Map
    4. 遍历方式
      HashTable能够用Enumeration
    5. 哈希值的使用方式
      • HashMap从新计算hash值,并且用&代替求模
      • HashTable直接使用对象的hash值
    6. 内部实现的初始大小
      • HashMap初始16,并且必定是2的倍数
      • HashTable初始11,扩容:old*2+1
  • HashTable和ConcurrentHashMap的区别
    • HashTable对整张表加锁
    • ConcurrentHashMap将Hash表分为16个桶(segment),每次只对须要的桶加锁 (jdk1.8 时,对Node的节点加锁,大大提升了并发度)
  • TreeMap

    TreeMap能够对集合中的键进行排序,其实现与TreeSet同样

  • 经常使用方法
    • 添加

      V put(K key, V value)(能够相同的key值,可是添加的value值会覆盖前面的,返回值是前一个,若是没有就返回null)
      putAll(Map<? extends K,? extends V> m) 从指定映射中将全部映射关系复制到此映射中(可选操做)。

    • 删除

      remove() 删除关联对象,指定key对象
      clear() 清空集合对象

    • 获取

      value get(key); 能够用于判断键是否存在的状况。当指定的键不存在的时候,返回的是null
      int size()

    • 判断
      1. boolean isEmpty() 长度为0返回true不然false
      2. boolean containsKey(Object key) 判断集合中是否包含指定的key
      3. boolean containsValue(Object value) 判断集合中是否包含指定的value
  • 遍历Map的方式
    • 一、将map 集合中全部的键取出存入set集合

      Set keySet() 返回全部的key对象的Set集合(Iterator),再经过get方法获取键对应的值。

    • 二、 values() ,获取全部的值.

      Collection values()不能获取到key对象

    • 三、 Map.Entry对象 推荐使用 重点

      Set<Map.Entry<k,v>> entrySet()

      • 将map 集合中的键值映射关系打包成一个Map.Entry对象
      • 经过Map.Entry 对象的getKey,getValue获取其键和值。

5.4.5 Collections和Arrays

  • Collections

    Collections:集合框架中的工具类,特色:该工具类中的方法都是静态的。

    • Collections常见方法
      1. 对list进行二分查找:
        前提该集合必定要有序。
        int binarySearch(list,key);//必须根据元素天然顺序对列表进行升级排序
        int binarySearch(list,key,Comparator);//要求list 集合中的元素都是Comparable 的子类。
      2. 对list集合进行排序:
        sort(list); //对list进行排序,其实使用的,是list容器中的对象的compareTo方法
        sort(list,comaprator);//按照指定比较器进行排序
      3. 对集合取最大值或者最小值:
        max(Collection)
        max(Collection,comparator)
        min(Collection)
        min(Collection,comparator)
      4. 对list集合进行反转:
        reverse(list);
      5. 对比较方式进行强行逆转
        Comparator reverseOrder();
        Comparator reverseOrder(Comparator);
      6. 对list集合中的元素进行位置的置换
        swap(list,x,y)
      7. 对list集合进行元素的替换。若是被替换的元素不存在,那么原集合不变
        replaceAll(list,old,new)
      8. 能够将不一样步的集合变成同步的集合
        Set synchronizedSet(Set s)
        Map synchronizedMap(Map<K,V> m)
        List synchronizedList(List list)
      9. 将集合变数组
        toArray
  • Arrays

    Arrays:用于对数组操做的工具类

    • Arrays常见方法
      1. 二分查找,数组须要有序
        binarySearch(int[])
        binarySearch(double[])
      2. 数组排序
        sort(int[])
        sort(char[])
        ……
      3. 将数组变成字符串
        toString(int[])
      4. 复制数组
        copyOf();
      5. 复制部分数组
        copyOfRange()
      6. 比较两个数组是否相同
        equals(int[],int[])
      7. 将数组变成集合
        • List asList(T[])
        • 这样能够经过集合的操做来操做数组中元素,可是不可使用增删方法,add,remove。由于数组长度是固定的,会出现UnsupportOperationExcetion。
        • 可使用的方法:contains,indexOf ……
          • 若是数组中存入的基本数据类型,那么asList会将数组实体做为集合中的元素。
          • 若是数组中的存入的引用数据类型,那么asList会将数组中的元素做为集合中的元素。
相关文章
相关标签/搜索