Java 基础

Day04

IntelliJ使用小技巧

  • 输入Psvm自动生成主方法入口
  • 输入sout自动生成输出语句
  • Alt 加数字 4 打开运行输出框
  • 快捷键设置 Settings - Keymap - Default copy - Code - Completion - Basic(打开提示信息)
  • x.fori自动生成 x次for循环
  • shift + F6 修改同一变量

Intellij 常用快捷键

  • Alt+Enter 导入包,自动修正代码
  • Ctrl+Y 删除光标所在行
  • Ctrl+D 复制光标所在行的内容,插入光标位置下面
  • Ctrl+Alt+L 格式化代码 (实用)
  • Ctrl+/ 单行注释
  • Ctrl+Shift+/ 选中代码注释,多行注释,再按取消注释
  • Alt+Ins 自动生成代码,toString,get,set等方法
  • Alt+Shift+上下箭头 移动当前代码行

IntelliJ自动保存代码修改

导入Module: File -> Project Settings -> Modules -> Import…

方法的定义格式

/*方法其实就是若干语句的功能集合*/

参数 + 返回值

定义方法的完整格式:

修饰符 返回值类型 方法名称(参数类型 参数名称, ...){
方法体
return 返回值;
}

方法重载(Overload)

对于功能相似的方法,方法的名称一样,但是参数列表不一样。 调用时根据输入的参数来对应。

注意事项:方法重载与下列因素相关
1.参数个数不同
2.参数类型不同
3.参数多类型顺序不同(int double 与 double int)

注意事项:方法重载与下列因素相关
1.与参数名称无关
2.与方法返回值类型无关!错误写法,区分不开。


Day05 数组

数组初始化

1.动态初始化(指定长度):

//动态初始化元素有默认值

数据类型 [] 数组名称 = new 数据类型[数组长度]

int []arrays = new int[5];

2.静态初始化(指定内容,自动推算长度):

数据类型 [] 数组名称 = new 数据类型[] {元素1, 元素2 …};

int[] arrayA = new int[] {5, 15, 25};
String[] arrayB = new String[]{ "hello", "world"};

省略版:
数据类型 [] 数组名称 = {元素1, 元素2, …};

  int[] arrayC = {10, 20, 30};

PS:静态、动态初始化标准格式均可以拆分成两个步骤。但静态初始化省略格式不可以拆。

int [] arrayA ;
array = new int[]{5, 15, 25};

PS: 直接打印数组名称,得到的是数组对应的内存地址哈希值。

Java中的内存划分

Java的内存划分为5个部分

1.栈(Stack): 存放的都是方法中得局部变量。方法的运行一定要在栈当中运行!
    局部变量:方法的参数,或者是方法{}内部的变量
    作用域:一旦超出作用域,立刻从栈内存中消失。
2.堆(Heap):凡是new出来的东西,都在堆当中。
    堆内存里面的东西都有一个地址值:16进制
    堆内存里面的数据,都有默认值。规则...
3.方法区(Method Area): 存储 .class相关信息,包含方法的信息。
4.本地方法栈(Native Method Stack): 与操作系统相关。
5.寄存器(pc Register): 与CPU相关。

数组长度

Array.length();
数组一旦创建,程序运行期间,长度不可改变。


Day06 类、对象、封装、构造方法、

面向对象三大基本特征

封装、继承、多态

  • 包括 属性 和 行为;
  • 类是对象的模板,对象是类的实例。
  • 成员方法不能用 static 关键字修饰 public void
  • 成员变量 直接定义在类内,在方法外。

类的使用

  1. 导入包: 之处需要使用的类的位置
    import 包名称.类名称;
    import  xyz.enforcerK.demo1.Student;
对于和当前类属于同一包的情况,可以省略导入语句。
  1. 创建:

     格式:  类名称   对象名 = new  类名称;
     Studnet stu = new Student();
  2. 使用:

    使用成员变量:  对象名.成员变量
    使用成员方法:  对象名.成员方法名(参数)

