Java基础——狂神说

Java基础——狂神说

文章目录

一、第一章——基础语法

1、标识符

合法标识符的规范

JavaC语言
由26个英文字母大小写,0-9 ,_或 $ 组成由字母、下划线(_)或数字(0~9)组成
数字不可以开头。必须由一个字母或下划线(_)开头
不可以使用关键字,但能包含关键字。
Java中严格区分大小写,长度无限制。
标识符不能包含空格。

2、变量、数据类型、常量

2.1、变量的分类
2.1.1、按数据类型分类

分为:基本数据类型和引用数据类型
1、基本数据类型包括:数值型(byte,short,int,long,float,double)、字符型(char)、布尔型(boolean)
2、引用数据类型包括:类(字符串包括在内)、接口、数组

2.1.1.1、浮点类型

注意:最好避免完全使用float数进行比较(下面代码是反例)

 public static void main(String[] args) {
        float num1 = 1321546541212154f;
        float num2 = num1 + 100.54152113124f;
        System.out.println(num1 == num2);
    }
    /*
    运行结果为:true
		*/
2.1.2、按声明的位置的不同分类

在方法体外,类体内声明的变量成为成员变量
在方法体内声明的变量成为局部变量
1、成员变量包括:实例变量、类变量
2、局部变量包括:形参、方法局部变量、代码块局部变量

3、基本数据类型转换

容量大——>容量小:强制类型转换
容量小——>容量大:自动类型转换
自动类型转换:容量小的类型自动转换为容量大的数据类型。数据类型按容量大小排序为:(char、byte、short)、int、long、float、double

public static void main(String[] args) {
        double num1 = 14.235;
        int num2 = (int)num1;
        System.out.println(num2);//(强制类型转换)

        int num3 = 123;
        double num4 = num3;
        System.out.println(num4);//(自动类型转换)
    }
    /*
    运行结果为:14
    		  123.0
    */

4、常量

常量:初始化后不能再改变值!不会变动的值
常量名一般使用大写字符

final 常量名 =;
final double PT = 3.14;

5、名称的命名规则

包名:多单词组成时所有字母都小写:xxxyyyzzz。
类名、接口名:多单词组成时,所有单词的首字母大写:XxxYyyZzz。
变量名、方法名:多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写:xxxYyyZzz。
常量名:所有字母都大写。多单词时每个单词用下划线链接:XXX_YYY_ZZZ。

6、运算符

大部分与c语言的运算符类似,新增了“instanceof”运算符,用来测试指定对象是否是指定类型(类或子类或接口)的实例。
需要注意的是 :逻辑与(&)和短路与(&&)的区别:
“&”:左边表达式无论真假,右边都进行运算。
“&&”:如果左边为真,右边参与运算,如果左边为假,那么右边不参与运算。

二、第二章——流程控制

1、用户交互Scanner

1.1 基本语法
Scanner scan = new Scannner(System.in);
1.2 next()和nextLine()的区别

1、next():获取输入的字符串
next()不能得到带有空格的字符串,不能获得空白
2、hasNext():判断是否还有输入的数据

 public static void main(String[] args) {
        //创建一个Scanner对象
        Scanner scanner = new Scanner(System.in);
        System.out.println("使用next方式接受:");
        //判断是否输入字符串
        if(scanner.hasNext()){
            String str = scanner.next();
            System.out.println("输入的内容为:" + str);
        }
        scanner.close();
    }
    /*
    键盘输入内容:hello world
    输出结果:hello
		*/

1、nextLine():获取输入的字符串
next()以Enter为结束符,可以获得空白
2、hasNexLinet():判断是否还有输入的数据

public static void main(String[] args) {
        //创建一个Scanner对象
        Scanner scanner = new Scanner(System.in);
        System.out.println("使用nextLine方式接受:");
        //判断是否输入字符串
        if(scanner.hasNextLine()){
            String str = scanner.nextLine();
            System.out.println("输入的内容为:" + str);
        }
        scanner.close();
    }
    /*
    键盘输入内:hello world
    输出结果:hello world
		*/

2、顺序结构

与c语言内容类似,不赘述。

3、选择结构

与c语言内容类似,不赘述。

4、循环结构

其他内容与c语言内容类似,不赘述。

增强for循环

增强for循环:主要用于数组或集合
声明语句:声明新的局部变量,该类型与数组元素的类型匹配。
表达式:访问的数组名,或者是返回值为数组的方法

for(声明语句 : 表达式)
{
	//代码句子
}

三、第三章——方法

1、方法的重载

1、方法名称必须相同
2、参数列表必须不同(个数不同、类型不同、参数排序顺序不同)
3、方法的返回类型可以相同也可以不相同

2、可变参数

1、在方法声明中,在指定参数类型后加一个省略号(…)。
2、可变参数必须是方法的最后一个参数。

public static void main(String[] args) {
        double[] scores = new double[]{60,70,80,90,40};
        demo01.test(scores.length,scores);
    }
    public static void test(int count , double ... scores){
        if(count <= 0){
            System.out.println("无输入的数据");
        }else{
            System.out.println("输入的数据为:");
            for (int i = 0; i < scores.length; i++) {
                System.out.print(scores[i] + "\t");
            }
        }
    }
    /*
    输出的结果为:    
    输入的数据为:
	60.0	70.0	80.0	90.0	40.0
    */

