day02【final、static、权限修饰符、代码块、接口】
今日内容
- final关键字
- 修饰类
- 修饰方法
- 修饰变量
- static—>必须掌握
- 修饰成员变量
- 修饰成员方法
- 修饰代码块
- 权限修饰符
- 分类
- 权限
- 代码块(格式,位置,执行,使用场景)
- 构造代码块
- 静态代码块
- 局部代码块
- 接口—>必须掌握
- 定义接口
- 实现接口
- 接口中成员访问特点
第一章 final关键字
1.1 final关键字的概述和使用
final关键字的概述
- 概述: final是一个关键字,表示最终,不可变的意思,可以用来修饰类,修饰方法,修饰变量
- 特点:
- 被final修饰的类不能被继承
- 被final修饰的方法不能被重写
- 被final修饰的变量不能重复赋值,只能赋值一次
final关键字的使用
修饰类
-
格式:
修饰符 final class 类名{} // 被final修饰的类不能被继承
-
jdk中被final修饰的类: String类,Scanner类,Math类…
-
案例:
final class Fu{} /*class Zi extends Fu{// 编译报错 }*/ public class Test { public static void main(String[] args) { Fu f = new Fu(); } }
修饰方法
-
格式: 修饰符 final 返回值类型 方法名(形参列名){ 方法体 }
-
特点: 被final修饰的方法不能被重写
-
案例:
class Fu{
public final void show(){
System.out.println(“Fu show…”);
}
}class Zi extends Fu{ // 编译报错,因为final修饰的方法不能被重写 /*@Override public void show() { }*/ } public class Test { public static void main(String[] args) { Zi zi = new Zi(); zi.show(); } }
修饰变量
-
格式:
- 方式一: final 数据类型 变量名 = 值;
- 方法二: final 数据类型 变量名; 变量名 = 值;
-
特点:
- 被final修饰的变量只能赋值一次,不能重复赋值
- 一般开发中,被final修饰的变量,变量名都是全部字母大写( fianl修饰的变量其实就是自定义的常量)
-
final修饰局部变量案例:
public class Test {
public static void main(String[] args) {
// 方式一:
final int A = 10;
// A = 20; // 编译报错,因为final修饰的变量只能赋值一次// 方式二: final int B; B = 100; // B = 200;// 编译报错,因为final修饰的变量只能赋值一次 } }
-
final修饰成员变量案例:
class Person{
public final int NUM = 10;// 开发中常见
}class Student{ public final int NUM; public Student(){ NUM = 20; } public Student(String name){ NUM = 30; // 对象和对象之间的关系是相互独立的 } } public class Test { public static void main(String[] args) { Student stu = new Student(); System.out.println(stu.NUM);// 20 // stu.NUM = 30;// 编译报错,因为final修饰的变量只能赋值一次 Student stu2 = new Student("张三"); System.out.println(stu2.NUM);// 30 // stu2.NUM = 40;// 编译报错,因为final修饰的变量只能赋值一次 } }
第二章 static关键字
1.static关键字
1.1 概述
- 概念: static是一个关键字,表示静态的意思,可以用来修饰成员变量,成员方法,代码块
1.2 修饰成员变量
格式:
- 格式: 修饰符 static 数据类型 变量名;
特点:
- 被static修饰的成员变量叫做静态成员变量\类变量
- 被static修饰的成员变量会被该类的所有对象共享
- 如果该类的某个对象修改了静态成员变量的值,那么该类的所有对象使用的都是修改后的值
访问方式:
- 对象名.静态成员变量名
- 类名.静态成员变量名 ------->推荐\掌握
案例:
public class Chinese {
// 非静态成员变量
String name;
// 静态成员变量
static String country;
public Chinese(String name,String country) {
this.name = name;
this.country = country;
}
public Chinese() {
}
}
public class Test {
public static void main(String[] args) {
/*
- 格式: 修饰符 static 数据类型 变量名;
特点:
- 被static修饰的成员变量叫做静态成员变量\类变量
- 被static修饰的成员变量会被该类的所有对象共享
- 如果该类的某个对象修改了静态成员变量的值,那么该类的所有对象使用的都是修改后的值
访问方式:
- 对象名.静态成员变量名
- 类名.静态成员变量名 ------->推荐\掌握
*/
// 创建Chinese对象
Chinese c1 = new Chinese("张三","中华人民共和国");
// 姓名:张三,国籍:中华人民共和国
System.out.println("姓名:"+c1.name+",国籍:"+c1.country);
System.out.println("=======");
// 创建Chinese对象
Chinese c2 = new Chinese();
// 姓名:null,国籍:中华人民共和国
System.out.println("姓名:"+c2.name+",国籍:"+c2.country);
System.out.println("=======");
// 如果该类的某个对象修改了静态成员变量的值,那么该类的所有对象使用的都是修改后的值
c2.country = "中国";
// 姓名:张三,国籍:中国
System.out.println("姓名:"+c1.name+",国籍:"+c1.country);
// 姓名:null,国籍:中国
System.out.println("姓名:"+c2.name+",国籍:"+c2.country);
System.out.println("=======");
System.out.println(Chinese.country);// 中国
}
}
1.3 修饰成员方法
格式:
修饰符 static 返回值类型 方法名(形参列名){
方法体
}
特点:
- 被static修饰的成员方法叫做静态方法
访问方式:
- 对象名.方法名(实参);
- 类名.方法名(实参);------->推荐\掌握
案例:
public class Chinese {
public void show1(){
System.out.println("非静态方法 show1...");
}
public static void show2(){
System.out.println("静态方法 show2...");
}
}
public class Test {
public static void main(String[] args) {
/*
修饰成员方法
*/
Chinese.show2();// 推荐
System.out.println("======");
Chinese c = new Chinese();
c.show1();
c.show2();
}
}
1.4 静态方法调用的注意事项
-
静态方法中不能出现this关键字
-
静态方法中只能直接访问静态成员变量和静态成员方法
-
静态方法中不能直接访问非静态成员变量和非静态成员方法
-
非静态方法中可以直接访问一切成员变量和成员方法
public class Chinese {
// 非静态成员变量
String name;
// 静态成员变量
static String country;// 静态成员方法 public static void method1(){ // 静态方法中不能出现this关键字 // System.out.println(this.name); // 静态方法中不能直接访问非静态成员变量和非静态成员方法 // System.out.println(name); // show1(); // 静态方法中只能直接访问静态成员变量和静态成员方法 System.out.println(country); method2(); } public static void method2(){ System.out.println("静态成员方法method2..."); } // 非静态方法 public void show1(){ System.out.println("非静态成员方法show1..."); } public void show2(){ // 访问非静态成员 System.out.println(name); show1(); // 访问静态成员 System.out.println(country); method2(); } } public class Test { public static void main(String[] args) { /* 静态方法中不能出现this关键字 静态方法中只能直接访问静态成员变量和静态成员方法 静态方法中不能直接访问非静态成员变量和非静态成员方法 非静态方法中可以直接访问一切成员变量和成员方法 */ Chinese.method1(); System.out.println("====="); // Chinese c = new Chinese(); // c.show2(); new Chinese().show2(); } }
1.5 修饰代码块
格式:
static {
}
// 静态代码块
位置:
- 类中方法外(类的成员位置)
执行:
- 随着类的加载而执行,并且只执行一次
- 类的加载: 第一次使用该类的时候,就会加载,并且只加载一次
使用场景:
- 如果程序中某段代码只需要执行一次,就可以把该段代码放入静态代码块中
- eg: 加载驱动,读取配置文件中的数据…
案例
public class Chinese {
static {
System.out.println("Chinese 静态代码块...");
}
public Chinese(){
System.out.println("Chinese 空参构造...");
}
}
*/
public class Test {
public static void main(String[] args) {
System.out.println("开始");
Chinese c1 = new Chinese();
Chinese c2 = new Chinese();
System.out.println("结束");
}
}
1.6 以后开发中static的应用
概述
以后的项目中,通常会需要一些“全局变量”或者“全局的工具方法”,这些全局变量和方法,可以单独定义在一个类中,并声明为static(静态)的,可以很方便的通过类名访问
例如
public class MathUtils {
// ctrl+shift+u
public static final double PI = 3.14;
public static final int WIDTH = 600;
public static final int HEIGHT = 800;
public static int getMax(int[] arr){
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max){
max = arr[i];
}
}
return max;
}
}
public class Test {
public static void main(String[] args) {
// 需求:在一个工具类中,定义一个π变量和获取int数组最大值方法
System.out.println(MathUtils.PI);// 3.14
int[] arr = {1,23,45,23,434,54,32,65,76};
System.out.println(MathUtils.getMax(arr));// 434
}
}
第三章 权限修饰符
1.1 权限修饰符
概述
- 在java中提供了4个权限修饰符,使用不同的权限修饰符修饰,被修饰的内容就具有不同的访问权限
- 分类:
- public : 公共的
- protected: 受保护的
- (空的): 默认
- private: 私有的
不同权限的访问能力
同一个类 同一个包 不同包的父子类 不同包的无关类
public √ √ √ √
protected √ √ √ ×
默认 √ √ × ×
private √ × × ×
-
案例:
同一个包:
package com.itheima.demo1_权限修饰符;/** * @Author:pengzhilin * @Date: 2021/3/20 9:10 */ public class Person { public void method1(){} protected void method2(){} void method3(){} private void method4(){} public void show(){ // 同一个类 method1(); method2(); method3(); method4(); } } package com.itheima.demo1_权限修饰符; /** * @Author:pengzhilin * @Date: 2021/3/20 9:10 */ public class Test { public static void main(String[] args) { Person p = new Person(); // 同一个包 p.method1(); p.method2(); p.method3(); // p.method4();// 编译报错 } } 不同包: package com.itheima.demo2_权限修饰符; import com.itheima.demo1_权限修饰符.Person; /** * @Author:pengzhilin * @Date: 2021/3/20 9:13 */ public class Student extends Person { // 不同包的子类 public void show(){ method1(); method2(); // method3();// 编译报错 // method4();// 编译报错 } } */ public class Test { public static void main(String[] args) { Person p = new Person(); // 不同包的无关类 p.method1(); // p.method2();// 编译报错 // p.method3();// 编译报错 // p.method4();// 编译报错 } }
开发中的使用
- 定义类一般使用public
- 定义成员方法一般使用public
- 定义成员变量一般使用private
- 定义构造方法一般使用public
第四章 代码块
2.1 构造代码块
-
格式: {}
-
位置: 类中,方法外
-
执行: 每次调用构造方法时,都会执行一次,优先于构造方法执行
-
使用场景: 统计创建了多少个对象
-
案例:
public class Person {
// 构造代码块
{
System.out.println(“Person类的构造代码块”);
}public Person(){ System.out.println("Person类的空参构造方法"); } }
2.2 静态代码块
- 格式: static {}
- 位置: 类中,方法外
- 执行: 随着类的加载而执行,并且只执行一次
- 使用场景: 加载驱动,或者放只需要执行一次的代码
- 案例:
public class Person {
static {
System.out.println(“Person类的静态代码块”);
}
}
2.3 局部代码块
- 格式: {}
- 位置: 方法中
- 执行: 调用方法时,执行到了局部代码块的位置才执行
- 使用场景: 节省内存空间,意义不大
- 案例:
public class Test {
public static void main(String[] args) {
int num1 = 10;
System.out.println(num1);
System.out.println(“开始”);
// 局部代码块
{
int num2 = 20;
System.out.println(“局部代码块,num2:” + num2);
}
// System.out.println(num2);// 编译报错,因为超过了num2的作用域
System.out.println(“结束”);
}
}
2.4 注意:
-
静态代码块优先于构造代码块执行
-
构造代码块优先于构造方法执行
public class Person {
// 静态代码块
static {
System.out.println(“Person类的静态代码块”);
}// 构造代码块 { System.out.println("Person类的构造代码块"); } public Person(){ System.out.println("Person类的空参构造方法"); } }
第五章 接口
3.1 概述
- 概述: 接口是Java语言中的一种引用类型,主要是用来存储方法的
- 接口中的成员:
- 常量(jdk7及其以前)
- 抽象方法(jdk7及其以前)
- 默认方法和静态方法(JDK 8)
- 私有方法(jdk9)
- 定义接口需要使用interface关键字—>编译后也会产生class文件
- 接口没有构造方法,也不能创建对象,所以一般都是供类实现的(implements),类似继承
- 实现接口的类叫做实现类,实现类如果是普通类必须重写接口中所有的抽象方法,否则实现类是一个抽象类
3.2 定义格式
格式
public interface 接口名称 {
// 常量
// 抽象方法
// 默认方法
// 静态方法
// 私有方法
}
案例
public interface IA {
// 常量:使用public static final修饰,而这三个修饰符可以省略不写
public static final int NUM = 10;
// 抽象方法:使用public abstract修饰,而这两个修饰符可以省略不写
public abstract void method1();
// 默认方法: 使用public default修饰,public可以省略不写,default不可以省略
public default void method2(){
System.out.println("IA 默认方法method2");
}
// 静态方法:使用public static修饰,public可以省略不写,static不可以省略
public static void method3(){
System.out.println("IA 静态方法method3");
}
// 私有方法: 使用private修饰,private不可以省略
// private void method4(){}
// private static void method5(){}
}
3.3 实现接口
实现概述
- 概述:类与接口的关系为实现关系,即类实现接口,该类可以称为接口的实现类,也可以称为接口的子类。
实现格式:
-
单实现
public class 实现类名 implements 接口名{} -
多实现
public class 实现类名 implements 接口名1,接口名2,接口名3,…{} -
先继承后实现
public class 实现类名 extends 父类名 implements 接口名1,接口名2,接口名3,…{}
案例演示:
interface IA{}
interface IB{}
interface IC{}
class Fu{}
// 单实现
class Imp1 implements IA{}
// 多实现
class Imp2 implements IA,IB,IC{}
// 先继承后实现
class Zi extends Fu implements IA,IB,IC{}
3.4 接口中成员的访问特点
-
接口中成员的访问特点: 接口中常量: 主要供接口名直接访问,也可以被实现类继承 接口中抽象方法:就是供实现类重写的 接口中默认方法:可以供实现类对象直接调用,或者在实现类中重写 接口中静态方法:只供接口名直接访问,不可以被实现类继承 接口中私有方法:只能在接口内部方法中调用,不可以被实现类继承
-
案例:
public interface IA {
// 常量: 使用public static final修饰
public static final int NUM = 10;// 抽象方法: 使用public abstract修饰 public abstract void method1(); // 默认方法: 使用public default修饰 public default void method2(){ System.out.println("IA接口的默认方法method2"); // method4(); } // 静态方法: 使用public static修饰 public static void method3(){ System.out.println("IA接口的静态方法method3"); } // 私有方法: 使用private修饰 //private void method4(){} //private static void method5(){} } public class Imp implements IA { @Override public void method1() { System.out.println("实现类重写接口中的抽象方法method1"); } @Override public void method2() { System.out.println("实现类重写接口中的默认方法method2"); } } public class Test { public static void main(String[] args) { /* 接口中成员的访问特点: 接口中常量: 主要供接口名直接访问,也可以被实现类继承 接口中抽象方法:就是供实现类重写的 接口中默认方法:可以供实现类对象直接调用,或者在实现类中重写 接口中静态方法:只供接口名直接访问,不可以被实现类继承 接口中私有方法:只能在接口内部方法中调用,不可以被实现类继承 */ // 访问接口中的常量 System.out.println(IA.NUM);// 10 System.out.println(Imp.NUM);// 10 // 访问接口中的抽象方法 Imp imp = new Imp(); imp.method1(); // 访问接口中的默认方法 imp.method2(); // 访问接口中的静态方法 IA.method3(); } }
3.5 多实现时的几种冲突情况
公有静态常量的冲突
interface IA{
public static final int A = 10;
public static final int B = 10;
}
interface IB{
public static final int A = 20;
}
class Imp implements IA,IB{
}
public class Test {
public static void main(String[] args) {
// 多实现常量冲突: 多个接口中同名的常量不能被实现类继承
// System.out.println(Imp.A);// 编译报错
System.out.println(Imp.B);// 10
}
}
公有抽象方法的冲突
interface IA{
public abstract void show();
}
interface IB{
public abstract void show();
}
class Imp implements IA,IB{
@Override
public void show() {
System.out.println("重写一次show方法...");
}
}
public class Test {
public static void main(String[] args) {
// 抽象方法冲突: 必须重写一次抽象方法
}
}
公有默认方法的冲突
interface IA{
public default void show(){
System.out.println("IA show...");
}
}
interface IB{
public default void show(){
System.out.println("IB show...");
}
}
class Imp implements IA,IB{
@Override
public void show() {
System.out.println("重写一次show方法");
}
}
public class Test {
public static void main(String[] args) {
// 默认方法的冲突: 必须重写一次默认方法
Imp imp = new Imp();
imp.show();
}
}
公有静态方法的冲突
interface IA{
public static void show(){
System.out.println("IA show...");
}
}
interface IB{
public static void show(){
System.out.println("IB show...");
}
}
class Imp implements IA,IB{
}
public class Test {
public static void main(String[] args) {
// 静态方法的冲突: 不存在冲突,因为静态方法不能被实现类继承
}
}
私有方法的冲突
- 不存在冲突,因为私有方法不能被实现类继承
3.6 接口和接口的关系
接口与接口之间的关系
-
接口和接口之间是继承关系
-
单继承
public interface A{}
public interface B extends A{} -
多继承
public interface A{}
public interface B{}
public interface C extends A,B{} -
多层继承
public interface A{}
public interface B extends A{}
public interface C extends B{}
接口继承接口的冲突情况
公有静态常量的冲突 `
interface IA{
public static final int B = 10;
public static final int C = 10;
}
interface IB{
public static final int B = 20;
}
interface IC extends IA,IB{
}
public class Test {
public static void main(String[] args) {
// 常量冲突: 多个接口中同名的常量不会被子接口继承,不同名的会被继承
// System.out.println(IC.B);// 编译报错
System.out.println(IC.C);// 10
}
}
公有抽象方法冲突
interface IA{
public abstract void show();
}
interface IB{
public abstract void show();
}
interface IC extends IA,IB{
}
class Imp implements IC{
@Override
public void show() {
System.out.println("重写一次即可");
}
}
public class Test {
// 抽象方法冲突: 多个父接口中有相同的抽象方法,子接口只会继承一个抽象方法
}
公有默认方法的冲突
interface IA{
public default void show(){
System.out.println("IA show...");
}
}
interface IB{
public default void show(){
System.out.println("IB show...");
}
}
interface IC extends IA,IB{
@Override
default void show() {
System.out.println("必须重写一次同名的默认方法");
}
}
public class Test {
// 默认方法冲突: 多个父接口中有相同的默认方法,子接口必须重写默认方法(default)
public static void main(String[] args) {
}
}
公有静态方法和私有方法
-
不存在冲突,因为静态方法和私有方法不会被子接口继承
interface IA{
public static void show(){
System.out.println(“IA show…”);
}
}
interface IB{
public static void show(){
System.out.println(“IB show…”);
}
}interface IC extends IA,IB{ } public class Test { public static void main(String[] args) { // 静态方法冲突: 子接口无法继承父接口的静态方法,所以不存在冲突 } }
3.7 继承的同时又实现存在的问题
父类和接口的公有静态常量的冲突
interface IA{
public static final int A = 10;
}
class Fu{
public static final int A = 20;
}
class Imp extends Fu implements IA{
}
public class Test {
public static void main(String[] args) {
// 常量冲突: 实现类不会继承有冲突的常量
// System.out.println(Imp.A);// 编译报错
}
}
父类和接口的抽象方法冲突
interface IA {
public abstract void show();
}
abstract class Fu {
public abstract void show();
}
class Imp extends Fu implements IA {
@Override
public void show() {
System.out.println("必须重写一次");
}
}
public class Test {
// 抽象方法冲突: 实现类必须重写一次有冲突的抽象方法
}
父类和接口的公有默认方法的冲突
interface IA {
public default void show(){
System.out.println("IA show");
}
}
abstract class Fu {
public void show(){
System.out.println("Fu show");
}
}
class Imp extends Fu implements IA {
}
public class Test {
public static void main(String[] args) {
// 默认方法的冲突: 优先访问父类的
Imp imp = new Imp();
imp.show();// Fu show
}
}
父类和接口的公有静态方法
interface IA {
public static void show(){
System.out.println("IA show");
}
}
abstract class Fu {
public static void show(){
System.out.println("Fu show");
}
}
class Imp extends Fu implements IA {
}
public class Test {
public static void main(String[] args) {
// 静态方法的冲突: 不存在冲突,使用的是父类的静态方法
Imp.show();// Fu show
}
}
父类和接口的私有方法
- 不存在冲突
3.8 抽象类和接口的练习
需求:
通过实例进行分析和代码演示抽象类和接口的用法。
1、举例:
犬: 抽象父类
行为:吼叫;吃饭;
缉毒犬:继承犬类,实现缉毒的接口
行为:吼叫;吃饭;缉毒;
缉毒的接口: 缉毒的功能
抽象类: 如果同一群事物共同的功能就定义在抽象类中
接口: 如果不同类型的事物共同拥有的功能就定义在接口中,让这些事物的类实现该接口
实现:
-
Dog
// 抽象父类
public abstract class Dog {
// 吼叫
public abstract void houJiao();// 吃饭 public abstract void eat(); }
-
JiDu
public interface JiDu {
public abstract void jiDu();
} -
JiDuDog
public class JiDuDog extends Dog implements JiDu{
@Override
public void houJiao() {
System.out.println(“汪汪汪…”);
}@Override public void eat() { System.out.println("吃狗粮..."); } @Override public void jiDu() { System.out.println("使用鼻子闻来缉毒..."); } }
-
Test
public class Test {
public static void main(String[] args) {
// 创建缉毒犬对象
JiDuDog jd = new JiDuDog();
jd.eat();
jd.jiDu();
jd.houJiao();
}
}
总结
必须练习:
0.fianl关键字修饰类,方法,变量--->必须掌握
1.static修饰成员变量的格式和使用--->必须掌握
2.static修饰成员方法的格式和使用--->必须掌握
3.static修饰代码块的格式和使用 --->必须掌握
4.定义接口,实现接口,接口中成员的访问特点--->必须掌握
5.理解各个权限修饰符的权限
- 描述final修饰的类的特点
不能被继承
- 描述final修饰的方法的特点
不能被重写
- 描述final修饰的变量的特点
只能赋值一次,不能重复赋值
- 能够使用static修饰成员变量
格式: static 数据类型 变量名
使用: 类名.变量名;
特点: 被该类的所有对象共享
- 能够使用static修饰成员方法
格式: 方法的返回值类型前面加static
使用: 类名.方法名(实参);
- 能够使用static修饰静态代码块
格式: static{}
位置: 类中方法外
执行: 随着类的加载而执行,并且只执行一次,优先于构造方法执行
- 能够说出每种权限修饰符的作用
同一个类 同一个包 不同包的父子类 不同包的无关类
public √ √ √ √
protected √ √ √ ×
默认 √ √ × ×
private √ × × ×
- 能够写出接口的定义格式
格式: public interface 接口名{ 接口的成员 }
- 能够写出接口的实现格式
格式: 单实现,多实现,先继承后实现
public class 实现类名 implements 接口名{}
public class 实现类名 implements 接口名1,接口名,...{}
public class 实现类名 extends 父类 implements 接口名1,接口名,...{}
- 能够说出接口中的成员特点
接口中的常量: 主要供接口名直接访问,当然也可以被实现类继承
接口中的抽象方法: 就是供实现类重写的
接口中的默认方法: 可以供实现类对象直接继承调用,也可以供实现类重写
接口中的静态方法: 只能供接口名直接访问,不能被实现类继承
接口中的私有方法: 只能在接口内部直接访问,不能被实现类继承
- 能够理解接口和接口之间的关系
接口和接口之间是继承关系,有单继承,多继承,多层继承
子接口可以继承父接口的常量,抽象方法,默认方法,无法继承静态方法和私有方法