PS: 使用对象类型作为方法的返回值
返回的是对象的地址

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

1.定义位置不同
局部变量:在方法的内部
成员变量:在方法的外部,直接写在类当中

2.作用域不同
局部变量:只有在方法当中可以用
成员变量:整个类全部可以通用

3.默认值不同
局部变量:没有默认值,若使用,必须手动进行赋值。
成员变量:有默认值,规则和数组相同。

4.内存中位置不同
局部变量:位于栈内存
成员变量:位于堆内存

5.生命周期不同
局部变量:随着方法进栈而诞生,随着方法出栈而消失。
成员变量:随着对象创建而诞生,随着对象被垃圾回收而消失。

面向对象的封装性

封装在Java中的体现:(将细节隐藏,对外界不可见)

  1. 方法就是一种封装

  2. 关键字 private 也是一种封装。(在本类中仍可正常访问,但是超出范围不能再直接访问,可以用 setter、 getter(boolean类型用is*)方法间接访问 )

    this 关键字

    this.* 用于重名时区分成员变量和局部变量
    通过谁调用的方法,谁就是this.

构造方法

构造方法是专门用来创建对象的方法,当我们通过关键字new来创建对象时,其实就是在调用构造方法。

public 类名称(参数类型 参数名称){
    方法体
}

注意事项:
1.构造方法的名称必须和所在的类名称完全一样,包括大小写
2.构造方法不要写返回值类型,void也不用
3.构造方法不能return返回值
4.没有编写任何构造方法,编译器会默认构造一个无任何功能的构造方法
5.一旦编写了至少一个构造方法,编译器将不会默认构造。
6.构造方法可以重载(方法名相同,参数列表不同)

public class Student{
    public Student(){
        System.out.println("构造方法执行啦!");
     }
}

定义一个标准的类

一个标准的类通常由以下四个部分组成

1.所有的成员边拉你个都要使用private 关键字修饰

  1. 为每一个成员变量编写一对Getter/Setter 方法
  2. 编写一个无参数的构造方法
  3. 编写一个全参数的构造方法

这样标准的类也叫作 Java Bean

使用 Code -> GenerateAlt + Insert 自动生成 Getter/Setter方法。

Generate 里面的 Constructor 生成 None/全选 生成 无参或全参构造方法。


Day07 Scanner类 、Random类、 ArrayList类

java.lang包下的内容不需要手动导入

Scanner类

import java.util.Scanner;

Scannner sc = new Scanner(System.in);
int num  = sc.nextInt();
String str = sc. next();

匿名对象

格式: new 类名称;
new 类名().方法() = “ “;

PS: 匿名对象只有使用一次,如果确定有一个对象只需要使用唯一的一次,就可以使用匿名对象。

匿名对象作为函数的参数和返回值

Random类

用来生成随机数

import java.util.Random;
Random r = new Random();    //留空即可
int num = r.nextInt();

Random类生成指定范围内数字

int num = r.nextInt(bound: 3); //左闭右开  生成 0, 1, 2中随机数

整体加一 生成[1, bound]

ArrayList集合

数组长度不可变,ArrayList 可变

ArrayList < E:泛型>
泛型: 装在集合内的所有元素,都是统一类型。

PS:
1.泛型只能是引用类型,不能是基本类型。
2.对于ArrayList 集合来说,直接打印得到的不是地址,是内容,若内容为空,打印的是 [];

import java.util.ArrayList;
// 从jdk1.7+开始,右侧尖括号内可不写内容,但是尖括号不可省略。
ArrayList <String> list = new ArrayList<>();
System.out.println(lsit); //[]

//向集合中添加一些数据
list.add("AA");
sout(list); //[AA]
list.add("BB");
list.add("CC");
sout(list); //[AA, BB, CC]

ArrayList常用方法