3、递归算法

3.1、递归的思路

一个方法在执行时,调用自身被称为“递归”。
递归相当于数学归纳法,有一个起始条件,有一个递推公式。
递归可以分为:单路递归和多路递归(如二叉树和斐波那契数列)。

3.2、代码演示——斐波那契数列

斐波那契数列:1 1 2 3 5 8 13

public static void main(String[] args) {
        System.out.println(fib(7));//输出的结果为:13
    }
    public static int fib(int n){
        if(n==1 || n==2){
            return 1;
        }
        return fib(n-1) + fib(n-2);
    }

四、第四章——数组

1、一维数组

1.1、一维数组的声明
dataType[] arrayRefVar;//首选
或者
dateType arrayRefVar[];
1.2、一维数组的三种初始化
1.2.1、静态初始化
int arr[] = new int[]{3,9,8};
或者
int[] arr = {3,9,8};
或者
String names[] = {"张三","李四","王五"};
1.2.2、动态初始化
int[] arr = new int[3];
arr[0] = 3;
arr[1] = 9;
arr[2] = 8;
或者
String names[];
names = new String[3];
names[0] = "张三";
names[1] = "李四";
names[2] = "王五";
1.2.3、默认初始化及默认初始化值

数组一经分配空间,其中每个元素也被隐式初始化。
默认初始化值:

数组元素类型元素默认初始化值
byte0
short0
int0
long0L
float0.0F
double0.0
char0或写为:‘\u0000’(表现为空)
booleanfalse
引用类型null
1.3、内存分析

内存分析
内存解析实例
内存解析实例

2、二维数组

