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
- 成员变量 直接定义在类内,在方法外。
类的使用
- 导入包: 之处需要使用的类的位置
import 包名称.类名称;
import xyz.enforcerK.demo1.Student;
对于和当前类属于同一包的情况,可以省略导入语句。创建:
格式: 类名称 对象名 = new 类名称; Studnet stu = new Student();使用:
使用成员变量: 对象名.成员变量
使用成员方法: 对象名.成员方法名(参数)PS: 使用对象类型作为方法的返回值
返回的是对象的地址
成员变量和局部变量的区别
1.定义位置不同
局部变量:在方法的内部
成员变量:在方法的外部,直接写在类当中
2.作用域不同
局部变量:只有在方法当中可以用
成员变量:整个类全部可以通用
3.默认值不同
局部变量:没有默认值,若使用,必须手动进行赋值。
成员变量:有默认值,规则和数组相同。
4.内存中位置不同
局部变量:位于栈内存
成员变量:位于堆内存
5.生命周期不同
局部变量:随着方法进栈而诞生,随着方法出栈而消失。
成员变量:随着对象创建而诞生,随着对象被垃圾回收而消失。
面向对象的封装性
封装在Java中的体现:(将细节隐藏,对外界不可见)
方法就是一种封装
关键字
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 关键字修饰
- 为每一个成员变量编写一对Getter/Setter 方法
- 编写一个无参数的构造方法
- 编写一个全参数的构造方法
这样标准的类也叫作 Java Bean
使用 Code -> Generate 或 Alt + 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); //200Day08 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 方法只有接口自己才能调用,不能被实现类或者别人使用。
实现接口注意事项
接口是没有静态代码块或者构造方法的
一个类的直接父类是唯一的,但是一个类可以同时实现多个接口。
格式: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.匿名内部类是省略了【实现类/子类名称】,但是匿名对象是省略了【对象名称】
强调:匿名内部类 ≠ 匿名对象!!!