public boolean add(E e): 向集合中添加元素,参数类型和泛型一致。
public E get(int index): 从集合中获取元素,参数是索引编号,返回对应位置元素。
public E remove(int index): 从集合当中删除元素,参数是索引编号,返回值就是被删除的元素。
public int size(): 获取集合的尺寸长度,即返回值就是集合当中包含的元素个数。

PS: ArrayList 中的add 方法一定会成功,其他的集合类型不一定。

用ArrayList存储基本类型

得使用包装类

/*
基本类型    包装类(引用类型,包装类都位于java.lang 包下) 
byte         Byte
short       Short    
int         Integer
long        Long
char        Character
float       Float
double      Double
boolean     Boolean
*/

//从jdk 1.5+ 支持自动装箱、自动拆箱
自动装箱: 基本类型 -> 包装类型
自动拆箱: 包装类型 -> 基本类型

ArrayList <Integer> List = new ArrayList<>();
list.add(100);
list.add(200):
sout(list); //[100, 200]

int num = list.get(1);  //200

Day08 String类、static、 Arrays类、Math类

String 类

字符串是常量,创建后不可修改,故可共享使用。
效果上相当于char[]字符数组,但底层原理是byte[]字节数组

创建字符串的常见 3 +1 种方式

三种构造方法:
1.public String(): 创建一个空白字符串,不含任何内容
2.public String(char [] array): 根据字符数组的内容,来创建对应的字符串
3.public String(byte[] array):根据字节数组的内容,来创建对应的字符串。
一种直接创建:
String str = “Hello”;//直接””无需new

字符串的常量池

程序当中直接双引号创建的字符串就在字符串常量池中(堆内存中)。

PS:
1.对于引用类型来说,==进行的是地址值得比较。
2.双引号直接写的字符串在常量池中,new的不在常量池中。

字符串内容常见比较方法

public boolean equals(Object obj):参数可以是任何对象,只有参数是一个字符串并且内容相同才会返回true,否则返回 false;
public boolean equalsIgnoreCase(String str): //英文大小写 忽略大小写,进行内容比较。

注意事项:
1.任何对象都能用Object进行接收
2.equals方法具有对称性,即a.equals(b) 和 b.equals(a) 效果相同
3.若比较一个常量与一个变量,建议将常量写在前面(细节,否则空指针异常错误 )

字符串常用获取方法

public int length(): 获取字符串当中含有的字符个数,返回字符串长度
public string concat(String str):将当前字符串和参数字符串拼接返回新的字符串。
public char charAt(int index):获取指定索引位置的单个字符(索引从0开始)
public int indexof(String str): 查找参数字符串在本字符串当中首次出现的索引位置,若没有返回-1

字符串截取方法

public String substring(int index):截取从参数位置一直到字符串末尾,返回新字符串;
public String substring(int begin, int end):截取从begin开始,一直到end结束(左闭右开)

字符串转换相关方法

public char[] toCharArray(): 将当前字符串拆分成字符数组作为返回值;
public byte[] getBytes(): 获得当前字符串底层的字节数组;
public String replace(charSequence ldString, charSequence newString):将所有出现的老字符串替换成为新的字符串,返回替换之后的结果新字符串,备注:charSequence表示可以接受字符串类型;

字符串分割方法

public String [] split(String regx):按照参数规则,将字符串切分成为若干部分。

注意:
split方法的参数其实是一个正则表达式,若要用英文”.”进行切分,必须写”\.“(两个反斜杠)

静态static 关键字

一旦用了static 关键字,那么这样的内容不再属于对象自己,而是属于类,所以凡是本类的对象,都共享一份数据

static 修饰成员变量

一改全改,全员共享,用作计数。

static 修饰成员方法

一旦使用static 修饰成员方法,那么这就成为了静态方法。静态方法不属于对象,而属于类。

若没有static 关键字,必须首先创建对象,然后通过对象才能使用它。而对于静态方法来说,可以通过对象名进行调用,也可以直接通过类名称来调用(推荐使用)。