2.1、二维数组的两种初始化方式
2.1.1、静态初始化
int[][] arr = new int[][]{{{3,8,2},{2,7},{9,0,1,6}};

注意特殊写法:int[] x, y[];
x是一维数组,y是二维数组。
2.1.2、动态初始化
格式1int[][] arr = new int[3][2];

格式2int[][] arr = new int[3][];
2.内存解析

内存解析

3、Arrays工具类的使用

boolean equals(int []a,int []b):判断两个数组是否相等。
String toString(int[] a):输出数组信息。
void fill(int []a,int val):将指定值填充到数值之中。
void sort(int[] a):对数组进行排序。
int binarySearch(int[] a, int key):对排序后的数组进行二分法检索指定的值。

public static void main(String[] args) {
        int[] arr = new int[]{11,22,33,445,4535,-43656};
        //输出数组信息
        System.out.println(Arrays.toString(arr));
        //将指定值填充到数组中,包前不包后
        Arrays.fill(arr,2,4,0);
        System.out.println(Arrays.toString(arr));
        //判断两个数组是否相等
        boolean isFlag = Arrays.equals(arr, new int[]{10,20});
        System.out.println(isFlag);
    }
    /*
    输出结果为:
    [11, 22, 33, 445, 4535, -43656]
	[11, 22, 0, 0, 4535, -43656]
	false
		*/

4、稀疏数组

当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组。
行数:非0元素个数+1。其中第一行的分别代表着数组的行数、列数和非0元素个数。第二行开始每一行分别代表着非0元素所在的行号、列号和元素值。
列数:3列

public static void main(String[] args) {
        int[][] arr1 = new int[][]{
                {0,0,0,22,0,0,15},
                {0,11,0,0,0,17,0},
                {0,0,0,-6,0,0,0},
                {0,0,0,0,0,39,0},
                {91,0,0,0,0,0,0},
                {0,0,28,0,0,0,0}
        };
        //输出原数组,并记录非零元素个数
        int totalCount = 0;
        System.out.println("原数组为:");
        for (int[] x : arr1) {
            for(int y : x){
                System.out.print(y + "\t");
                if(y != 0)
                    totalCount++;
            }
            System.out.println();
        }
        System.out.println("******************************");
        //创建稀疏数组
        int[][] arr2 = new int[totalCount + 1][3];
        //初始化稀疏数组
        arr2[0][0] = arr1.length;
        arr2[0][1] = arr1[0].length;
        arr2[0][2] = totalCount;
        int count = 1;//记录稀疏数组的行数
        for (int i = 0; i < arr1.length; i++) {
            for (int j = 0; j < arr1[i].length; j++) {
                if(arr1[i][j] != 0){
                    arr2[count][0] = i;
                    arr2[count][1] = j;
                    arr2[count][2] = arr1[i][j];
                    count++;
                }
            }
        }
        //输出稀疏数组
        System.out.println("稀疏数组为:");
        for (int[] x : arr2) {
            for(int y : x){
                System.out.print(y + "\t");
                if(y != 0)
                    totalCount++;
            }
            System.out.println();
        }
    }
    /*
    输出结果:
    原数组为:
	0	0	0	22	0	0	15	
	0	11	0	0	0	17	0	
	0	0	0	-6	0	0	0	
	0	0	0	0	0	39	0	
	91	0	0	0	0	0	0	
	0	0	28	0	0	0	0	
	******************************
	稀疏数组为:
	6	7	8	
	0	3	22	
	0	6	15	
	1	1	11	
	1	5	17	
	2	3	-6	
	3	5	39	
	4	0	91	
	5	2	28	
    */

五、第五章——面向对象

1、什么是面向对象

1.1、面向对象和面向过程

面向过程:强调的是功能行为,以函数为最小单位,考虑怎么做。
面向对象:强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。

1.2、面向对象的本质及三大特性

面向对象的本质:以类的方式组织代码,以对象的组织(封装)数组。
三大特性:封装、继承、多态。

2、类和对象

2.1、概念

:对一类事物的描述,是抽象的、概念上的定义
对象:是实际存在的该类事物的每个个体,因而也称为实例(instance)
--------面向对象程序设计的重点是类的设计
--------设计类,就是设计类的成员。

2.2、二者关系

对象,是由类new出来的,派生出来的。

2.3、对象的创建与对象的内存解析
2.3.1、对象的创建
Person p1 = new Person();
Person p2 = new Person();
Person p3 = p1;//没有创建一个对象,p3和p1共用一个堆空间的对象实体。
2.3.2对象的内存解析

对象的内存解析

2.4、匿名对象

匿名对象:我们创建的对象,没显式的赋给一个变量名。
特点:匿名对象只能调用一次。

new Phone().sendEmail();
new Phone().playGame();

new Phone.price = 1999;
new Phone().showPrice();//0.0

3、类的五个成员

类的成员:属性、方法、构造器;代码块、内部类。

3.1、属性
3.1.1、属性和局部变量的相同点
  1. 定义变量的格式:数据类型 变量名 = 变量值
  2. 先声明,后使用
  3. 变量都其对应的作用域
3.1.2、属性和局部变量的不同点
  • 1、在类中声明的位置的不同
    ——属性:直接定义在类的一对{}内
    ——局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量
  • 2、关于权限修饰符的不同
    ——属性:可以在声明属性时,指明其权限,使用权限修饰符。
    常用的权限修饰符:private、public、缺省、protected —>封装性
    ——局部变量:不可以使用权限修饰符。
  • 3、默认初始化值的情况
    ——属性:类的属性,根据其类型,都默认初始化值。
    整型(byte、short、int、long:0)
    浮点型(float、double:0.0)
    字符型(char:0 (或’\u0000’))
    布尔型(boolean:false)
    引用数据类型(类、数组、接口:null)
    ——局部变量:没默认初始化值。
    意味着,我们在调用局部变量之前,一定要显式赋值。
    特别地:形参在调用时,我们赋值即可。
  • 4、在内存中加载的位置
    —— 属性:加载到堆空间中 (非static)
    ——局部变量:加载到栈空间
3.2、方法
3.2.1、方法的声明

权限修饰符 返回值类型 方法名(形参列表){ 方法体 }

3.2.2、说明
  • 1、关于权限修饰符:默认方法的权限修饰符先都使用public
    Java规定的4种权限修饰符:private、public、缺省、protected -->封装性再细说
  • 2、返回值类型: 返回值 vs 没返回值
    ——如果方法返回值,则必须在方法声明时,指定返回值的类型。同时,方法中,需要使用return关键字来返回指定类型的变量或常量:“return 数据”。
    ——如果方法没返回值,则方法声明时,使用void来表示。通常,没返回值的方法中,就不需要使用return.但是,如果使用的话,只能“return;”表示结束此方法的意思。
  • 3、方法名:属于标识符,遵循标识符的规则和规范,“见名知意”
  • 4、形参列表: 方法可以声明0个,1个,或多个形参。
    ——格式:数据类型1 形参1,数据类型2 形参2,…
  • 5、方法体:方法功能的体现。
3.3、构造器
3.3.1、作用

1.创建对象
2.初始化对象的信息

3.3.2、使用说明

1.如果没显式的定义类的构造器的话,则系统默认提供一个空参的构造器
2.定义构造器的格式:权限修饰符 类名(形参列表){}
3.一个类中定义的多个构造器,彼此构成重载
4.一旦我们显式的定义了类的构造器之后,系统就不再提供默认的空参构造器
5.一个类中,至少会有一个构造器。

3.3.3、代码举例
    //构造器
	public Person(){
		System.out.println("Person().....");
	}
	
	public Person(String n){
		name = n;
		
	}
	
	public Person(String n,int a){
		name = n;
		age = a;
	}
3.4、代码块
3.4.1、作用

代码块的作用:用来初始化类、对象的信息

3.4.2、静态代码块 VS 非静态代码块
静态代码块非静态代码块
作用:初始化类的信息作用:可以在创建对象时,对对象的属性等进行初始化
内部可以输出语句内部可以输出语句
随着类的加载而执行,而且只执行一次随着对象的创建而执行
如果一个类中定义了多个静态代码块,则按照声明的先后顺序执行如果一个类中定义了多个非静态代码块,则按照声明的先后顺序执行
静态代码块的执行要优先于非静态代码块的执行每创建一个对象,就执行一次非静态代码块
静态代码块内只能调用静态的属性、静态的方法,不能调用非静态的结构非静态代码块内可以调用静态的属性、静态的方法,或非静态的属性、非静态的方法
3.4.3、属性赋值的顺序
  • ①默认初始化

  • ②显式初始化/⑤在代码块中赋值

  • ③构造器中初始化

  • ④有了对象以后,可以通过"对象.属性"或"对象.方法"的方式,进行赋值

  • 执行的先后顺序:① ——>② / ⑤ ——> ③—— > ④

3.5、内部类
3.5.1、定义

定义:Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类.

3.5.2、分类

成员内部类(静态、非静态 )VS 局部内部类(方法内、代码块内、构造器内)

3.5.3、对于成员内部类的理解

一方面,作为外部类的成员:
1.调用外部类的结构
2.可以被static修饰
3.可以被4种不同的权限修饰
另一方面,作为一个类:
1.类内可以定义属性、方法、构造器等
2.可以被final修饰,表示此类不能被继承。言外之意,不使用final,就可以被继承
3.可以被abstract修饰

3.5.4、成员内部类
3.5.4.1、如何创建成员内部类的对象?(静态的,非静态的)
//创建静态的Dog内部类的实例(静态的成员内部类):
Person.Dog dog = new Person.Dog();

//创建非静态的Bird内部类的实例(非静态的成员内部类):
//Person.Bird bird = new Person.Bird();//错误的
Person p = new Person();
Person.Bird bird = p.new Bird();
3.5.4.2、如何在成员内部类中调用外部类的结构?
class Person{
	String name = "小明";
	public void eat(){
}
//非静态成员内部类
	class Bird{
		String name = "杜鹃";
		public void display(String name){
			System.out.println(name);//方法的形参
			System.out.println(this.name);//内部类的属性
			System.out.println(Person.this.name);//外部类的属性
			Person.this.eat();//外部类的方法
		}
	}
}
3.5.5、局部内部类的使用
//返回一个实现了Comparable接口的类的对象
	public Comparable getComparable(){
		//创建一个实现了Comparable接口的类:局部内部类
		//方式一:
//		class MyComparable implements Comparable{
//
//			@Override
//			public int compareTo(Object o) {
//				return 0;
//			}
//			
//		}
//		
//		return new MyComparable();
		
		//方式二:
		return new Comparable(){

			@Override
			public int compareTo(Object o) {
				return 0;
			}
			
		};
		
	}

4、面向对象的三大特征

面向对象的三大特征为:封装性、继承性、多态性

4.1、封装性
4.1.1、封装性思想具体的代码体现:
  • 体现一:将类的属性xxx私化(private),同时,提供公共的(public)方法来获取(getXxx)和设置(setXxx)此属性的值
private double radius;
public void setRadius(double radius){
	this.radius = radius;
}
public double getRadius(){
	return radius;
}
  • 体现二:不对外暴露的私有的方法
  • 体现三:单例模式(将构造器私有化)
  • 体现四:如果不希望类在包外被调用,可以将类设置为缺省的。
4.1.2、Java规定的四种权限修饰符
4.1.2.1、权限从小到大顺序为:private < 缺省 < protected < public
4.1.2.2、具体的修饰范围:

private:类内部。
(缺省):类内部、同一个包下。
protected:类内部、同一个包下、不同包的子类。
public:类内部、同一个包下、不同包的子类、同一个工程。

4.1.2.3、权限修饰符可用来修饰的结构说明:

4种权限都可以用来修饰类的内部结构:属性、方法、构造器、内部类。
修饰类的话,只能使用:缺省、public

4.2、继承性
4.2.1、继承性的格式:
class A extends B{}
 *    A:子类、派生类、subclass
 *    B:父类、超类、基类、superclass
4.2.2、子类继承父类以后有哪些不同?
  • 1.体现:一旦子类A继承父类B以后,子类A中就获取了父类B中声明的所有的属性和方法。
    特别的,父类中声明为private的属性或方法,子类继承父类以后,仍然认为获取了父类中私的结构。只因为封装性的影响,使得子类不能直接调用父类的结构而已。
  • 2.子类继承父类以后,还可以声明自己特有的属性或方法:实现功能的拓展。
    子类和父类的关系,不同于子集和集合的关系。
    extends:延展、扩展
4.2.3、Java中继承性的说明

1.一个类可以被多个子类继承。
2.Java中类的单继承性:一个类只能有一个父类
3.子父类是相对的概念。
4.子类直接继承的父类,称为:直接父类。间接继承的父类称为:间接父类
5.子类继承父类以后,就获取了直接父类以及所间接父类中声明的属性和方法

4.3、多态性
4.3.1、何为多态性?

对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)
举例:
Person p = new Man();
Object obj = new Date();

