Corejava干货

本人自己总结的corejava的知识点如下
环境变量的搭建

编程语言

人与人沟通 自然语言 汉语、英语、日语、韩语…

人机对话 编程语言

​ 低级: 机器语言

​ 中级:汇编语言、C语言

​ 高级:Java、Python

Java语言

Java的由来
  • 95 sun Green项目组 James Golsing(詹姆斯高斯林)
  • 99 分为三大方向:J2SE、J2EE、J2ME – > 05 JavaSE、JavaEE、JavaME
  • 09 被Oracle收购
  • 14 JDK 8.0
Java的语言特点
  • 面向对象
  • 简单性
  • 跨平台

如何实现跨平台???

Oak 中小型消费电子产品 (收音机、微波炉)

—》 Java

  • Java运行机制:先编译,后解释

    编译:将源文件(.java文件) 编译成 .class文件(字节码文件,无限接近于二进制的文件)

    解释并运行: 将.class文件 解释并运行

​ 特点 : 跨平台,执行效率高

​ 理念:Write Once Run Anywhere 一次编写,到处运行

  • **JVM(Java虚拟机) **: 屏蔽底层操作系统(OS)差异

    JRE运行环境: JVM+解释器

    JDK开发环境:JRE + 编译器+开发工具包(JDK类库+调试工具)

配置环境变量

JAVA_HOME : jdk的安装目录, 例: C:\Program Files\Java\jdk1.8.0_92

Path : JDK 安装目录下的bin目录,例:C:\Program Files\Java\jdk1.8.0_92\bin

classpath : . 类路径

DOS命令操作

  • 打开:win+r cmd
  • 查看当前目录下的所有文件及文件夹:dir
  • 进入文件夹: cd 文件夹名称
  • 盘符切换: d:
  • 清屏 : cls
  • 退出:exit

第一个Java应用程序

  1. 创建.java文件

  2. 代码

    • 类 代码的容器
    • 主函数 程序的入口
    • 打印语句 :在控制台输出一句话
    • 每句代码以分号(英文格式 ; )结尾
    class HelloWorld{
           
    	public static void main(String[] args){
           
    		System.out.println("9班的同学们,你们好");	//换行打印
    		System.out.print("晚上要好好敲代码...");   //不换行打印
    	}
    }
    
  3. 编译:javac 源文件名称.java javac A.java

  4. 运行/解释:java 类名 java HelloWorld

注意:

1. 一个类中只能定义一个主函数
  1. 一个源文件中可以定义多个类,每个类都会生成对应的.class文件;但是类名不能相同

公开类

public修饰的类,称为公开类

  1. 公开类类名必须和源文件名称保持一致
  2. 一个源文件中只能定义一个公开类
public class Test{
     
	public static void main(String[] args){
     
		System.out.println("早上好");
	}
}

包package

作用:管理.class文件

语法:package 包名

位置:源文件有效第一行

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

带包运行 : java 包名.类名(全限定名)

编码规范

  • 书写格式

    层级之间要有缩进(一个制表符(tab))

    一行只写一句代码

  • 代码注释

    单行注释 // 注释内容

    多行注释 /* 多行注释内容 */

    文档注释 (生成外部文档javadoc -d 文件夹名称 源文件名称.java)/**文档注释内容 */ 【了 解】

    注意:注释不参与编译

  • 标识符的命名规范

    1. 语法规定:
      • 只能由字母、数字、_ 、$组成,数字不能开头
      • 严格区分大小写
      • 没有长度限制
      • 不能使用关键字、保留字(goto、const)、特殊字(true、false、null)
    2. 约定成俗:
      • 望文生义、遵循驼峰命名法
      • 类名:由一个、多个单词组成,每个单词的首字母大写 HelloWorld
      • 函数名、变量名:由一个、多个单词组成,首单词首字母小写,后面的单词首字母大写helloWorldTest
      • 包名:全小写,包与包之间使用. 隔开。采用域名倒置 , www.baizhi.com --> com.baizhi.entity
      • 常量名 : 全大写 , 每个单词之间使用_隔开 HELLO_WORLD

变量

**概念:**计算机内存中的一块存储空间,用来存储数据

变量的组成:变量名、变量类型、变量值

变量的使用流程

  1. 声明变量 让jvm分配内存 变量类型 变量名; int a;
  2. 赋值 为变量赋上数据 变量名 = 变量值; a = 10;
  3. 变量的使用 通过变量名获取 System.out.println(a);
变量声明的多种方式
声明的同时并赋值    int b = 20; 
同时声明多个变量并赋值   
	int b = 10,c,d = 40;
	c = 30;

注意: Java是强类型的语言,数据类型必须和变量类型保持一致

数据类型

  1. 基本|原始数据类型

    • 整数

      数据类型 字长 取值范围
      byte 1Byte (字节) -128~127
      short 2B -32768~32767
      int 4B -2147483648~2147483647
      long 8B -9223372036854775808
      ~9223372036854775807
      -90京 ~ 90京
      需要在字面值后追加L或l

      注意:整数的默认类型是int

    • 小数,浮点数

      数据类型 字长 精度
      float 4B 单精度 必须在字面值后追加F或者f
      double 8B 双精度 D或d 可加可不加

      注意:浮点数的默认类型是double

    • 字符型

      char 字长2B 0~65535

      采用 Unicode字符集 万国码

      字面值形式 :

      ​ 字符型 ‘A’

      ​ 整数型 65-‘A’ 97 - ‘a’ 48-‘0’

      ​ 16进制 ‘\u0041’ - ‘A’

      转义字符:

      转义字符 描述
      \n 换行符
      \t 缩进(制表位)
      \\ 反斜线
      \' 单引号
      \'' 双引号
    • 布尔类型

      boolean true( 真 )\false(假)

      注意:布尔类型不参与算数运算

  2. 引用|对象数据类型

    字符串 String String s = "ashdjasd";

    注意:字符串可以是0-n个字符组成

类型转换

  • 自动类型提升

    两种类型相互兼容

    目标类型 范围大于 源类型

    byte --> short --> int --> long --> float --> double
    		 char --> int   
    
  • 强制类型转换

    两种类型相互兼容

    目标类型 范围小于 源类型

    int a = 10;
    short s = (short)a;
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6zgUBbAq-1574690630589)(D:/feiq/Recv Files/CoreJava/day02 ----变量及运算符/笔记/1571734285201.png)]

  • 算数运算时类型提升

    double + double/其他类型 --> double

    float +其他类型(不含double) – > float

    long + 其他类型(不包含double+float) --> long

    int + 其他类型(不包含double+float+long) --> int

    byte、short之间进行运算 --> int

    注意: String类型可以和任意类型进行+运算 , 结果自动提升为String类型 --》字符串拼接

运算符

表达式:使用运算符连接的变量或字面值,并可以得到一个最终结果。

算数运算符: + - * /(除) %(求模)

一元运算符: ++ 、-- 让自身+1 或者-1

​ a++ : 先取值,后自增 ; ++a : 先自增,后取值

赋值运算: = 、-=、+=、*=、/=、%= (不会进行类型转换)

关系运算符:< 、>、<= 、>=、==(判断是否相等)、!=(不等于) ——> 布尔表达式

逻辑运算符:

​ &&(并且|与) 两者都为true --> true

​ || (或者|或) 有一个为true --> true

​ ! (取反) !true --> false ; !false–>true

三元运算符: ? : 布尔表达式?值1:值2

思考:如何让a+1, 小于原来的a ??? [面试题]

条件分支流程

控制台输入

  • Scanner(扫描仪):接收用户输入的数据
//创建扫描仪
java.util.Scanner sc = new java.util.Scanner(System.in);
//让用户在控制台输入数据
//并且进行接收
String s = sc.next();  //接收一个字符串
int a = sc.nextInt();  //接收一个整数
double d = sc.nextDouble();	//接收一个小数

**注:**如果输入了不匹配的数据,则会产生java.util.InputMismatchException

  • import 导包语句

定义位置:package 语句下方,class语句上方

语法:import 包名.类名;

import java.util.*;    //导入 java.util包下的所有类

**注意:**默认导入java.lang包,String、System 都位于java.lang包;同包下的类不需要导入

条件分支语句

概念:根据某个条件是否成立,来决定某段代码是否执行。

分支语句的执行次数0-1

if分支【重点】
if(布尔表达式){
     
    //if代码块
}else{
     
    //else代码块
}
  1. 若布尔表达式为true,则执行if代码块
  2. 若布尔表达式为false,则执行else代码块
多重if
if(布尔表达式1){
       代码块1  }
else if(布尔表达式2){
       代码块2 }