无论是成员变量还是成员方法,若有了static关键字,都推荐通过类名称来进行调用。(本类中的静态方法可以省略类名称)
PS:
1.静态方法不能直接访问非静态变量(因为在内存中先有静态内容,后有非静态内容)
2.静态方法中不能用this关键字,this代表当前对象

static 内存图&& 静态代码块

方法区中有一块静态区
格式:

public class 类名称{
    static{
        //静态代码块内容
    }
}

特点:
当第一次用到本类时,静态代码块执行唯一的一次。静态内容总是优先于非静态内容,所以静态代码块比构造方法先执行。

静态代码块的典型用途:
用来一次性地对静态成员变量进行赋值。

数组工具类 Arrays

java.util.Arrays是一个与数组有关的工具类,里面提供了大量静态方法,用来实现数组常见操作。

public static String toString(数组):将参数数组编程字符串(按照默认格式:[元素1,元素2,…])
public static void sort(数组):按照默认升序对数组元素进行排序

备注:
1.若是数值,sort默认按升序
2.若是字符串,按字母升序
3.若是自定义的类型,那么这个类需要comparable接口

数学工具类 Math

java.util.Math 提供大量的静态方法,完成与数学运算相关的操作。

public static double abs(double num):获取绝对值,有多种重载
public static double ceil(double num):向上取整
public statci double floor(double num):向下取整
public static long round(double num):四舍五入

Math.PI 代表近似的圆周率常量


Day09 继承、super、this、抽象类

继承主要解决的问题: 共性抽取

继承的格式

public class 父类名称{
    //...
}

public class 子类名称 extends 父类名称{
    //...
}

继承中成员变量的访问特点

当子父类中有重名变量时,则创建子类对象时,访问有两种方式:
1.直接通过子类对象访问成员变量:
等号左边(定义时)是谁,就优先用谁,没有则向上找。
2.间接通过成员方法访问成员变量:
该方法属于谁,就优先用谁,没有则向上找。

区分子类方法中重名的三种变量

局部变量: 直接写成员变量名
本类的成员变量: this.成员变量名
父类的成员变量: super.成员变量名

继承中成员方法的访问特点

若重名怎么办???
创建的对象(new的)是谁,就优先用谁,若没有则向上找。
注意:无论是成员方法还是成员变量,如果没有都是向上找父类,绝对不会向下找子类。

继承中方法的覆盖重写(override)

概念:在继承关系当中,方法名称一样,参数列表也一样。
重写(Override): 方法名称相同,参数列表 也一样。覆盖、覆写。
重载 (Overload): 方法名称一样,参数列表 不一样。
方法的覆盖重写特点: 创建的是子类对象,则优先用子类方法。

覆盖重写的注意事项:
1.必须保证父子类之间方法的名称相同,参数列表也相同。
@Override 写在方法前面,用来检测是否为有效的覆盖重写方法,(可不写)
2.子类方法的返回值类型必须 小于等于 父类方法的返回值范围。String < Object
3.子类方法的权限必须 大于等于 父类方法的权限修饰符。
public > protected > (default) > private
备注: default 不是关键字,而是什么都不写,留空。

方法的覆盖重写_应用场景

设计原则: 对于已经投入使用的类,尽量不要进行修改,推荐定义一个新的类,来重复利用其中共性内容,并且添加改动新内容。直接使用super.方法名复用代码。

继承中,父子类构造方法的访问特点

1.子类构造方法中有一个默认隐含的”super调用”, 所以一定是先调用的父类构造方法,后执行的子类构造。
2.子类构造可以通过super关键字来调用父类重载构造。
3.super的父类构造调用,必须是子类构造方法的第一个语句。且一个子类构造方法不能调用多次super构造。
总结:
子类必须调用父类构造方法,不写则默认有一个super():写了则用写的指定的super调用,super只能有一个,还必须是第一个。

super 关键字的三种用法