4.3.2、多态性的使用前提:

① 类的继承关系 ② 方法的重写

4.3.3、代码举例
	public void func(Animal animal){//Animal animal = new Dog();
		animal.eat();
		animal.shout();
	}
4.3.4、多态性使用的注意点:

对象的多态性,只适用于方法,不适用于属性(编译和运行都看左边)

4.3.5、关于向上转型与向下转型:
4.3.5.1、向上转型:多态
4.3.5.2、向下转型:
  • 1 为什么使用向下转型:
    有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的,但是由于变量声明为父类类型,导致编译时,只能调用父类中声明的属性和方法。子类特有的属性和方法不能调用。如何才能调用子类特的属性和方法?使用向下转型。
  • 2 如何实现向下转型:
    使用强制类型转换符:()
  • 3 使用时的注意点:
    ① 使用强转时,可能出现ClassCastException的异常。
    ② 为了避免在向下转型时出现ClassCastException的异常,我们在向下转型之前,先进行instanceof的判断,一旦返回true,就进行向下转型。如果返回false,不进行向下转型。
  • 4 instanceof的使用:
    ① a instanceof A:判断对象a是否是类A的实例。如果是,返回true;如果不是,返回false。
    ② 如果 a instanceof A返回true,则 a instanceof B也返回true.其中,类B是类A的父类。
    ③ 要求a所属的类与类A必须是子类和父类的关系,否则编译错误。