else if(布尔表达式3){
       代码块3  }
else{
      代码块4 }
后续代码...
  1. 若布尔表达式1 - true,则执行代码块1;跳出分支语句,执行后续代码
  2. 若所有的表达式结果为false,则执行代码块4(else代码块)
  3. 只能执行其中之一
嵌套if
if(){
     
    if(){
     }else if(){
     }else{
     }
}else{
     
    
}     //当外层条件满足时,才会判断内层条件

if(){
     }
if(){
     }else{
     }
if(){
     }else if(){
     }else{
     }
if(){
     
    if(){
     }else if(){
     }else{
     }
}else{
     
    if(){
     }else if(){
     }else{
     }
}
switch… case
switch(int表达式){
     
    case1:代码块1
    case2:代码块2
    case3:代码块3
    ...
}
后续代码...
  1. int表达式的值与那个case值相匹配从哪进入switch代码块(决定了入口)
  2. break : 跳出switch代码块(手动添加出口)
  3. default: 当所有的case不匹配时执行
// 5 6 7差  8 9良好 10优秀
Scanner sc = new Scanner(System.in);
int score = sc.nextInt();
switch(score){
     
    case 5:
    case 6:
    case 7:System.out.println("差");break;
    case 8:
    case 9:System.out.println("良好");break;
    case 10:System.out.println("优秀");break;
    default:System.out.println("输入有误");
}

细节:

  1. switch后的表达式 可以是int以及所有能够提升为int的数据类型 , byte、short、char、int
  2. since JDK 7.0 可以使用String作为表达式类型

对比:

用switch case 能做的,用if else 一定能做

用if else能做的 , 用switch case 不一定能做

思考:为什么可以用String类型???怎么实现的???

局部变量【重中之重】

概念:声明在函数内部的变量,称之为局部变量

特点:必须先赋值,后使用

作用范围:从定义行开始,到所在的代码块结束

注意:相同作用范围内不允许命名重复

循环执行流程

概念:根据某个条件是否成立,来多次执行同一段代码

循环的四部分:

  • 循环变量的初始化
  • 循环变量的迭代
  • 循环条件
  • 循环体

while循环

执行次数:0-n次

while(布尔表达式){
        //若布尔表达式为true,则执行逻辑代码;直至布尔表达式为false,则执行后续																		  代码
    //逻辑代码
}
...
//打印10遍HelloWorld
int i = 0;       //循环变量的初始化
while(i<10){
     	 //循环条件 -- 决定了循环次数
    System.out.println("HelloWorld"+i);	//循环体
    i++;		//循环变量的迭代
}
while(true){
        //死循环 -- 无限循环,没有结束的出口
    System.out.println(111111);
} 
	
int i = 0;
while(i<10){
     
    System.out.println(111111);
}

do…while循环

执行次数:1-n次

do{
     
    //逻辑代码
}while(布尔表达式);
  1. 不管条件是否成立,先执行一遍do代码块
  2. 执行一遍后,若结果仍然为true,则再次执行逻辑代码
  3. 直到结果为false,结束循环

for循环

for(循环变量的初始化;循环条件;循环变量的迭代){
     
    //循环体   逻辑代码
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n6jN92MO-1574690630590)(D:/feiq/Recv Files/CoreJava/day04 ----循环/笔记/1571901148280.png)]

i = 0;i<10    执行10遍
i = 0;i<=10      11遍
i = 1;i<10       9遍
i = 1;i<=10      10
for(;;){
         //死循环
    System.out.println(1111);
}

流程控制语句

break; 跳出switch代码块、循环结构

continue; 跳出本次循环

嵌套循环

for(int i=0;i<3;i++){
        //外层循环决定行数
    for(int j=0;j<5;j++){
     	//内层循环决定列数
        System.out.print("*");
    }
    System.out.println();   //换行
}

// i=0   j=0  1  2  3  4 * * * * *
// i=1   j=0  1  2  3  4 * * * * *
// i=2   j=0  1  2  3  4 * * * * *
label标签【了解】
outer:for(int i=1;i<=5;i++){
        //label标签  给循环起的名字
    inner:for(int j=1;j<=4;j++){
     
        if(j==2) break outer;      //跳出的时候 指定跳出的循环
        System.out.print("i="+i+",j="+j+"\t");
    }
    System.out.println();
}

函数执行

概念:一段功能代码,可以反复使用

函数的使用流程

  1. 函数的声明 约定了函数的功能 public static 返回值类型 函数名(形参列表)

    • 参数【重点】:调用者向被调用者传递的数据

      形式参数(形参):变量的声明,相当于函数内部的局部变量

      实际参数(实参):为形参赋值

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LhPSfH9x-1574690630590)(D:/feiq/Recv Files/CoreJava/day05 ----函数/笔记/1571986656196.png)]

      注意:实参和形参必须保证,数量、类型、顺序一致

    • 返回值【重点】:被调用者返回给调用者的数据

      返回值类型 :

      ​ void : 没有返回值

      ​ 八种基本数据类型、String

      public static void main(String[] args){
               
      		int d = add();
      		System.out.println(d);
      	}
      //计算两个数的和
      public static int add(){
               
          return 10;   //return value;  将数据value进行返回
      }
      

      return 关键字:

      • 结束函数的执行,return value;语句后不要定义代码
      • 一个函数只能有一个return value;语句被执行
      • 如果函数内部有分支结构,保证每一个分支都具有return value;语句
      • 若函数返回值类型为void,可以用return关键字,控制函数执行流程
  2. 函数的实现 实现约定的功能 { //代码块 }

  3. 定义位置 类以内,与主函数并列

  4. 函数的调用【重点】

    无参调用:函数名();

    有参调用:函数名(实参列表);

    有返回值调用:数据类型 变量名 = 函数名(实参列表);

    ​ 注意:数据类型返回值类型一致

public static 返回值类型  函数名(形参列表){
     
    //函数的实现代码
}

返回值类型、函数名、形参列表   ---》 函数三要素

函数的作用

  • 提高可读性
  • 减少代码冗余
  • 提高复用性
  • 提高可维护性

函数的嵌套调用

在一个函数内部调用另外一个函数

递归【了解】

一个函数调用了它本身,称之为递归调用

注意:需要为递归函数手动添加出口,否则会无穷递归,运行报错

​ 报错信息为java.lang.StackOverflowError(内存溢出)

递归的思想:

当解决一个大问题时,可以分解为多个小问题;而且小问题的解决方案跟大问题一致。可以使用递归

数组

概念:一组连续的存储空间,一次性存储多个相同数据类型的数据

数组的使用流程:[重点]

  1. 声明数组 : 数据类型[] 变量名; int[] a; int []a; int a[];

    声明数组的多种方式
    
    声明的同时并分配空间:数据类型[] 数组名 = new 数据类型[长度];
    声明的同时并为元素赋值:int[] a = new int[]{
           元素值1,元素值2,元素值3,...};
    	注意:不再为其分配长度
    					int[] a = {
           元素值1,元素值2,元素值3,...};
    	注意:
    		int[] a ;
    		a = {
           元素值1,元素值2,元素值3,...};  //error
    
  2. 分配空间: 变量名 = new 数据类型[数组的长度]; a = new int[5];

数组的下标范围: 0 - 数组名.length-1

元素访问 : 数组名[下标];   

当访问超出下标范围的元素,则运行报错:
	报错信息为:java.lang.ArrayIndexOutOfBoundsException(下标越界)
	
数组的长度:数组名.length

数组的遍历:一一获取所有元素
		for(int i=0;i<a.length;i++){
     
			System.out.print(a[i]+"\t");
		}
		System.out.println();

数组元素具有默认值:
	byte\short\int\long 	 0
    float\double      		 0.0
    char           			 空字符|0
    boolean         		 false 
    String           		 null

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r7IWApB3-1574690630590)(D:/feiq/Recv Files/CoreJava/day06 ----数组01/笔记/1572234738834.png)]

数组的内存特点:内存空间是连续的

优点:便于通过数组的首地址,计算出每一个元素的地址 查询快

a[i] = 首地址+字长*i

缺点:长度固定

​ 数组的扩容
一、【理解】

1. 定义一个新数组,长度大于原数组
2. 将原数组中的元素一一挪到新数组
3. 更新地址

int[] a = {
     10,20,30,40};
int[] b = new int[a.length*2];
for(int i=0;i<a.length;i++){
     
    b[i] = a[i];
}
a = b;

二、使用Arrays工具类【开发重点】

int[] a = {
     10,20,30,40};
a = java.util.Arrays.copyOf(a,a.length*2);    //返回一个扩容后的数组