1.在子类的成员方法中,访问父类的成员变量。
2.在子类的成员方法中,访问父类的成员方法。
3.在子类的构造方法中,访问父类的构造方法。

this 关键字的三种用法

1.在本类的成员方法中,访问本类的成员变量(Not局部变量).
2.在本类的成员方法中,访问本类的另一个成员方法(this可省略的)。
3.在本类的构造方法中,访问本类的另一个构造方法。
(注意:
A. this调用也必须是构造方法的第一个语句,唯一一个.
B.super和this两种构造调用,不能同时使用)

java继承的三个特点

1.单继承,唯一直接父类
2.可以多级继承,父类的父类(也叫父类). java.lang.Object是所有类的祖先类
3.一个子类的直接父类是唯一的,但是一个父类可以有很多子类。

抽象的概念

图形{
    计算面积的方法//抽象方法
}
正方形、三角形、图形

动物{
    吃东西的方式//抽象方法
}
狗吃骨头、猫吃鱼

如果父类当中的方法不确定如何进行{}方法体实现,那么这应该是就是一个抽象方法

抽象方法 和 抽象类

抽象方法: 返回值类型前加上 abstract 关键字,不写方法体具体内容

抽象方法所在的类必须是抽行类才行,在class 前加上 abstract 即可。抽象类可以有普通方法。

抽象类、抽象方法的使用

1、不能直接创建new 抽象类对象
2、必须用一个子类来继承抽象父类
3、子类必须覆盖重写抽象父类当中的所有抽象方法。覆盖重写(实现):去掉抽象方法中的 abstract 关键字,加上方法体。
4、创建子类对象进行使用

注意事项:
1.抽象类不能创建对象。
2.抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
3.抽象类中,不一定含有抽象方法,但是有抽象方法的类必定是抽象类。(通常用于某些特殊的类结构设计、设计模式中的适配器模式)
4.抽象类的子类,必须重写抽象父类中所有的抽象方法。否则子类也是一个抽象类。


Day10_接口、多态

接口就是一种公共的规范标准,只要符合规范标准,就可以通用

接口的定义基本格式

/接口就是多个类的公共规范,是一种引用类型,最重要的就是其中的:抽象方法 /

基本格式:

public interface 接口名称{
    //接口内容
}

接口生成的字节码文件仍然是.class

若是Java7,那么接口中可以包含:
1.常量
2.抽象方法

若是Java8,还可以额外包含有:
3.默认方法
4.静态方法

若是Java9,还可以额外包含有:
5.私有方法
共5种

接口中抽象方法的定义与使用

//任何版本的Java 接口中都可以定义抽象方法
格式:

public abstract 返回值类型 方法名称(参数列表);

eg:
    public interface MyInterfaceAbstract{
            public abstract void methodAbs1();
            abstract void methodAbs2();
            public void methodAbs3();
            void methodAbs4();
    }

注意:
1.接口当中的抽象方法,修饰符必须是两个固定的关键字:public abstract
2.这两个关键字修饰符,可以选择性地省略。
3.方法的三要素,可以随意定义

接口使用步骤:
1.接口不能直接使用,必须有一个实现类来实现该接口。
格式:

public class 实现类名称 implements 接口名称{
        //...
}

2.接口的实现类必须覆盖重写(实现)接口中的所有抽象方法(Alt +Enter 快速插入)
实现:去掉abstract关键字,加上方法体。
3.创建实现类的对象,来进行使用

注意:
如果实现类没有覆盖重写接口中所有的抽象方法,那么这个实现类自己必须是抽象类。

接口中默认方法的定义与使用

// 从Java 8开始,接口中可以定义默认方法

格式:

public default 返回值类型 方法名称(参数列表){
    方法体
}

备注:
接口中的默认方法,可以解决接口升级问题。(接口添加方法,已有的实现类无需做修改)

默认方法会被实现类继承下去,实现类对象进行调用默认方法,如果实现类中没有,会向上在接口里找。