5、其它关键字:this、super、static、final、abstract、interface、package、import等

5.1、this关键字

可以调用的结构:属性、方法;构造器

5.1.1、this调用属性、方法:
  • this理解为:当前对象 或 当前正在创建的对象
  • 1、在类的方法中,我们可以使用"this.属性"或"this.方法"的方式,调用当前对象属性或方法。但是,
    通常情况下,我们都择省略"this."。特殊情况下,如果方法的形参和类的属性同名时,我们必须显式
    的使用"this.变量"的方式,表明此变量是属性,而非形参。
  • 2 、在类的构造器中,我们可以使用"this.属性"或"this.方法"的方式,调用当前正在创建的对象属性或方法。但是,通常情况下,我们都择省略"this."。特殊情况下,如果构造器的形参和类的属性同名时,我们必须显式的使用"this.变量"的方式,表明此变量是属性,而非形参。
5.1.2、this调用构造器:

① 我们在类的构造器中,可以显式的使用"this(形参列表)"方式,调用本类中指定的其他构造器
② 构造器中不能通过"this(形参列表)“方式调用自己
③ 如果一个类中有n个构造器,则最多有 n - 1构造器中使用了"this(形参列表)”
④ 规定:"this(形参列表)“必须声明在当前构造器的首行
⑤ 构造器内部,最多只能声明一个"this(形参列表)”,用来调用其他的构造器

5.2、关键字:package/import
5.2.1、package的使用
  • 1.为了更好的实现项目中类的管理,提供包的概念
  • 2.使用package声明类或接口所属的包,声明在源文件的首行
  • 3.包,属于标识符,遵循标识符的命名规则、规范(xxxyyyzzz)、“见名知意”
  • 4.每"."一次,就代表一层文件目录。
5.2.2、JDK中的主要包介绍:

1、java.lang:包含一些常用类,如String、Math、Integer、System和Thread。
2、java.net:包含执行与网络相关的操作的类和接口。
3、java.io:提供多种输入/输出功能的类。
4、java.util:包含一些使用工具类。
5、java.text:包含一些java格式化相关的类。
6、java.sql:包含java进行JDBC数据库编程的相关类/接口。
7、java.awt:包含了构成抽象窗口工具集的多个类。

5.2.2、import的使用

import:导入

  1. 在源文件中显式的使用import结构导入指定包下的类、接口
  2. 声明在包的声明和类的声明之间
  3. 如果需要导入多个结构,则并列写出即可
  4. 可以使用"xxx.*"的方式,表示可以导入xxx包下的所结构
  5. 如果使用的类或接口是java.lang包下定义的,则可以省略import结构
  6. 如果使用的类或接口是本包下定义的,则可以省略import结构
  7. 如果在源文件中,使用了不同包下的同名的类,则必须至少一个类需要以全类名的方式显示。
  8. 使用"xxx.*"方式表明可以调用xxx包下的所结构。但是如果使用的是xxx子包下的结构,则仍需要显式导入
  9. import static:导入指定类或接口中的静态结构:属性或方法。
5.3、关键字:super
  • super 关键字可以理解为:父类的
  • 可以用来调用的结构:属性、方法、构造器
5.3.1、super调用属性、方法:
  • 1 我们可以在子类的方法或构造器中。通过使用"super.属性"或"super.方法"的方式,显式的调用父类中声明的属性或方法。但是,通常情况下,我们习惯省略"super."
  • 2 特殊情况:当子类和父类中定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须显式的使用"super.属性"的方式,表明调用的是父类中声明的属性。
  • 3 特殊情况:当子类重写了父类中的方法以后,我们想在子类的方法中调用父类中被重写的方法时,则必须显式的使用"super.方法"的方式,表明调用的是父类中被重写的方法。
5.3.2、super调用构造器:
  • 1 我们可以在子类的构造器中显式的使用"super(形参列表)"的方式,调用父类中声明的指定的构造器
  • 2 "super(形参列表)"的使用,必须声明在子类构造器的首行!
  • 3 我们在类的构造器中,针对于"this(形参列表)"或"super(形参列表)"只能二一,不能同时出现
  • 4 在构造器的首行,没显式的声明"this(形参列表)“或"super(形参列表)”,则默认调用的是父类中空参的构造器:super()
  • 5 在类的多个构造器中,至少一个类的构造器中使用了"super(形参列表)",调用父类中的构造器
5.4、关键字:static

static可以用来修饰的结构:主要用来修饰类的内部结构,如属性、方法、代码块、内部类

5.4.1、static修饰属性:静态变量(或类变量)
  • 1 属性,是否使用static修饰,又分为:静态属性 vs 非静态属性(实例变量)
    实例变量:我们创建了类的多个对象,每个对象都独立的拥一套类中的非静态属性。当修改其中一个对象中的非静态属性时,不会导致其他对象中同样的属性值的修改。
    静态变量:我们创建了类的多个对象,多个对象共享同一个静态变量。当通过某一个对象修改静态变量时,会导致其他对象调用此静态变量时,是修改过了的。
  • 2 static修饰属性的其他说明:
    ① 静态变量随着类的加载而加载。可以通过"类.静态变量"的方式进行调用
    ② 静态变量的加载要早于对象的创建。
    ③ 由于类只会加载一次,则静态变量在内存中也只会存在一份:存在方法区的静态域中。
  • 3 静态属性举例:System.out; Math.PI;