三、了解

//将原数组中的元素 挪到新数组
System.arraycopy(原数组,起始下标,新数组,存储元素的起始下标,长度);

数组的应用

数组应用于参数:实参为形参赋值时,传递的是地址

数组应用于返回值:需将函数内部数组的地址进行返回

可变长参数【了解】

概念:可接收多个同类型实参的参数 , 不限个数

语法:数据类型…参数名

使用方式和数组相同

public static void m1(int...a){
       //可变长参数a
    //遍历数组
    for(int i=0;i<a.length;i++){
     
        System.out.print(a[i]+"\t");
    }
    System.out.println();
}

注意:可变长参数只能定义在形参列表最后,而且只能定义一个

数组排序

冒泡排序 : 相邻的两个元素比较大小,互换位置【面试重点】

	//实现将数组进行从小到大进行排列
	//相邻的两个元素进行比较,大的后挪
		int[] a = {
     8,7,6,4,3};
		/*  8 7 6 4 3 
		0-1 7 8 6 4 3    比较轮数 长度-1
		1-2 7 6 8 4 3    每一轮做的事 a[i]>a[i+1]  交换位置
		2-3 7 6 4 8 3 
		3-4 7 6 4 3 8
		
		0-1 6 7 4 3 8
		1-2 6 4 7 3 8
		2-3 6 4 3 7 8
		
		0-1 4 6 3 7 8
		1-2 4 3 6 7 8
		
		0-1 3 4 6 7 8
		*/
		for(int i=0;i<a.length-1;i++){
        //外层循环控制比较轮数
			//每一轮的内容
			for(int j=0;j<a.length-1-i;j++){
     		//内层循环表示元素下标
				if(a[j]>a[j+1]){
     
					int temp = a[j];
					a[j] = a[j+1];
					a[j+1] = temp;
				}
			}
		}

选择排序:拿固定元素和后面的元素做比较【面试重点】

for(int i=0;i<a.length-1;i++){
       //固定下标
    for(int j=i+1;j<a.length;j++){
       //表示后面的元素对应的下标
        if(a[i]>a[j]){
     
            int temp = a[i];
            a[i] = a[j];
            a[j] = temp;
        }
    }
}

JDK排序【开发重点】

java.util.Arrays.sort(数组名称);  //将数组按升序排序

二维数组

概念:一维数组中的一维数组。一维数组的元素又是一个一维数组。

使用流程

  1. 声明 数据类型[][] a; int[][] a;
  2. 分配空间 a = new int[行数|高维数组的长度][列数|低维数组的长度];
二维数组的多种声明方式
int[][] a = new int[3][4];
int[][] a = new int[][]{
     {
     10,20,30},{
     1,2},{
     10,30,50,60},...};   //不规则二维数组
int[][] a = {
     {
     10,20,30},{
     1,2},{
     10,30,50,60},...};

int[][] a = new int[3][];
a[0] = new int[3];
a[1] = new int[2];
a[2] = new int[5];

  1. 元素访问:数组名[行号|高维数组的下标][列号|低维数组的下标];

  2. 二维数组的遍历

    数组名.length --> 高维数组的长度

for(int i=0;i<a.length;i++){
     
    for(int j=0;j<a[i].length;j++){
        //表示低维数组的下标
        System.out.print(a[i][j]+"\t");
    }
    System.out.println();
}

5.二维数组的内存特点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vLwCuC0l-1574690630591)(D:/feiq/Recv Files/CoreJava/day06 ----数组01/笔记/1572333835072.png)]

面向对象

面向过程:自顶向下、逐步求精

面向对象:

  1. 准备好所需对象
  2. 对象之间相互配合

对象的组成

  1. 特征:属性,代表对象有什么
  2. 行为:方法,代表对象能做什么
  3. 计算机中 ,使用来去描述对象

类和对象的关系

  • 类是对象的模板
  • 对象是类的实例

类的定义

  • 属性:代表有什么 ——> 实例变量、成员变量

    语法:数据类型 变量名;

    定义位置:类以内,方法外部

    属性具有默认值:

    ​ 数值类型:0/0.0

    ​ 布尔类型:false

    ​ 引用类型:null

    成员变量和局部变量的区别???

    成员变量 局部变量
    定义位置 类以内,方法外部 方法内部
    是否具有默认值 具有默认值 必须先赋值,后使用
    作用范围 类的内部 定义行开始,到所在的代码块结束
    命名冲突 成员变量和局部变量命名冲突时,局部变量优先 相同作用范围内,不允许命名冲突
  • 方法:代表行为 ——> 成员方法

    语法:public 返回值类型 方法名(形参列表){

    ​ //方法实现

    ​ }

    定义位置:类以内,其他方法外部

  • 创建对象 : 在内存中开辟连续的空间

    new关键字

    类名 对象名 = new 类名(); Student s = new Student();

  • 访问属性:对象名.属性名

    访问方法:对象名.方法名(实参);

方法重载OverLoad

  • 概念:在一个类内部,定义了多个相同名字的方法

  • 要求:方法名相同,但是参数列表不同(类型不同、顺序不同、个数不同)

  • 作用:会根据传入的参数,精确匹配对应的方法

  • 注意:若不能精确匹配,则就近向上匹配;但是要避免混淆

    public void m1(double d,int a){
           
    	System.out.println("m1(double,int)");
    }
    public void m1(int a,double d){
           
    	System.out.println("m1(int,double)");
    }
    ----------------------------------------------
    m1(10,10);    //混淆  -- 编译报错
    
  • 好处:使代码更加灵活、屏蔽差异

构造方法

  • 特殊的方法。
  • 语法:public 类名(){ } 构造方法名必须和类名保持一致;没有返回值类型,连void都没有
  • 定义位置:类以内,其他方法外部
  • 注意:
    1. 构造方法在new对象时调用,调用一次;不能手动调用
      2. 若不手动定义构造方法,则默认提供无参构造;若手动提供构造,则系统不再提供
  • 作用:
    1. 创建对象时使用
    2. 为属性赋值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VG8PcuYl-1574690630591)(D:/feiq/Recv Files/CoreJava/day08 ----面向对象/笔记/1572425174639.png)]

对象的创建过程

  1. 分配空间 为属性赋默认值
  2. 初始化属性 为属性赋初始值(第二次)
  3. 调用构造方法 第三次为属性赋值