即:
/
1.接口的默认方法,可以通过接口实现类对象,直接调用。
2.接口的默认方法,也可以被接口实现类进行*覆盖重写

接口的静态方法定义与使用

// Java8开始

格式:

public static 返回值类型 方法名称(参数列表){
            方法体
}

注意:
不能通过接口实现类的对象来调用接口当中的静态方法。

正确用法:
通过接口名称,直接调用其中的静态方法。

格式:

接口名称.静态方法名(参数);

接口中私有方法的定义与使用

/*
问题描述:
我们需要抽取一个共有方法,用来解决两个默认方法之间重复代码的问题。
但是这个共有方法不应该让实现类使用,应是私有化的。

从java 9 开始,接口中允许定义私有方法。
1.普通私有方法,解决多个默认方法之间有重复代码问题。
格式:

private 返回值类型 方法名称(参数列表){
    方法体
}

2.静态私有方法,解决多个静态方法之间重复代码的问题
格式:

private static 返回值类型 方法名称(参数列表){
    方法体
}

*/

接口中常量的定义与使用

/*
接口当中也可以定义“成员变量”,但是必须使用public static final 三个关键字进行修饰。
从效果上看,这其实就是接口的 常量

格式:

public static final 数据类型 常量名称 = 数据值;
//一旦赋值,不可修改

注意事项:
1.接口当中的常量,可以省略 public static final, 不写也一样。
2.接口当中的常量,必须进行赋值。
3.接口中常量的名称,使用完全大写字母,用下划线进行分割。(推荐命名规则)

使用:
接口名称.常来名称;
*/

接口内容小结

在java 9+ 版本中,接口的内容可以有:

1.成员变量其实是常量,
格式:

[public] [static] [final] 数据类型 常量名称 = 数据值;

注意:
常量必须进行赋值,而且一旦赋值不能改变。
常量名称完全大写,用下划线进行分离

2.接口中最重要的就是抽象方法,格式:

[public][abstract] 返回值类型 方法名称(参数列表);

注意:实现类必须覆盖重写接口的所有抽象方法,除非实现类是抽象类。

3.从Java 8开始,接口里允许定义默认方法,格式:

[public] default 返回值类型 方法名称(参数列表){
方法体}

注意:默认方法也可以被覆盖重写

4.从Java 8开始,接口中允许定义静态方法,格式:

[public] static 返回值类型 方法名称(参数列表){方法体}

注意: 应该通过接口名称进行调用,不能通过实现类对象调用接口静态方法

5.从Java 9 开始,接口里允许定义私有方法,格式:
普通私有方法:private 返回值类型 方法名称(参数列表){方法体}
静态私有方法:private static 返回值类型 方法名称(参数列表){方法体}
注意: private 方法只有接口自己才能调用,不能被实现类或者别人使用。

实现接口注意事项

  1. 接口是没有静态代码块或者构造方法的

  2. 一个类的直接父类是唯一的,但是一个类可以同时实现多个接口。
    格式:

    public class MyInterfaceImpl implements MyInterfaceA, MyInterfaceB{

     //覆盖重写所有抽象方法

    }

3.如果实现类所实现的多个接口中,存在重复的抽象方法,那么只需要覆盖重写一次即可
4.如果实现类没有覆盖重写所有接口当中的所有抽象方法,那么实现类就必须是一个抽象类
5.如果实现类所实现的多个接口当中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖重写
6.一个类如果直接父类当中的方法和接口当中的默认方法产生了冲突,优先用父类当中的方法。

接口之间的多继承

/*
1.类与类之间是单继承的。直接父类只有一个
2.类与接口之间是多实现的,一个类可以实现多个接口
3。接口与接口之间是多继承的

注意事项:
1.多个父接口当中的抽象方法如果重复,没关系
2.多个父接口中的默认方法如果重复,那么子接口必须进行默认方法的覆盖重写(带default关键字)

*/

多态