5.4.2、静态变量内存解析:

静态变量内存解析

5.4.3、static修饰方法:静态方法、类方法

① 随着类的加载而加载,可以通过"类.静态方法"的方式进行调用
② 静态方法中,只能调用静态的方法或属性
非静态方法中,既可以调用非静态的方法或属性,也可以调用静态的方法或属性

5.4.4、使用举例

举例一:Arrays、Math、Collections等工具类
举例二:

class Circle{
	private double radius;
	private int id;//自动赋值
	
	public Circle(){
		id = init++;
		total++;
	}
	
	public Circle(double radius){
		this();
//		id = init++;
//		total++;
		this.radius = radius;
		
	}
	
	private static int total;//记录创建的圆的个数
	private static int init = 1001;//static声明的属性被所对象所共享
	
	public double findArea(){
		return 3.14 * radius * radius;
	}

	public double getRadius() {
		return radius;
	}

	public void setRadius(double radius) {
		this.radius = radius;
	}

	public int getId() {
		return id;
	}

	public static int getTotal() {
		return total;
	}
}
5.5、关键字:final

final可以用来修饰:类、方法、变量

  • 1 final 用来修饰一个类:此类不能被其他类所继承。
    比如:String类、System类、StringBuffer类
  • 2 final 用来修饰方法:表明此方法不可以被重写
    比如:Object类中getClass();
  • 3 final 用来修饰变量:此时的"变量"就称为是一个常量
    ①final修饰属性:可以考虑赋值的位置:显式初始化、代码块中初始化、构造器中初始化
    ② final修饰局部变量: 尤其是使用final修饰形参时,表明此形参是一个常量。当我们调用此方法时,给常量形参赋一个实参。一旦赋值以后,就只能在方法体内使用此形参,但不能进行重新赋值。

static final 用来修饰属性:全局常量

5.6、关键字:abstract

abstract可以用来修饰:类、方法

5.6.1、abstract修饰类:抽象类
  1. 此类不能实例化
  2. 抽象类中一定有构造器,便于子类实例化时调用(涉及:子类对象实例化的全过程)
  3. 开发中,都会提供抽象类的子类,让子类对象实例化,完成相关的操作 —>抽象的使用前提:继承性
5.6.2、abstract修饰方法:抽象方法
  1. 抽象方法只方法的声明,没方法体
  2. 包含抽象方法的类,一定是一个抽象类。反之,抽象类中可以没有抽象方法的。
  3. 若子类重写了父类中的所的抽象方法后,此子类方可实例化
    若子类没重写父类中的所的抽象方法,则此子类也是一个抽象类,需要使用abstract修饰
5.6.3、注意点
  • 1.abstract不能用来修饰:属性、构造器等结构
  • 2.abstract不能用来修饰私有方法、静态方法、final的方法、final的类
5.6.4、abstract的应用举例:

举例一:

public abstract class Vehicle{
	public abstract doulbe calcFuelEfficiency();//计算燃料效率的抽象方法
	public abstract doulbe calcTripDistance();//计算行驶距离的抽象方法
}
public class Truck extends Vehicle{
	public doulbe calcFuelEfficiency();{//写出计算卡车的燃料距离的具体方法}
	public doulbe calcTripDistance();{//写出计算卡车行驶距离的具体方法}
}
public class RiverBarge extends Vehicle{
	public doulbe calcFuelEfficiency();{//写出计算驳船的燃料距离的具体方法}
	public doulbe calcTripDistance();{//写出计算驳船行驶距离的具体方法}
}

举例二:

abstract class GeometricObject{
		public abstract double findArea();
}
class Circle extends GeometricObject{
		private double radius;
		
		public double findArea(){
			return 3.14 * radius * radius;
  };
}
5.7、关键字:interface
5.7.1、使用说明
  • 1.接口使用interface来定义
  • 2.Java中,接口和类是并列的两个结构
  • 3.如何定义接口:定义接口中的成员
    3.1 JDK7及以前:只能定义全局常量和抽象方法
    全局常量:public static final的.但是书写时,可以省略不写
    抽象方法:public abstract的
    3.2 JDK8:除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法(略
  • 4.接口中不能定义构造器的!意味着接口不可以实例化
  • 5.Java开发中,接口通过让类去实现(implements)的方式来使用.
    如果实现类覆盖了接口中的所抽象方法,则此实现类就可以实例化
    如果实现类没覆盖接口中所的抽象方法,则此实现类仍为一个抽象类
  • 6.Java类可以实现多个接口 —>弥补了Java单继承性的局限性
    格式:class AA extends BB implements CC,DD,EE
  • 7.接口与接口之间可以继承,而且可以多继承
  • 8.接口的具体使用,体现多态性
  • 9.接口,实际上可以看做是一种规范
5.7.2、举例:
class Computer{
	public void transferData(USB usb){//USB usb = new Flash();
		usb.start();
		System.out.println("具体传输数据的细节");
		usb.stop();
	}
}

interface USB{
	//常量:定义了长、宽、最大最小的传输速度等
	void start();
	void stop();
}

class Flash implements USB{
	@Override
	public void start() {
		System.out.println("U盘开启工作");
	}
	@Override
	public void stop() {
		System.out.println("U盘结束工作");
	}
}

class Printer implements USB{
	@Override
	public void start() {
		System.out.println("打印机开启工作");
	}
	@Override
	public void stop() {
		System.out.println("打印机结束工作");
	}
}
5.7.3、Java8中关于接口的新规范
  • 1.接口中定义的静态方法,只能通过接口来调用。
  • 2.通过实现类的对象,可以调用接口中的默认方法。
    如果实现类重写了接口中的默认方法,调用时,仍然调用的是重写以后的方法
  • 3.如果子类(或实现类)继承的父类和实现的接口中声明了同名同参数的默认方法,那么子类在没重写此方法的情况下,默认调用的是父类中的同名同参数的方法。–>类优先原则
  • 4.如果实现类实现了多个接口,而这多个接口中定义了同名同参数的默认方法,
    那么在实现类没重写此方法的情况下,报错。–>接口冲突。
    这就需要我们必须在实现类中重写此方法
  • 5.如何在子类(或实现类)的方法中调用父类、接口中被重写的方法
    public void myMethod(){
    method3();//调用自己定义的重写的方法
    super.method3();//调用的是父类中声明的
    //调用接口中的默认方法
    CompareA.super.method3();
    CompareB.super.method3();
    }

六、第六章——异常

  • 1.异常:在Java语言中,将程序执行中发生的不正常情况称为“异常”。 (开发过程中的语法错误和逻辑错误不是异常)
  • 2.Java程序在执行过程中所发生的异常事件可分为两类:
    ①Error:Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。比如:StackOverflowError和OOM。一般不编写针对性的代码进行处理。
    ②Exception: 其它因编程错误或偶然的外在因素导致的一般性问题,可以使
    用针对性的代码进行处理。例如:空指针访问、试图读取不存在的文件、网络连接中断、数组角标越界。

1、异常体系及异常分类

1.1、异常体系

java.lang.Throwable
|-----java.lang.Error:一般不编写针对性的代码进行处理。
|-----java.lang.Exception:可以进行异常的处理
|------编译时异常(checked)
|-----IOException
|-----FileNotFoundException
|-----ClassNotFoundException
|------运行时异常(unchecked,RuntimeException)
|-----NullPointerException
|-----ArrayIndexOutOfBoundsException
|-----ClassCastException
|-----NumberFormatException
|-----InputMismatchException
|-----ArithmeticException

1.2、异常分类
1.2.1、运行时异常

是指编译器不要求强制处置的异常。一般是指编程时的逻辑错误。对于这类异常,可以不做处理。

1.2.2、编译时异常

是指编译器要求必须处理的异常。

2、常见的异常
2.1、常见的异常

java.lang.RuntimeException
ClassCastException
ArrayIndexOutOfBoudsException
NullPointerException
ArithmeticException
NumberFormatException
InputMismatchException
java.io.IOException
FiletNotFoundExcption
EOFException
java.lang.ClassNotFoutdException
java.lang.InterruptedException
java.io.RuntimeException
java.sql.SQLException

2.2、代码举例
2.2.1、ArrayIndexOutOfBoundsException
 public static void main(String[] args) {
        String friends[] = { "lisa", "bily", "kessy" };
        for (int i = 0; i < 5; i++) {
            System.out.println(friends[i]); // friends[4]?
        }
        System.out.println("\nthis is the end");
    }
    /*
    运行结果:
    lisa
	bily
	kessy
	Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException:3
		atcom.atguigu.Exception.java.ArrayIndexOutOfBoundsException.main(ArrayIndexOutOfBoundsException.java:11)
    */
2.2.2、NullPointerException
public class NullRef {
        int i = 1;
        public static void main(String[] args) {
            NullRef t = new NullRef();
            t = null;
            System.out.println(t.i);
        }
}
	/*
	运行结果:
	Exception in thread "main" java.lang.NullPointerException
		at com.atguigu.Exception.java.NullRef.main(NullRef.java:12)
	*/
2.2.3、ArithmeticException
public class ArithmeticExceptionTest {
    int x;
    public static void main(String[] args) {
        int y;
        ArithmeticExceptionTest c=new ArithmeticExceptionTest();
        y=3/c.x;
        System.out.println("program ends ok!");
    }
}
	/*
	运行结果:
	Exception in thread "main" java.lang.ArithmeticException: / by zero
		at com.atguigu.Exception.java.ArithmeticExceptionTest.main(ArithmeticExceptionTest.java:12)
	*/
2.2.4、ClassCastException
public class ClassCastExceptionTest {
    public static void main(String[] args) {
        Object obj = new ClassCastExceptionTest();
        String str = (String)obj;
    }
}
	/*
	运行结果;
	 Exception in thread "main" java.lang.ClassCastException: com.atguigu.Exception.java.ClassCastExceptionTest cannot be cast to java.lang.String
		at com.atguigu.Exception.java.ClassCastExceptionTest.main(ClassCastExceptionTest.java:10)
	*/
3、异常处理
3.1、java异常处理的抓抛模型
  • 过程一:“抛”:程序在正常执行的过程中,一旦出现异常,就会在异常代码处生成一个对应异常类的对象。 并将此对象抛出。一旦抛出对象以后,其后的代码就不再执行。
    关于异常对象的产生:① 系统自动生成的异常对象 ② 手动的生成一个异常对象,并抛出(throw)
  • 过程二:“抓”:可以理解为异常的处理方式:① try-catch-finally ② throws
3.2、异常处理方式一:try-catch-finally
3.2.1、使用说明
try{
	//可能出现异常的代码
 }catch(异常类型1 变量名1){
  		//处理异常的方式1
 }catch(异常类型2 变量名2){
 		//处理异常的方式2
 }catch(异常类型3 变量名3){
 		//处理异常的方式3
}
 ....
 finally{
 		//一定会执行的代码
 }
  • 说明:
  • 1.finally是可选的。
  • 2.finally中声明的是一定会被执行的代码。即使catch中又出现异常了,try中return语句,catch中return语句等情况。
  • 3.像数据库连接、输入输出流、网络编程Socket等资源,JVM是不能自动的回收的,我们需要自己手动的进行资源的释放。此时的资源释放,就需要声明在finally中。
  • 4.使用try将可能出现异常代码包装起来,在执行过程中,一旦出现异常,就会生成一个对应异常类的对象,根据此对象的类型,去catch中进行匹配
  • 5.一旦try中的异常对象匹配到某一个catch时,就进入catch中进行异常的处理。一旦处理完成,就跳出当前的try-catch结构(在没写finally的情况。继续执行其后的代码
  • 6.catch中的异常类型如果没子父类关系,则谁声明在上,谁声明在下无所谓。
    catch中的异常类型如果满足子父类关系,则要求子类一定声明在父类的上面。否则,报错
  • 7.常用的异常对象处理的方式: ① String getMessage() ② printStackTrace()
  • 8.在try结构中声明的变量,再出了try结构以后,就不能再被调用
  • 9.try-catch-finally结构可以嵌套
3.2.2、代码举例

1、ArrayIndexOutOfBoundsException的处理

public static void main(String[] args) {
		String friends[] = { "lisa", "bily", "kessy" };
		try {
			for (int i = 0; i < 5; i++) {
			System.out.println(friends[i]);
		}
		} catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("index err");
		}
		System.out.println("this is the end");
}
	/*
	运行结果:
	lisa
	bily
	kessy
	index err
	this is the end
	*/

2、ArithmeticException的处理

public class ArithmeticExceptionTest {
    int x;
    public static void main(String[] args) {
        int y;
        ArithmeticExceptionTest c = new ArithmeticExceptionTest();
        try {y = 3 / c.x;
        } catch (ArithmeticException e) {
            System.out.println("divide by zero error!");
        }
        System.out.println("program ends ok!");
    }
}
	/*
	运行结果:
	divide by zero error!
	program ends ok!

	*/
3.3、异常处理方式二:“throws + 异常类型”

"throws + 异常类型"写在方法的声明处。指明此方法执行时,可能会抛出的异常类型。
一旦当方法体执行时,出现异常,仍会在异常代码处生成一个异常类的对象,此对象满足throws后异常类型时,就会被抛出。异常代码后续的代码,就不再执行!

代码举例:

public class ThrowsTest{
    public static void main(String[] args) throws InterruptedException{
        snow();
    }

    public static void snow() throws InterruptedException{
        for(int i =0;i<5;i++){
            System.out.println(i);
            Thread.sleep(1000);//睡眠1s
        }
    }
}
	 /*
	运行结果:
	0
	1
	2
	3
	4
		*/
3.4、两种方式的区别及如何选择
3.4.1、区别

try-catch-finally:真正的将异常给处理掉了。
throws的方式只是将异常抛给了方法的调用者。并没真正将异常处理掉。

3.4.2、如何选择
  • 1.如果父类中被重写的方法没throws方式处理异常,则子类重写的方法也不能使用throws,意味着如果子类重写的方法中异常,必须使用try-catch-finally方式处理。
  • 2.执行的方法a中,先后又调用了另外的几个方法,这几个方法是递进关系执行的。我们建议这几个方法使用throws的方式进行处理。而执行的方法a可以考虑使用try-catch-finally方式进行处理。
4、手动抛出异常对象
4.1、使用说明

在程序执行中,除了自动抛出异常对象的情况之外,我们还可以手动的throw一个异常类的对象。

4.2、代码举例
class Student{
	private int id;
	
	public void regist(int id) throws Exception {
		if(id > 0){
			this.id = id;
		}else{
			//手动抛出异常对象
//			throw new RuntimeException("您输入的数据非法!");
//			throw new Exception("您输入的数据非法!");
			throw new MyException("不能输入负数");
		}
	}
	
	@Override
	public String toString() {
		return "Student [id=" + id + "]";
	}
}

5、自定义异常类
5.1、如何自定义一个异常类?
  • 1.继承于现的异常结构:RuntimeException 、Exception
  • 2.提供全局常量:serialVersionUID
  • 3.提供重载的构造器
5.2、代码举例
public class MyException extends Exception{
	static final long serialVersionUID = -7034897193246939L;
	
	public MyException(){
	}
	
	public MyException(String msg){
		super(msg);
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值