this关键字

  1. this. : this 代表当前对象 ,可以在成员方法、构造方法中使用

    this.属性名: 获取当前对象的属性

    this.方法名(实参) : 调用当前对象其他方法

  2. this() : 调用本类其他构造方法,只能使用在构造方法

    this() : 调用本类的无参构造

    this(实参):调用本类的有参构造

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bkuMMh40-1574690630591)(D:/feiq/Recv Files/CoreJava/day08 ----面向对象/笔记/1572493516402.png)]

    注意: 1. 必须定义在构造方法有效第一行

     2. 避免递归调用构造方法
    
        ```java
        public B(){
            this(10);
        }
        public B(int a){
            this();
        }  //erro  递归调用构造方法
    
    
    
    
    #### 引用
    
    1. 对象类型的变量称之为引用
    
       `类名 引用名 = new 构造方法名();`
    
        ***注意:*** 引用数据类型必须和对象类型保持一致
    
    2. 引用中存储的是对象的首地址
    
    3. 每个对象空间在堆空间中,相互独立
    
    4. 引用之间相互赋值赋的是地址
    
       基本数据类型之间传递的是数值
    
    5. 当引用值为null时,使用属性和方法,会运行报错:
    
       报错信息为:`java.lang.NullPointerException(空指针异常)`
    
    6. 引用的应用:应用于参数、返回值、数组
    
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3cwiKo2b-1574690630592)(D:/feiq/Recv Files/CoreJava/day08 ----面向对象/笔记/1572507779188.png)]
    

三大特性

封装

  1. private 修饰属性 --> 私有属性

    只能在本类中访问

  2. 需要提供对应的方法

    • set方法 --》 设值
    public  void setXXX(形参){
                //setXXX   set+属性名,属性名首字母大写
        属性 = 参数值;
    }  
    
    • get方法 --》 取值
    public 返回值类型  getXXX(){
           		 //getXXX  get+属性名,属性名首字母大写
        return 属性值;
    }
    
    • 可以在set、get方法内部 监测数据的安全性
    private int age;    //属性私有化
    //提供set方法 --》 为age赋值
    public void setAge(int age){
           
        if(age>0&&age<150){
           
            this.age = age;
        }else{
           
            System.out.println("请输入合法的年龄");
        }
    }
    //提供get方法 -- > 获取属性值
    public int getAge(){
           
        return this.age;
    }
    

    ***注意:***一个get方法只能获取一个属性值;一个set方法只能为一个属性赋值

继承

红笔 is a 笔

狗 is a 动物

学生 is a 人

概念:类和类之间建立 is a 关系

  1. 关键字 :extends

class Student extends Person{}
​ Student 继承于 Person

​ 子类 继承于 父类

  1. 子类可以使用父类中属性和方法
    3. 一定要满足 is a关系 ,不能随便建立
    4. 父类抽取了 子类的共性

继承的好处

  1. 提高代码的复用性
  2. 提高代码的可扩展性

方法覆盖(override)

  1. 在子类中定义和父类中一致的方法

  2. 要求:方法三要素(返回值类型、方法名、参数列表)相同

    ​ 访问修饰符 要求相同或更宽

    注意:若形参列表不同,则不会编译报错,而是构成方法重载

  3. 若子类中覆盖了父类中的方法,则实际运行是子类中覆盖后的方法

继承的特点

  1. Java中的类是单继承,一个子类只能有一个直接父类;

    但是可以多级继承,一个子类可以有多个间接父类。

  2. 属性和方法是逐级叠加的

哪些可以继承??

  1. 构造方法不能被继承

  2. 属性和方法由访问修饰符决定是否被继承:

    访问修饰符访问权限

    本类 同包 非同包子类 非同包非子类
    private(私有的) × × ×
    [default](默认的) × ×
    protected(受保护的) ×
    public(公开的、公共的)

    从严到宽

    哪些属性、方法可以被继承:

    private修饰 不可被继承

    [default] 修饰 同包子类可以被继承

    protected 可以继承

    public 可以继承

继承关系下的对象创建过程

在创建子类对象时,会先构建父类对象

  1. 分配空间 (父类+子类)

  2. 递归的构建父类对象

    ​ i. 初始化父类属性

    ​ ii.调用父类构造方法

  3. 初始化子类属性

  4. 调用子类构造方法

super关键字

  1. super() : 调用父类中的构造方法

    super(); 调用父类无参构造

    super(实参); 调用父类有参构造

    注意:

    • 使用在子类构造方法中,决定了JVM在构建父类对象时,使用哪一个父类构造方法
    • super() /super(实参) 只能定义在子类构造方法中的有效第一行
    • 若子类构造方法中 没有定义super() / super(实参),则JVM默认提供super();
    • super() 和 this() 不能同时出现
  2. super. super 代表父类对象

    super.父类属性名; 调用父类的属性

    super.父类方法名(实参); 调用父类的方法

    多态

    概念:父类类型的引用 指向 子类类型对象【重点】

    Animal a = new Dog();

    ​ 父类引用 子类对象

    1. 父类类型的引用只能使用父类中的属性和方法
    2. 如果子类中覆盖了父类中的方法,则实际运行的是覆盖后的方法

    类型转换

    1. 类型提升 ---->向上转型

      Dog d = new Dog();
      Animal a = d;   //多态
      
    2. 强制类型转换 ---->向下转型

      Animal a = new Dog();
      Dog d = (Dog)a;
      

      注意【重点】:

      ​ 1. 若转换双方存在继承关系,则强转一定编译通过;但是若引用中存储的实际对象类型和目 标类型不匹配,则运行报错 , 报错信息为:java.lang.ClassCastException(强制类型转换异常)

      Animal a = new Cat();
      Dog d = (Dog)a;  //运行报错  强制类型转换异常		
      

      ​ 2. 若转换双方没有继承关系,则编译报错

    3. 如何避免强制类型转换异常??? 【重点】

      关键字:instanceof

      用法: 引用名 instanceof 对象类型(目标类型)

      ​ 判断引用中存储的实际对象类型和目标类型是否一致;

      ​ 若一致,则为true;若不一致,则为false

    多态的应用

    1. 多态应用于返回值: 返回值父类 + 所有子类类型
    2. 多态应用于参数:实参类型父类+所有子类类型
    3. 多态应用于数组:元素类型可以是父类+所有子类类型

    多态的好处

    屏蔽了子类差异,使代码更加灵活

三大修饰符

abstract(抽象的)

  1. 修饰类 ——> 抽象类
    • 不能创建对象,但是可以声明引用
    • 具有构造方法,是在创建子类对象时,先构建父类对象这一步使用
  2. 修饰方法 ——> 抽象方法
    • 语法:public abstarct 返回值类型 方法名(参数列表);
    • 抽象方法只有声明,没有实现,连 {} 都没有
    • 抽象方法只能定义在抽象类中
    • 若子类继承了抽象类,则必须实现抽象类中的所有抽象方法;否则子类也必须声明为抽象类
  3. 好处:强制使用多态

static(静态的)

  1. 修饰属性 ——> 静态属性、类变量

    • 全类共有的,与创建多少对象无关

    • 访问方式类名 . 静态属性名 ——>常用

      ​ 对象名 . 静态属性名

  2. 修饰方法 ——> 静态方法

    • 语法: public static 返回值类型 方法名(参数列表){ //方法实现 }

      ​ 注意:public 和 static 没有先后顺序

    • 访问方式类名.静态方法名(实参) ——> 常用

      ​ 对象名 . 静态方法名 (实参)

    • 注意:

      • 静态方法中不能访问非静态成员(属性、方法)

        静态方法中只能访问静态成员(属性、方法)

      • 非静态方法可以访问非静态成员和静态成员

      • 静态方法中不能使用this和super关键字

      • 静态方法允许被覆盖,但是只能被静态方法覆盖;而且没有多态

        class MyClass{
                   
        	public static void m1(){
                   
        		System.out.println("m1()...");
        	}
        }
        class SubClass extends MyClass{
                   
        	public static void m1(){
                   
        		System.out.println("子类m1()...");
        	}
        }
        --------------------------------------------
        MyClass mc03 = new SubClass();
        mc03.m1();   //m1()...
        
    1. 修饰初始代码块 ——> 静态代码块

      • 初始化代码块【了解】:

        定义位置:类以内,方法外部

        执行:在创建对象的第二步执行,与初始化属性,根据定义的先后顺序来去执行

      • 静态代码块【开发应用重点】:

        定义位置:类以内,方法外部,被static修饰

        执行:在类加载时执行,与初始化静态属性,按照定义的先后顺序来去执行。

        ​ 只执行一次。

        类加载【理解+面试重点】

        当JVM第一次使用一个类时,会通过classpath(类路径)加载它的所有信息(包名、类名、父类、方法、属性、构造方法…),保存在JVM内存中。这个过程称之为类加载。

        • 类加载只会执行一次。

        • 类加载的时机:

          ​ i. 第一次创建对象时:先进行类加载,再创建对象

          ​ ii. 第一次通过类名访问静态属性、静态方法

          ​ iii. Class.forName(“类全限定名”);

          ​ iv. 当创建子类对象时

          ​ 先进行父类类加载,再进行子类类加载;

          ​ 先创建父类对象,再创建子类对象;

final(最终的)

  1. 修饰变量(属性、局部变量、类变量)

    • 被final修饰的变量称之为作用范围内的常量只允许赋值一次;不可被更改

    • 修饰属性:

      被final修饰的属性没有默认值

      ​ 赋值时机:显示初始化,初始化代码块,构造方法

      ​ 注意:三个机会,只能选其一

    • 修饰类变量(静态变量)

      ​ 被final修饰的静态变量(static final int b; //静态常量)没有默认值

      ​ 赋值时机:显示初始化,静态代码块

      ​ 注意:只能任选其一

    • 被final修饰的基本数据类型 值不可以更改

      被final修饰的引用数据类型 指向的地址不可以更改

  2. 修饰方法

    • 语法:访问修饰符 final 返回值类型 方法名(形参列表){ }

      ​ 注意:访问修饰符和 final不分先后

    • 可以继承,不允许覆盖

  3. 修饰类(断子绝孙类)

    • 不可被继承(没有子类)

注意

  • abstract、final、static 都不能修饰构造方法
  • private 和 abstract 不能连用
  • final 和 abstract 不能连用
  • static 和 abstract 不能连用

接口

概念:是一种标准,是使用者和实现者都必须遵循的标准;代表一种能力【理解】

语法:【重点】

  1. 定义:interface 接口名{}
  2. 接口会生成对应的.class文件
  3. 接口不能创建对象,但是可以声明引用
  4. 接口没有构造方法
  5. 属性默认为公开静态常量(默认被public static final修饰)
  6. 方法默认是公开抽象方法(默认被public abstract 修饰)
interface MyInter{
     
	int a = 10;  //public static fianl int a = 10;
	void m1();   //public abstract void m1();
}

注意:接口不是类

实现类【重点】

  1. class MyClass implements 接口名{}

  2. 实现类必须实现接口中的所有方法。访问修饰符只能是public

  3. 使用 :

    //接口类型的引用 指向 实现类类型的对象 -->多态
    MyInter mi = new MyClass();
    

继承关系

  1. 类和类之间是单继承

  2. 接口和接口之间是多继承

    interface 接口名1 extends 接口名2,接口名3,...{}

  3. 一个类可以实现多个接口

    class 类名 implements接口1,接口2,...{}

  4. 一个类可以继承父类的同时,实现多个接口

class 类名 extends 父类名 implements接口1,接口2,...{}

继承关系产生的影响[了解]

互相强转的双方,若一方是接口类型,则强转编译一定通过;

但是运行时会判断,引用中指向的实际对象类型和目标类型是否匹配,

若匹配,则编译通过,运行通过;

若不匹配,则编译通过,运行报错:

报错信息为:java.lang.ClassCastException(类型转换异常)

接口的好处【理解】

  1. 扩充子类的能力:主要功能定义在父类中,次要功能定义在接口中
  2. 解耦合:降低代码之间的耦合度

接口回调【了解】

先有接口的使用者,后有接口的实现者。

Object类(java.lang)

  1. 所有类的超类、根类、父类

  2. Object类型的引用可以指向任意类型的对象。

    Object o = new Student();

  3. Object类中方法,是所有类所共有的

常用方法

  • getClass() : 获取引用中存储的实际对象类型【重点

    通常用于判断两个引用中指向的实际对象类型是否一致

//o引用中指向的实际对象类型是否和p引用中指向的实际对象类型一致
if(o.getClass()==p.getClass()) {
     
    System.out.println("一致...");
} else {
     
    System.out.println("不一致...");
}
  • int hashCode() : 返回该对象的哈希码值(对象的整数表现形式)

  • String toString() : 返回该对象的字符串表现形式(所有的属性内容)[重点]

    要求:需要重写toString()方法

    public String toString(){
           
        return 属性值拼接成的字符串;
    }
    
  • boolean equals(Object o) : 比较对象的内容是否相同[重点]

    ==:比较基本数据类型,比较的是数值

    ​ 比较引用数据类型,比较的是地址

    对象之间比较内容(属性值)是否完全相同,需通过equals方法,自定义类型需要重写equals

    重写规则:

    public boolean equals(Object o) {
           
        //1. 自反性(比较this和o是否指向同一对象)
        if(this==o) return true;
        //2. 非空判断  判断o是否为null
        if(o==null) return false;
        //3. 判断当前对象和o是否是同一类型
        if(this.getClass()!=o.getClass()) return false;
        //4. 强制类型转换
        Dog d = (Dog)o;
        //5. 逐一比较属性
        if(this.age==d.age&&this.sex==d.sex&& this.name.equals(d.name)) {
           
            return true;
        }
        return false;
    }
    
  • finalize() :垃圾回收器回收垃圾对象时调用的方法【不要在这个方法中定义逻辑代码】

    垃圾对象:没有引用指向的对象,称之为垃圾对象

    垃圾回收:销毁垃圾对象,清理内存空间

    垃圾回收器回收垃圾 对象的时机【了解】:

    自动回收机制:当JVM内存耗尽时,垃圾回收器会自动回收所有垃圾对象

    手动回收机制:通过System.gc(); 手动的通知垃圾回收器做垃圾回收。

    ​ 若垃圾收器空闲,则回收;若忙,则不回收。

内部类

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

特点 :

  1. 内部类也会生成对应的.class文件 , 文件名为 Outer$Inner.class
  2. 内部类可以访问外部类的私有属性,不破坏封装性
  3. 内部类分为:成员内部类,静态内部类,局部内部类,匿名内部类(重点)
  • 成员内部类(10%)

    定义位置 : 类的内部,方法外部

    如何创建对象:

    //创建外部类对象
    //依赖外部类-->创建内部类对象
    Outer o = new Outer();
    Outer.Inner inner = o.new Inner();
    

    注意事项:

    1. 外部类对象 外部类类名.this

      访问外部类对象的属性 外部类类名.this.属性名

    2. 成员内部类中不能定义静态成员(属性、方法)

  • 静态内部类(10%)

    定义位置:类的内部,方法外部,被static修饰

    如何创建对象:

    Outer.Inner inner = new Outer.Inner();
    

    注意事项:

    1. 静态内部类只能访问外部类的静态成员
  • 局部内部类(30%)

    定义位置 : 方法内部

    如何创建对象:

    ​ 在定义它的方法内部创建,要创建在类定义完成之后

    public static void main(String[] args) {
           
    		class Inner{
             //局部内部类
    			int a = 10;
    			public void m1() {
           
    				System.out.println(111);
    			}
    		}
    		new Inner();  //创建局部内部类对象
    	}
    

    注意事项:

    1. 它可以访问它所在方法的局部变量,但是这个变量必须被final修饰(语法规定)

      在JDK 1.8开始, 局部变量默认被final修饰(语法糖)

    好处:做到接口公开,实现隐藏;实现弱耦合

  • 匿名内部类(50%)

    定义位置:定义方法内部,一个特殊的局部内部类(局部内部类具有的特点它都有)

    创建对象:

    ​ 没有类名,必须实现一个接口或者继承一个父类

    new 接口名(){
           
        //匿名内部类的内容-->必须实现的接口的方法
    }
    
    ------------------------------
    new 父类类名(){
           
        //类的内容
    }    
    

    注意:

    1. 只能创建一次对象
    2. 匿名内部类定义完成 , 则对象创建完毕

    坏处:可读性差

    好处:使代码更加灵活 , 减少代码量

常用类

包装类

**概念:**为八种基本数据类型提供的对象数据类型。

基本数据类型 包装类类型(java.lang)
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean

相互转换

int <——>Integer

  • int —— > Integer【重点】
		int a = 10;
		Integer i1 = new Integer(a);    //通过构造方法
//		static Integer valueOf(int i) :将整数转换为Integer对象
		Integer i2 = Integer.valueOf(a);
  • Integer —— > int 【重点】
//		int intValue()  返回Integer对象的int值
		int b = i2.intValue();

String <——> Integer

  • String ——> Integer【重点】
		String s = "123";
		Integer i3 = new Integer(s);  //通过构造方法
//		static Integer valueOf(String s) 
		Integer i4 = Integer.valueOf(s); 
  • Integer ——> String
String s1 = i3+"";
String s2 = i3.toString();

String <——>int

  • String——>int【重点】
//		static int parseInt(String s) 
		int c = Integer.parseInt(s);
  • int ——>String
int a = 10;
String s = a+"";

注意: String 转换为 数值类型时,String字面值必须是纯数字格式;

​ 否则,会运行报错,报错信息为:java.lang.NumberFormatException(数字格式转换异常)

Since JDK 5.0 提供了自动拆箱和自动装箱的功能。基本数据类型和包装类类型之间可以自动转换。

自动拆箱:包装类类型——>基本数据类型

自动装箱:基本数据类型——>包装类类型

缓冲区【理解】

在自动装箱时,默认调用valueOf方法;对-128~127之间的数做了预先包装,存放在缓冲区内(常量池)。提高效率。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hyXn4i9I-1574690630593)(D:/feiq/Recv Files/CoreJava/day16 ----常用类/笔记/1573454017007.png)]

作用【理解】

用于区分0和null,用于区分有效数据和无效数据

String(字符串)(java.lang)

常用方法【重点】
  • char charAt(int index): 根据下标返回对应的字符

  • int length() : 返回值字符串的长度

    *注意:*s.length() , 调用方法获取长度

    ​ 数组名.length :获取数组长度

  • int indexOf(String str): 返回字符串str在当前字符串中第一次出现的下标;

    ​ 若不存在此字符串,则返回 -1

  • int lastIndexOf(String str) : 返回字符串str在当前字符串中最后一次出现的下标;

    ​ 若不存在此字符串,则返回 -1

  • String substring(int beginIndex,int endIndex) : 返回beginIndex ~ endIndex组成的字符串

    ​ (包含beginIndex ,不包含endIndex )

  • String[] split(String str): 根据str 对字符串进行拆分,返回拆分后的数组

  • String toUpperCase(): 将字符串转换成全大写

  • String toLowerCase(): 将字符串转换成全小写

  • boolean endsWith(String str) : 判断字符串是否以str结尾

  • boolean contains(String str) : 判断字符串中是否包含str;若包含-true,若不包含-false

创建对象的两种方式【理解+面试重点】
 String s = "abc";    字面值形式

只会产生一个对象  存放在串池中
String s = new String("abc");   构造方法创建

产生两个对象  一个存放在串池中,一个存放在堆空间中

intern() : 返回 s 对象在串池中的字符串对象
String 具有不可变性【理解+面试重点】
String s1 = "abc";
String s2 = s1;
s1+="bcd";   //s1指向的地址发生改变

System.out.println(s2);     //abc
System.out.println(s1);     //abcbcd

String类型在做拼接时,不会在原有的对象上进行改变,而是创建新的空间存储拼接后的对象。

导致,字符串拼接效率过低

可变长字符串【面试重点】

StringBuffer : JDK 1.0 线程安全,运行效率低

StringBuilder : JDK 5.0 线程不安全,运行效率高

常用:

append(String s) :拼接字符串 (类似于String的+)

BigDecimal(java.math)

  • 作用:精确表示、计算浮点数
  • 创建BigDecimal对象(方式很多,以参数为字符串为例):

​ BigDecimal bd=new BigDecimal(“1.0”);(推荐使用)

  • 常用方法:

BigDecimal add(BigDecimal bd)

BigDecimal subtract(BigDecimal bd)

BigDecimal multiply(BigDecimal bd)

BigDecimal divide(BigDecimal bd)

BigDecimal bd6 = new BigDecimal("10");
BigDecimal bd7 = new BigDecimal("3");
// 2 :表示取小数点后两位
//BigDecimal.ROUND_HALF_UP:四舍五入
BigDecimal bd8 = bd6.divide(bd7,2,BigDecimal.ROUND_HALF_UP);  // bd8 = bd6/bd7

注意: 若不能整除则需指定取舍位数,否则运行报错

集合

**概念:**存储多个对象的容器,本身也是一个对象。

Collection集合(java.util)

  • 特点:Collection 体系的根接口。能够存储多个对象。
  • 常用方法:

add(Object o): 增加一个元素

contains(Object o): 判断集合中是否包含元素o

remove(Object o): 删除元素o

int size(): 返回有效元素个数

  • 实现类:见子接口中的实现类

List接口(java.util)

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

  • 常用方法:

    * add(Object o): 增加一个元素

    * add(int index,Object o) : 向指定位置处插入一个元素

    * remove(int index): 根据下标删除元素

    * set(int index, Object o) : 将index下标处对应的元素,替换为o

    * get(int index): 根据下标获取对应的元素

    * int size(): 返回有效元素个数

    contains(Object o): 判断集合中是否包含元素o

    indexOf(Object o): 返回元素第一次出现的下标,若不包含则返回-1

    lastIndexOf(Object o) : 返回元素最后一次出现的下标,若不包含则返回-1

    subList(int fromIndex, int toIndex): 返回fromIndex(包含)~toIndex (不包含)

    ​ 之间元素组成的List集合

  • 实现类:ArrayList

    实现类之间的区别???【面试重点】

    • ArrayList JDK 1.2 线程不安全 效率高

      ​ 数组实现 内存空间连续,查询快,增删慢

    • Vector JDK 1.0 线程安全 效率低

    • LinkedList 链表实现 内存空间不连续,查询慢,增删快

    查询多 ——> ArrayList

    增删多 ——> LinkedList

  • 遍历

    下标遍历:

    for(int i=0;i<list.size();i++) {
           
        System.out.println(list.get(i));
    }
    
  • for-each遍历

    for(数据类型  变量名:集合名称|数组名称){
           
        // 变量名  --> 表示元素
    }
    注意: 数据类型和泛型类型保持一致
    

泛型集合【重点】

概念:类型安全的集合,强制集合元素类型一致

List list = new ArrayList();

注意

  1. 编译时即可检查元素类型是否一致
  2. 引用泛型必须和对象泛型保持一致;没有多态

自定义泛型类 [了解]

class MyClass<T>{
        //自定义泛型类
	private T a;
	public T getA() {
     
		return a;
	}
	public void setA(T a) {
     
		this.a = a;
	}
}

注意:

  1. 泛型的类型 在创建对象时决定

    MyClass<String> mc = new MyClass<>();  //决定泛型为String类型
    
  2. 通常使用T/K/V/E作为泛型标识

  3. since jdk 1.5 可以定义泛型接口
interface IA<K,V>{
     
	void m1(K k);
	void m2(V v);
}
class MyClass01<K,V> implements IA<K,V>{
     
	public void m1(K k) {
     }
	public void m2(V v) {
     }
}
-------------------------------------------------
IA<Integer,String> ia = new MyClass01<>();

Collections[了解]

概念:一个工具类,提供了操作集合的方法

static void reverse(List list) : 反转集合中的元素

static void shuffle(List list): 将集合中的元素 , 随机重置

static void sort(List list): 对集合中的元素进行升序排序

​ 注意:若集合中元素是自定义类型,则需要自定义类实现Comparable接口,实现comparTo方法

public int compareTo(Student o) {
     
    //定义排序的规则
    //拿当前对象的属性 和 参数o的属性值  做对比
    //如果当前对象的属性值 > 参数O对象的数值   则返回正整数 1
    //如果当前对象的属性值 < 参数O对象的数值   则返回负整数 -1
    //如果当前对象的属性值 == 参数O对象的数值   则返回0
    if(this.age>o.age) return 1;
    else if(this.age<o.age) return -1;
    else {
     
        //代表年龄相等的情况
        return this.name.compareTo(o.name);
    }
}

Set接口(java.util)

  • 特点:无序无下标,元素内容不可以重复

  • 常用方法:全部继承于Collection

  • 实现类:HashSet

    ***HashSet如何实现元素内容不重复???***【面试重点】

    1. 基于hashCode值实现元素内容不重复

    2. 当hashCode值相同时 , 会调用equals方法进行比较内容是否一致

    3. hashCode的重写规则: 目的是保证属性值相同的两个对象,哈希码值相同

      public int hashCode() {
               
          //把所有的属性值进行计算出一个整数  进行返回
          return name.hashCode()+age+(int)score;
      }
      
  • 遍历方式:

    for-each

    迭代器遍历

    //1. 获取迭代器对象  	iterator():返回迭代器对象      Iterator:表示迭代器
    //2. 调用方法  判断指针后是否还有元素     hasNext():判断是否还有元素  若有-															          true;若没有-false 
    //3. 调用方法  使指针后移一位,并且将跨过的元素进行返回     next():返回下一个元素
    Iterator<String> iterator = set.iterator();
    while(iterator.hasNext()) {
           
        String s = iterator.next();
        System.out.println(s);
    }
    

异常

概念:在程序运行过程中,产生的意外情况

**异常处理:**提高程序的容错性,提前准备好应对异常的代码,正常情况下不执行

try{
     
  	插入银行卡
	输入密码和金额
	金额-=2000
	吐钱2000 
}catch(){
     
    金额+=2000 
}finally{
     
   退卡 
}

异常的分类[理解]

  • Throwable:所有异常的父类,位于java.lang包下

    • Error : 严重错误,无法处理

      java.lang.StackOverflowError 内存溢出

    • Exception

      • RuntimeException 运行时异常|未检查异常

        可以避免,可处理可不处理

        NullPointerException: 空指针异常

        IndexOutOfBoundsException : 下标越界异常

        ClassCastException : 类型转换异常

        NumberFormatException: 数字格式转换异常

      • RuntimeException 非运行时异常|已检查异常

        不可避免,必须处理

        FileNotFoundException : 文件找不到异常

        EOFException : 文件到达结尾异常

异常的产生【理解】

  1. 自动产生:程序运行过程中,遇到错误的代码,导致程序终止。

  2. 手动产生:

    throw  new 异常类名()//手动产生异常
    

    1)定义在方法内部

    2)相当于return语句,导致方法的终止

异常的传递【理解】

按着方法的调用链方向反方向传递,直至JVM,最终导致程序终止。

异常的处理【重点】

  1. 消极处理 : 声明上抛
throws: 定义在方法声明之后  

public static void m2(int i) throws 异常名1,异常名2{
     }

注意 : 只是推卸责任的处理方式,最终异常并没有得到解决

  • 方法覆盖(终极版)

    返回值类型、方法名、参数列表 要和父类保持一致

    访问修饰符 相同或更宽

    不能比父类抛出更多、更宽的异常

  1. 积极处理:try-catch 捕获
try{
     
    //可能出现异常的代码
}catch(异常类名1 e){
     
    //当异常出现时会执行的代码
}catch(异常类名2 e){
     
    // 当另外一个异常出现时会执行的代码
}
  • try块中产生的异常会跟catch后面异常进行比较,哪一个匹配执行哪一个catch代码块
  • catch 可以捕获父类异常,也可以捕获子类异常;但父类异常一定要定义在子类异常之后
try{
      //有可能发生异常的代码  }  
catch() {
      //异常发生时执行的代码  }    
finally{
      //不管是否发生异常 都一定会执行的代码  }    
  • finally 代码块通常用于关闭资源
  • 若方法有返回值,那么在try和catch代码块中都需要定义return语句;但是通常情况下 不要在finally代码中定义return语句
//常用结构小结
try{
     }catch(){
     }
try{
     }catch(){
     }catch(){
     }catch(){
     }
try{
     }catch(){
     }finally{
     }
try{
     }catch(){
     }catch(){
     }catch(){
     }finally{
     }
try{
     }finally{
     }
try{
     try{
     }catch(){
     }finally }catch(){
     }
try{
     }catch{
      try{
     }catch(){
     }finally{
     } }
try{
     }catch(){
     }finally{
      try{
     }catch(){
     }finally{
     } }

1. try 后必须跟一个catch或者finally代码块
2.catchfinally同时出现,则finally必须定义在catch之后

自定义异常类【了解】

  1. 要继承于Exception|RuntimeException ;

    继承于Exception 表示已检查异常;继承于RuntimeException 未检查异常

  2. 提供有参无参构造

    class CheckPasswordException extends Exception{
           
    	public CheckPasswordException() {
           
    		super();
    	}
    	public CheckPasswordException(String message) {
           
    		super(message);
    	}
    }
    

I/O流

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

IO流的分类

  • 按方向划分(以JVM为参照物):

    输入流:从外部存储设备 ——> JVM内存 读

    输出流:从JVM内存——>外部存储设备 写

  • 按单位划分

    字节流:以字节为单位,可以操作任意类型的文件

    字符流:以字符为单位,只能操作文本类型的文件;

    ​ 文本类型的文件:使用记事本能够打开的文件.txt, .java , .html…

  • 按功能划分

    节点流 : 只具有基本的读写功能

    过滤流: 在节点流的基础上,增加新的功能。

字节流

  • 字节流抽象父类

    OutputStream (字节输出流) --> 写操作

    ​ |- write(int b):向外部存储设备 写入一个字节

    ​ |- write(byte[] b) : 写入b.length个字节

    ​ |- write(byte[] b, int off, int len): b表示数组,off表示开始下标,len表示写入的长度

    InputStream(字节输入流) --> 读操作

    ​ |- int read() : 从外部存储设备读取一个字节。若没有读取到 则返回-1。

    ​ |- read(byte[] b) : 一次性读取多个字节,并且将读取到的数据存放在b数组中

    ​ |- read(byte[] b, int off, int len):一次性读取len个字节,并且将读取到的数据存放在b数· 组中;存储的位置从off开始,

  • 文件字节流

    1. FileOutputStream : 文件字节输出流

    创建对象

    FileOutputStream fos = new FileOutputStream("文件路径");
    
    注意:
    1. 文件路径中指定的文件,若文件存在则选择已经存在的,若不存在则新创建一个;
    	若文件夹不存在,则不新创建,而是运行报错:
    	报错信息为:java.io.FileNotFoundException
    	
    2.  路径可以定义为绝对路径或者相对路径
    	绝对路径:E:/CoreJava/day20 ----流IO/笔记/a.txt
         相对路径: a.txt              产生的文件在当前项目的根目录下
         
    3. FileOutputStream fos = new FileOutputStream("文件路径"true);   
    	true 代表在原有的文件上进行追加
    	false 代表在原有的文件上进行覆盖,默认为false   
    
    1. FileInputStream : 文件字节输入流
    FileInputStream fos = new FileInputStream("文件路径");
    
    注意:
    1. 路径中指定的文件必须存在,否则运行报错
       报错信息为:java.io.FileNotFoundException
    

如何实现文件复制???

FileInputStream fis = new FileInputStream("E:\\CoreJava\\day20 ----流IO\\上课录屏\\文件字节输入流.wmv");
FileOutputStream fos = new FileOutputStream("file\\文件字节输入流.wmv");
//一边读一边写
while(true) {
     
    int i = fis.read(); //一次性读取一个字节
    if(i==-1) break;  
    fos.write(i);  //写一个字节  90m = 90*1024*1024B
}	
fis.close();
fos.close();
FileInputStream fis = new FileInputStream("E:\\CoreJava\\day20 ----流IO\\上课录屏\\文件字节输入流.wmv");
FileOutputStream fos = new FileOutputStream("file\\文件字节输入流.wmv");
byte[] bs = new byte[1024];
while(true) {
     
    //一次循环读取 1024个字节 = 1KB
    int read = fis.read(bs);
    if(read==-1) break;
    //一次循环写入 1024个字节 = 1KB
    fos.write(bs);
}
fis.close();
fos.close();

包装流

  • 过滤流 BufferedInputStream/BufferedOutputStream
    • 提供了缓冲区,提高了IO效率;减少访问磁盘的次数
    • 一定要记得清空缓冲区 通过flush()方法;也可以直接close();
//1. 创建一个文件字节输入输出流
FileInputStream fis = new FileInputStream("E:\\CoreJava\\day20 ----流IO\\上课录屏\\文件字节输入流.wmv");
FileOutputStream fos = new FileOutputStream("file\\文件字节输入流.wmv");
//2. 创建过滤输入输出流
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos);
//3. 边读边写
while(true) {
     
    int i = bis.read();
    if(i==-1) break;
    bos.write(i);
}
//4. 关流
bis.close();
bos.close();
  • 数据包装流 DataOutputStream/DataInputStream

    • 可以操作八种基本数据类型

      WriteByte(int n)/readByte()writeShort(int n)/readShort()

      writeInt(int n)/readInt()writeLong(long n)/readLong()

      writeFloat(float f)/readFloat()writeDouble/readDouble()

    • 可以操作String数据:writeUTF(String str)/readUTF()

  • 对象过滤流 ObjectInputStream/ObjectOutputStream

    • 增强了基本的读写功能

    • 可以操作八种基本数据类型、字符串类型

    • 增强了读写对象的功能

      readObject(): 从流中读取一个对象

      writeObject(Object obj): 向流中写入一个对象

      1. 进行对象序列化时(把对象放在流上进行传输):需要自定义类实现Serializable接口

    ​ 2. 当读取超出数量的对象时,会运行报错,报错信息为:java.io.EOFException 文件到达结尾异常

    ​ 3. 若自定义类型的属性也是自定义类型,那么属性类型也需实现Serializable 接口

    ​ 4. 在传输集合对象时,若元素是自定义类型,则元素对应的类也必须实现Serializable 接口

    ​ 5. transient :修饰属性,代表此属性不参与序列化

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-obkiuTCR-1574690630593)(D:\feiq\Recv Files\day20 ----流IO\笔记\IO流总结.jpg)]

字符流

编解码

乱码:编码方式和解码方式不一致导致。

常用的编码集

ANSCII 美国

ISO8859 - 1 西欧

GBK 简体中文

BG2312 简体中文

BIG5 繁体中文

UTF-8 万国码

字符流的抽象父类

  • Reader(字符输入流) ——>读操作

    • int read(): 读取的字符内容,若没有则返回-1

    • int read(char[] c): 一次读取多个字符,存放在char数组中

    • int read(char[] b,int off,int len):一次读取多个字符,存放在char数组中;

      ​ 存储的起始下标是off,初始数量len

  • Writer(字符输出流) ——>写操作

    • write(int n): 写入一个字符
    • write(String s) : 写入一个字符串
    • write(char[] c ): 将数组中的字符 写入到文件中

节点流

  • FileWriter 文件字符输出流
  • FileReader 文件字符输入流

过滤流

  • BufferedReader : 过滤字符输入流

    String readLine() : 一次性读取一个文本行;若文件到达结尾则返回null

  • PrintWriter : 过滤字符输出流

    println(String s): 换行写入一个字符串

    当使用缓冲流写入一个对象时,写入的实际上是 对象的字符串表现形式(toString方法的返回值)。

桥转换流

InputStreamReader / OutputStreamWriter

  1. 将字节流转换为字符流
  2. 在转换为字符流时,设置编解码方式
//	1. 创建字节流对象
FileInputStream fis = new FileInputStream("file/e.txt");
//	2.创建桥转换流    将字节流——>字符流
InputStreamReader isr = new InputStreamReader(fis,"utf-8");

步骤总结

创建字节节点流

创建桥转换流,同时设置编解码方式包装过滤流,

方便读写操作读/写操作

关闭流:只需要关闭最外层流

线程

进程:在os(操作系统)中并发的一个任务。

并发:由cpu分配时间片,决定当前执行哪个任务。微观串行(交替执行),宏观并行。

线程:进程中并发的一个任务。

线程的组成【了解】

  • CPU时间片
  • 数据:栈空间独立,堆空间共享
  • 代码

创建线程的两种方式【重重点】

Thread(java.lang):表示线程类

1. 定义一个任务类 实现Runnable接口
2. 创建任务对象
3. 创建Thread对象,提交线程任务
class MyTask implements Runnable{
     
	//重写run方法
    public void run(){
     }
}
------------------------------------
MyTask mt = new MyTask();
Thread t1 = new Thread(mt);
1. 继承Thread类,重写run方法
2. 创建线程子类对象

class MyThread extends Thread{
     
    public void run(){
     }
}
------------------------------------
Thread t2 = new MyThread();

start(): 启动线程

线程的状态【理解+面试重点】

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iD92Jn82-1574690630594)(D:/feiq/Recv Files/day22 ----线程01(1)]/笔记/1574155841632.png)

sleep(long mills): 让当前线程陷入有限期的休眠状态。

t.join() : 让当前线程陷入等待,等待 t 线程执行完毕。

注意: JDK 5.0 开始 就绪状态和运行状态 统称为Runnable状态

线程同步、线程安全【理解+重点】

线程不安全【面试重点】

当多个线程并发访问同一个对象(临界资源)时,破坏了不可被分割的操作(原子操作),会导致数据不一致。

同步代码块

synchronized(Obj){
      	//obj表示Object对象
    //不可分割的代码(原子操作)
}  
  1. 每一个obj对象,都具有一个互斥锁标记。
  2. 想进入同步代码块,必须拥有互斥锁标记。
  3. 同步代码块执行完毕,释放锁标记

同步方法

public synchronized 返回值类型 方法名(){
     
    //不可分割的代码(原子操作)
}
  • 使用当前对象(this)作为临界资源,进行加锁

反射

类的对象:根据一个类实例化的对象(new出来的对象

类对象:类加载的产物,保存在这个类的所有信息(类名、包名、父类、属性、方法、接口、构造方 法…)

获取类对象的三种方式

  1. 通过实例对象获取。对象名.getClass()
Student s = new Student();
Class c1 = s.getClass();  
  1. 通过类名获取 类名.class
Class c2 = Student.class;
  1. 通过静态方法Class.forName("类的全限定名");
Class c3 = Class.forName("demo.Student");  //全限定名:包名+类名
java.lang.reflect包下的类

Filed : 属性

Method : 方法

Constructor : 构造方法

Class类中的方法

  • getFields(): 获取公开属性(父类+子类)
  • c.getDeclaredFields() : 获取所有属性(只包含本类)
  • getMethods(): 获取公开方法(父类+子类)
  • c.getDeclaredMethods() : 获取所有方法(只包含本类)
  • c.getConstructors(): 获取所有的构造方法

根据类对象获取实例对象

Class c = Class.forName("类的全限定名");
Object o = c.newInstance();    //根据类对象获取实例对象

设计模式

单例模式:实现一个类只能创建一个对象

//饿汉式
class B{
     
	private static final B b = new B();
	private B() {
     }
	public static B getInstance() {
        
		return b;
	}
}
//懒汉式
class C{
     
	private static C c = null;
	private C() {
     }
	public static synchronized C getInstance() {
     
		if(c==null) {
        
			c = new C();
		}
		return c;
	}
}

饿汉式:浪费空间。 懒汉式:效率较低

class D{
     
	private static class Inner{
     
		static D d = new D();
	}
	public static D getInstance() {
     
		return Inner.d;
	}
	private D() {
     }
}

开闭原则:对扩展开放,对修改关闭

工厂设计模式

  • 使用反射实现工厂设计模式
public class TestFactory {
     
	public static void main(String[] args) throws Exception {
     
		Scanner  sc  = new Scanner(System.in);
		String name = sc.next();
		Animal a = getAnimal(name);
		a.m1();
	}
	//工厂 : 参数表示类的全限定名
	public static Animal getAnimal(String className) throws Exception {
     
		Class c = Class.forName(className);  //类对象
		Object o = c.newInstance();  //根据类对象获取实例对象
		Animal a = (Animal)o;   //类型转换
		return a;
	}
}
  • 利用流和Properties集合 进行读取配置文件
public class TestFactory {
     
	public static void main(String[] args) throws Exception {
     
		Animal a = getAnimal();
		a.m1();
	}	
	public static Animal getAnimal() throws Exception {
     
//		className  使用流进行读取
//		1. 创建字节流
		FileInputStream fis = new FileInputStream("config.xml");
//		2. 创建Properties集合   调load方法 
		Properties p = new Properties();
//		将配置文件中的数据加载集合中  以=为分割  =前是key  =后是value
		p.load(fis);  
		String className = p.getProperty("className");  //根据key获取value
		
		Class c = Class.forName(className);  //类对象
		Object o = c.newInstance();  //根据类对象获取实例对象
		Animal a = (Animal)o;   //类型转换
		return a;
	}
}

同步方法*

public synchronized 返回值类型 方法名(){
     
    //不可分割的代码(原子操作)
}
  • 使用当前对象(this)作为临界资源,进行加锁

反射

类的对象:根据一个类实例化的对象(new出来的对象

类对象:类加载的产物,保存在这个类的所有信息(类名、包名、父类、属性、方法、接口、构造方 法…)

获取类对象的三种方式

  1. 通过实例对象获取。对象名.getClass()
Student s = new Student();
Class c1 = s.getClass();  
  1. 通过类名获取 类名.class
Class c2 = Student.class;
  1. 通过静态方法Class.forName("类的全限定名");
Class c3 = Class.forName("demo.Student");  //全限定名:包名+类名
java.lang.reflect包下的类

Filed : 属性

Method : 方法

Constructor : 构造方法

Class类中的方法

  • getFields(): 获取公开属性(父类+子类)
  • c.getDeclaredFields() : 获取所有属性(只包含本类)
  • getMethods(): 获取公开方法(父类+子类)
  • c.getDeclaredMethods() : 获取所有方法(只包含本类)
  • c.getConstructors(): 获取所有的构造方法

根据类对象获取实例对象

Class c = Class.forName("类的全限定名");
Object o = c.newInstance();    //根据类对象获取实例对象

设计模式

单例模式:实现一个类只能创建一个对象

//饿汉式
class B{
     
	private static final B b = new B();
	private B() {
     }
	public static B getInstance() {
        
		return b;
	}
}
//懒汉式
class C{
     
	private static C c = null;
	private C() {
     }
	public static synchronized C getInstance() {
     
		if(c==null) {
        
			c = new C();
		}
		return c;
	}
}

饿汉式:浪费空间。 懒汉式:效率较低

class D{
     
	private static class Inner{
     
		static D d = new D();
	}
	public static D getInstance() {
     
		return Inner.d;
	}
	private D() {
     }
}

开闭原则:对扩展开放,对修改关闭

工厂设计模式

  • 使用反射实现工厂设计模式
public class TestFactory {
     
	public static void main(String[] args) throws Exception {
     
		Scanner  sc  = new Scanner(System.in);
		String name = sc.next();
		Animal a = getAnimal(name);
		a.m1();
	}
	//工厂 : 参数表示类的全限定名
	public static Animal getAnimal(String className) throws Exception {
     
		Class c = Class.forName(className);  //类对象
		Object o = c.newInstance();  //根据类对象获取实例对象
		Animal a = (Animal)o;   //类型转换
		return a;
	}
}
  • 利用流和Properties集合 进行读取配置文件
public class TestFactory {
     
	public static void main(String[] args) throws Exception {
     
		Animal a = getAnimal();
		a.m1();
	}	
	public static Animal getAnimal() throws Exception {
     
//		className  使用流进行读取
//		1. 创建字节流
		FileInputStream fis = new FileInputStream("config.xml");
//		2. 创建Properties集合   调load方法 
		Properties p = new Properties();
//		将配置文件中的数据加载集合中  以=为分割  =前是key  =后是value
		p.load(fis);  
		String className = p.getProperty("className");  //根据key获取value
		
		Class c = Class.forName(className);  //类对象
		Object o = c.newInstance();  //根据类对象获取实例对象
		Animal a = (Animal)o;   //类型转换
		return a;
	}
}

你可能感兴趣的:(Codejava知识点)