/
代码中体现多态性,用父类引用指向子类对象。(左父右子)
*格式:

父类名称 对象名 = new 子类名称();
Fu obj = new Zi();

或者

接口名称 对象名 = new 实现类名称();

*/

多态中成员变量的使用特点

/*
访问成员变量的两种方式:
1.直接通过对象名称访问成员变量:看等号左边是谁,优先用谁,没有则向上找
2.间接通过成员方法访问成员变量,看方法属于谁,优先用谁,没有则向上找

*/

Fu obj = new Zi();
sout(obj.num);  //假设父子类均有num变量,输出父类中的num
obj.showNum();
//子类没有覆盖重写,就是父:10
//子类如果覆盖重写,就是子:20

多态中成员方法的使用特点

/*
在多态的代码中,成员方法的访问规则:
new的是谁,就优先用谁,没有则向上找。

成员方法口诀:编译看左边,运行看右边
&&成员变量:编译看左边,运行还看左边
*/

Fu obj = new Zi();  //多态

obj.method();   //父子都有,优先用子
obj.methodFu(); //子类没有,父类有,向上找到父类
obj.methodZi();
//报错

使用多态的好处

无论右边new的时候换成哪个子类对象,等号左边的调用方法都不会变化。

对象的向上转型

1.对象的向上转型,其实就是多态写法
格式: 父类名称 对象名 = new 子类名称();
eg: Animal animal = new Cat();
含义:右侧创建一个子类对象,将它当做父类来看待使用。
注意:向上转型一定是安全的.

对象的向下转型

/*
向上转型一定是安全的.
但是也有一个弊端:一旦向上转型为父类,那么就无法调用子类原本特有的内容。

解决方案: 用对象的向下转型 还原
*/

对象的向下转型,就是一个还原的动作。
格式:

子类名称 对象名 = (子类名称)父类对象;

含义:将父类对象,还原为 本来的 子类对象

注意事项:
a.必须保证对象本来创建的时候,就是猫,才能向下转型为猫。
b.如果对象创建的时候本来不是猫,向下转为猫,则会报错(这不废话吗???)
ClassCastException.

用instanceof()关键字进行类型判断

Q:如何才能知道一个父类引用的对象,本来是什么子类??
A:
格式:

对象 instanceof 类

返回一个boolean值结果,判断前面的对象能不能当做后面类型的实例


Day11 final 权限 内部类

final

final 关键字代表最终的、不可改变的

常见四种用法:
1.用来修饰一个类
2.用来修饰一个方法
3.用来修饰一个局部变量
4.用来修饰一个成员变量

final 修饰类

格式: public final class 类名{}
含义:不可被继承
注意: 其中所有成员方法都无法进行覆盖重写,因为不可被继承。

final 修饰一个方法

这个方法是最终方法,无法被覆盖重写。
格式:

修饰符 final 返回值类型 方法名称(参数列表){
    //方法体
    }

注意事项:
对于类、方法来说,abstract 与final 关键字不能同时使用,因为矛盾。

final 修饰局部变量

一旦使用 final修饰,不可被修改,只要保证唯一一次赋值即可

final int num;
num = 30;

//对于基本类型来说,不可变说的是变量当中的数据不可变
//对于引用类型来说,不可变说的是变量当中的地址值不可变(数据可变,setter方法)

final 修饰成员变量

1、由于成员变量具有默认值,所以用了final之后必须手动赋值
2、对于final的成员变量,要么使用直接赋值,要么通过构造方法赋值。(二选一)
3.必须保证类当中所有重载的构造方法,都最终会对final的成员变量进行赋值

四种权限修饰符

                public >     protected >        (default) >         private

同一个类         YES            YES                 YES             YES

同一个包         YES            YES                 YES             NO
(new *().*)

不同包子类      YES             YES                 NO              NO
(需导包)

不同包非子类    YES               NO                  NO              NO

注意:(default)并不是关键字,而是不写
助记:三角形分布(4、3、2、1)、(我自己、我邻居、我儿子、陌生人)、

