day03【final、static、匿名内部类】
今日内容
java
1.关键字 final[重点]
2.关键字 static[重点] 静态关键字
3.抽象类 模板模式
第一章 final 关键字
java
final关键字概念:
含义:最终的,可以修饰类、成员变量、成员方法。
1.0 引入案例
java
package com.itheima.demo01_final;
/*
余则成
我党 情报人员
潜伏在重庆政府
*/
public class YuZeCheng {
/*
这份情报最好要做成 谁都无法修改的!!
final 最终的 不能被更改
final修饰的方法 叫做最终方法
只能被继承 不能被重写
*/
public final void qingBao(){
System.out.println("蒋介石要逃跑....");
}
}
package com.itheima.demo01_final;
/*
余则成
儿子 小余 继承 余则成
*/
public class XiaoYu extends YuZeCheng {
// 小余 在 去情报站的路上 被追杀...
// 军统----女特务 精神欺骗
// @Override
// public void qingBao(){
// System.out.println("蒋介石爱种梧桐树!");
// }
}
package com.itheima.demo01_final;
public class FinalDemo {
// 情报站
public static void main(String[] args) {
// 原本余则成要来送情报,但是被抓了
// 把情报给了他儿子 小余
// -----经过很多地方----最终要到达情报站-
XiaoYu xiaoYu = new XiaoYu();
xiaoYu.qingBao();
}
}
结论:final 修饰的方法不能被重写。
1.1 final 关键字
java
final: 中文意思 最终,不能发生更改的。
修饰方法,修饰的方法被称为最终方法,可以被继承不能被重写。
修饰类,被称为最终类,不能被继承。
修饰变量(局部,成员) 只能赋值一次,赋值之后不能值被更改。
基本 数值 引用 地址值
1.2 final 的作用介绍
final 修饰类
java/** * 被final修饰的类 称为最终类,不能被继承! */ public final class LiLianYing { } public class LiYingLian extends LiLianYing{//报错 原因是final修饰的类不能被继承 }
final 修饰方法
java被final修饰的方法称为最终方法,也可以叫做最牛逼的方法,不能被重写! public class Fu { public final void show(){} } public class Zi extends Fu{ public void show(){}//这里报错 原因时被final修饰的方法不能被重写 }
final 修饰局部变量-基本类型
java//这是一个局部位置 被final修饰只能赋值一次 final int c = 1; System.out.println(c); // c=2;//加了final 这里报错 原因是 被final修饰的变量只能被赋值一次 System.out.println(c);
final 修饰引用类型的变量
java// 创建对象 有地址0x11 // dog 的值 是 0x11 final Dog dog = new Dog(); dog.age=10;// 给0x11空间中的age赋值 dog.age = 11;//给0x11空间中的age 赋值 // 空间的age赋值了两次 // dog = new Dog();// dog的值发生改变了 变成0x22 // 总结 final如果修饰基本类型变量 数值不能变 //final修饰引用类型变量 地址值不能变
final 修饰了局部变量
java特点: 如果被修饰的变量是基本类型,数值不能变。 如果被修饰的变量是引用类型,地址值不能变。
final 修饰成员变量
java被final修饰的成员变量,也是称为常量,只能赋值一次。而且在初始化之前 必须完成赋值。
第二章 static 关键字
2.1 static 修饰成员可以被多个对象共享
java
package com.itheima.static01;
public class NBAPlayer {
String name;//姓名
static String country;//国籍
public void show(){
System.out.println(name+"的国籍是:"+country);
}
}
package com.itheima.static01;
/**
* 每new一次 都会在 堆空间 构建一个地址
*
* 变量是内存中的一小块区域。
* 现在有三个对象
* 每个对象都有 两块小区域
* player1 name 詹姆斯 country 美国
* player2 name 杜兰特 country 美国
* player3 name 林书豪 country 美国
* 运动员名字不一样申请三个空间是可以理解的
* 国籍是一样的 还申请三个 有些浪费
*
* 能不能 只申请一个空间,让这个三个对象实现共享!
* 申请到类中合适?
* java提供了一个关键 static 表示 与类相关的
* 特点
* 可以被多个对象共享!!
*
* country被static修饰
*
* 如果说 可以被多个对象共享
* player1设置了国籍之后 player2 player3 就不用设置了。
*
* player1设置国籍叫 美国 player2 player3没有设置国籍
* 但是运行之后 发现 player2 player3有国籍了。
*
*/
public class Demo {
public static void main(String[] args) {
//创建球员对象
NBAPlayer player1 = new NBAPlayer();
player1.name="詹姆斯";
player1.country="美国";
player1.show();
NBAPlayer player2 = new NBAPlayer();
player2.name="杜兰特";
// player2.country="美国";
player2.show();
NBAPlayer player3 = new NBAPlayer();
player3.name="林书豪";
//player3.country = "美国";
player3.show();
}
}
2.2 static 关键字 内存图
加入了一下代码
java
System.out.println("刚才的国籍赋值由player1赋值,所以结果都是player1赋值后的结果");
// 最近篮球没有进世界杯 所以蓝联规划 林书豪
// 派马保国 说服 他
NBAPlayer.country = "中华人民共和国";
//查看一下 player3
player3.show();
//再查看一下 player2 player1
player1.show();
player2.show();
效果:
通过内存图记住几个结论
java
1:类只加载一次。静态成员属于类,随着类的加载而加载,加载一次,优先于对象存在。
2:被static修饰的成员,不属于某个对象,在静态区域。属于类,所以静态成员可以叫做类成员。
3:静态成员可以被对象共享使用。
注意 以后调用静态内容 建议 直接使用类名调用,因为本身就是属于类。
2.3 静态修饰符的使用
java
静态可以修饰类中成员
成员变量--静态变量
格式 static 类型 变量名 ;
成员方法--静态方法
格式 就是比之前的方法多了一个 static
public static 返回值类型 方法名(..){
return ...;
}
修饰 代码块
什么是代码块 {}
static{ } 静态代码块
修饰后的成员变量成员方法怎么调用呢?
java
类名.属性名 类名.方法名(..)
举例
System.out
Math 数学类 进行数学运算的,这个类的方法都是static修饰的。
Math.ceil() 向上取整。
Arrays.toString();
只要大家发现 类名能直接调用的方法都是静态的。
java
package com.itheima.static02;
public class MyMath {
//定义了一个 静态的变量 pai
public static double pai = 3.14;
public static int sum(int a,int b){
return a+b;
}
}
java
package com.itheima.static02;
public class Demo {
public static void main(String[] args) {
//静态可以直接类名调用
System.out.println(MyMath.pai);
int sum = MyMath.sum(3, 4);
System.out.println(sum);
}
}
2.4 注意事项
在一个静态方法中能否直接调用一个非静态变量?
不能。 静态--秦始皇 非静态---现在人
静态只能调用静态!
非静态方法中能不能调用静态内容:可以
2.5 静态代码块
代码块:就是大括号括起来的内容 {}
java
if(){
}
for(){
}
**静态代码块: 代码块前面加 static **
java
static{
写代码区域
}
位置: 类中方法外!!
java
package com.itheima.static03;
public class Student {
//定义一个 静态代码块
static{
System.out.println("静态代码执行了");
}
public Student(){
System.out.println("student类的无参构造");
}
public void show(){
}
}
package com.itheima.static03;
public class Demo {
public static void main(String[] args) throws ClassNotFoundException {
//静态代码块怎么调用 能不能调用
// 无法调用
// 静态修饰成员 随着类的加载而加载
// new Student();//当这个对象出现的时候 是不是类已经加载完了
Class.forName("com.itheima.static03.Student");
// 上面一句话 就是把 com.itheima.static03.Student 加载到内存中
new Student();
new Student();
new Student();
}
}
结论:
java
a:随着字节码文件(类)的加载,而执行,只执行一次。
b:优先于对象出现,所以肯定比构造早。
作用:
在将来的工具类中,用于读取配置文件。
对于程序中只需要加载一遍的内容,可以采用静态代码块。
第三章 内部类
3.1 什么是内部类
概念:就是在一个类的内部定义一个类
java
public class A{
private String a;
public void show(){
class C{}
}
//成员内部类
class B{
}
}
B是A的内部类,A是B的外部类。
内部类分为:成员内部类和局部内部类。在成员位置的就是成员内部类,在局部位置就是局部内部类。
3.2 成员内部类 的访问特点
java
package com.itheima.innerclass01;
public class ZhiZunBao {
//成员属性
private String lover = "紫霞仙子";
//成员方法
public void tiaoya(){
System.out.println("我爱紫霞仙子");
System.out.println("我爱白晶晶");
}
//成员内部类---定义了一个心脏
class Heart{
private String wife = "白晶晶";
//内部类的 方法
public void speak(){
System.out.println("最爱的人是谁:"+lover);//内部类访问外部类的成员变量
tiaoya();//内部类访问外部类的成员方法
System.out.println("你的妻子是:"+wife);
}
}
}
java
package com.itheima.innerclass01;
public class Demo {
public static void main(String[] args) {
//直接创建 Heart对象?
// Heart heart = new Heart();内部类无法单独创建对象
//先 创建外部类对象
// ZhiZunBao zhiZunBao = new ZhiZunBao();
// ZhiZunBao.Heart heart = zhiZunBao.new Heart();
//简化形式
ZhiZunBao.Heart heart = new ZhiZunBao().new Heart();
heart.speak();
}
}
结论
java
1:内部类中可以直接访问到外部类成员。
2:想要调用内部类成员,必须先创建外部类对象再创建内部类对象。
创建格式 外部类.内部类 变量名= new 外部类().new 内部类();
3.3 内部类编译之后 会产生.class 文件
java
ZhiZunBao$Heart.class
内部类编译之后形成了.class文件。
作用:在一个类的内部创建一个类,只允许当前类用这个类,别人无法直接访问。
第三章 匿名内部类
产生的结果,也是一个.class 文件,这不过这个.class 文件没有具体的名字。
java
package com.itheima.nonameinnerclass;
public abstract class Animal {
public abstract void eat();
}
java
package com.itheima.nonameinnerclass;
import javafx.scene.AmbientLight;
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
java
package com.itheima.nonameinnerclass;
public class Demo {
public static void main(String[] args) {
//我想养一只动物
// 不能直接实例化抽象类 咋办?
/*
1: 创建一个类 继承 Animal
2:重写了 抽象方法 eat()
3: 创建Animal子类对象
*/
Animal animal = new Cat();
animal.eat();
/*
能不能不在外面创建类的基础上 完成对象的实例化?
只能使用内部类
*/
class Dog extends Animal{
public void eat(){
System.out.println("狗吃you");
}
}
Animal a2 = new Dog();
a2.eat();
// 我想要动物 是猫是狗重要吗 不重要 重写的方法才重要
//能不能再简单直接点 来一个 只突出 重写方法的 子类对象
Animal a3 = new Animal() {
@Override
public void eat() {
System.out.println("老虎吃鸡");
}
};
// 产生了 Animal的子类对象 (以匿名内部类的形式出现)
a3.eat();
}
}
作用
匿名内部类 本质 是快速的构建一个接口或者类的子类对象!
为啥叫匿名内部类,在产生这个子类对象的时候,临时的产生一个类,这个类没有名字。
格式
java
new 接口名/类名(){
把所有抽象方法都要重写。
}
效果