内部类

内部类的概念与分类

/
一个事物的内部包含另一个事物,一个类内部包含另一个类
Eg:身体和心脏的关系,汽车和发动机
/

分类:
1.成员内部类
2.局部内部类(包含匿名内部类)

成员内部类的定义和使用

定义格式:

修饰符 class 外部类名称{
    修饰符  class 内部类名称{
        //...
    }
    //...
}

注意:内用外,随意访问,外用内,需要内部类对象

使用方式:
1.间接方式:在外部类的方法当中,使用内部类,然后main只是调用外部类的方法。
2.直接方式:公式:

类名称 对象名 = new 类名称;
【外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();】

内部类的同名变量访问

Eg:

//若出现了重名现象,格式 :     外部类名称.this.外部类成员变量名
public class Outer{
    int num = 10;       .//外部类成员变量

    public class Inner{
            int  num =20;   //内部类的成员变量
            public void methodInner(){
                int num = 30;   //内部类方法的局变量
                sout(num);  //30局部变量,就近原则
                sout(this.num); //内部类的成员变量
                sout(Outer.this.num);   //外部类的成员变量
            }
    }
}

局部内部类定义

/
如果一个类是定义在一个方法内部的,那么这就是一个局部内部类
“局部”,只有当前所属的方法才能使用它,出了这个方法就不能用了
/

定义格式:

修饰符  class 外部类名称{
    修饰符 返回值类型 外部类方法名称(参数列表){
        class 局部内部类名称{
                //...
        }
    }
}

使用方法:
在外部类方法中 将局部内部类实例化,然后调用内部类方法

小结一下类的权限修饰符:
public > protected > (default) > private

定义一个类的时候,权限修饰符规则:
1.外部类: public / (default)
2.成员内部类: 四种都可以
3.局部内部类: 什么都不能写

局部内部类的final问题

如果希望访问所在方法的局部变量,那么这个局部变量必须是 【有效final的(仅赋值一次或者用final修饰)】

匿名内部类(重要)

/*
如果接口的实现类(或者父类的子类)只需要使用唯一的一次
那么这种情况下就可以省略掉该类的定义,而改为使用【匿名内部类】

匿名内部类定义格式:

接口名称 对象名 = new 接口名称(){
    //覆盖重写接口中所有抽象方法
};
// 大括号中的是匿名内部类

*/

省掉一个单独实现类的定义

匿名内部类使用注意事项

对格式“ new 接口名称(){…}”进行解析
1.new 代表创建对象的动作
2.接口名称就是匿名内部类需要实现的哪个接口
3.{…}这才是匿名内部类的名称

另外注意:
1.匿名内部类,在创建对象时,只能使用唯一一次。
如果希望多次创建对象,而且类的内容一样的话,那么就必须使用单独定义的实现类了
2.匿名对象,在【调用方法】的时候,只能调用唯一一次。
如果希望同一个对象,调用多次方法,那么必须给对象起个名字
3.匿名内部类是省略了【实现类/子类名称】,但是匿名对象是省略了【对象名称】
强调:匿名内部类 ≠ 匿名对象!!!

类作为成员变量类型

接口作为成员变量类型

接口作为方法的参数或返回值


   转载规则


《Java 基础》 Adward 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
MySQL——DQL、约束、范式 MySQL——DQL、约束、范式
内容 一、 DQL 查询语句 1.排序查询 2.聚合函数 3.分组查询 4.分页查询 二、约束 三、多表间关系 四、范式 五、数据库备份与
2020-03-21
下一篇 
数据库粗略回顾(三) 数据库粗略回顾(三)
五、修改数据关系数据库的基本操作就是增删改查,即CRUD:Create、Retrieve、Update、Delete。其中,对于查询,我们已经详细讲述了SELECT语句的详细用法。 而对于增、删、改,对应的SQL语句分别是: INSERT
2020-03-03
  目录