第六天:
1、static final常量: ---------- 应用率高
1)必须声明同时初始化
2)通过 类名点 来访问,不能被改变
3)建议:常量名所有字母都大写,多个单词用_分隔
4)编译器在编译时 会将常量直接替换为具体的值,效率高
5)何时用:数据永远不变,并且经常使用
package oo.day06;
//static final常量的演示
public class StaticFinalDemo {
public static void main(String[] args) {
System.out.println(Aoo.PI); //常常通过类名点来访问
//Aoo.PI = 3.1415926; //编译错误,常量不能被改变
}
}
class Aoo{ //加static关键字的都是公开的
public static final double PI = 3.14159; //常量是让别人用的,是公开的
// public static final 一个公开的常量
//public static final int NUM; //编译错误,常量必须声明同时初始化
}
-------------------------------------------------------------
public class StaticFinalDemo {
public static void main(String[] args) {
//1)加载Boo.class到方法区中(字节码文件)
//2)静态变量num也一并存储在方法区中
//3)到方法区中 获取num的值 并输出
System.out.println(Boo.num);
//编译器在编译时 会 将常量直接替换为具体的值,效率高(因为上面是3步)
//相当于System.out.println(5);
System.out.println(Boo.COUNT);
//常量是编译期直接 将常量直接替换为具体的值,还没到运行期
//分配内存 是运行期干的事,因为内存是Jvm管理的;
// java编译运行过程:---------常见面试题
// 1)编译期: .java源文件,经过编译,生成 .class字节码文件
// 2)运行期:JVM加载 .class并运行 .class(0和1)
}
}
class Boo{
public static int num = 5; //静态变量
public static final int COUNT = 5; //常量
}
设计规则:
1)将所有派生类所共有的属性和行为,抽到超类中------------抽共性
2)派生类的行为都一样,设计为 普通方法
派生类的行为不一样,设计为 抽象方法
3)将部分派生类所共有的属性和行为,抽到接口中
接口是对继承的单根性的扩展--------------实现多继承
继承: 超类是亲爹,只能有一个
接口: 接口是干爹,可以有多个
2、抽象方法:
1)由abstract修饰
2)只有方法的定义,没有具体的实现( 连{ }都没有 )
eg:public abstract void step(); //抽象方法
Java规定,包含抽象方法的类必须是抽象类
/**飞行物*/ //Java规定,包含抽象方法的类必须是抽象类
② public abstract class FlyingObject(){ //所以 这里也要加 abstract
protected int width; //宽
protected int height; //高
}
① public abstract void step(); //抽象方法
3、抽象类:
1)由abstract修饰
2)包含抽象方法的类必须是抽象类
3)抽象类不能被实例化(不能new对象)
(即:抽象类单独存在是没有意义的,一个类的意义就是为了创建对象)
4)所以,抽象类是需要 被继承的, (抽象类都要有子类)
抽象类的派生类(子类):
4.1)重写所有抽象方法---------变不完整为完整 (不能new对象就不完整)
4.2)也声明为抽象类-----------一般不这么做
5)抽象类的意义:
5.1)封装共有的属性和行为-----------代码复用(也是父类的意义)
5.2)给所有派生类提供统一的类型--------向上造型
5.3)可以包含抽象方法,为所有派生类提供统一的入口(造型后能点出来)
派生类的具体实现不同,但入口是一致的
eg:
3)的举例:
① FlyingObject o; //正确
//FlyingObject是抽象类(看上面代码),抽象类 总归是个类,类是数据类型,
//只要是数据类型就能声明变量(是类就能声明变量,声明的是引用类型变量,简称,引用),
//所以正确
② new FlyingObject(); //编译错误 抽象类不能new对象 (在创建FlyingObject对象)
③ FlyingObject[] fs; //正确 只要是数据类型就能声明数组
④ new FlyingObject[3]; //正确 因为是 在创建FlyingObject数组对象
FlyingObject[] fs = new FlyingObject[3]; //正确 在创建FlyingObject数组对象
4)的举例:
abstract class FlyingObject{//FlyingObject是抽象类,不能new对象,它单独存在没有意义
int width,height,x,y
abstract void step(); //抽象方法(派生类的行为不一样,设计为 抽象方法)
}
//子类继承了父类 宽 高 x y和一个抽象方法(复用)
class Airplane extends FlyingObject{ //需要 子类(派生类)继承 抽象类
void step(){ //重写抽象方法----变不完整为完整 (重写不加abstract)
y向下
}
}
class Bee extends FlyingObject{ //需要 子类(派生类)继承 抽象类
void step(){
x左右、y向下
}
}
//方法重写:发生在父子类中,方法名称相同,参数列表相同,方法体不同
类和类----------------继承
接口和接口------------继承
类和接口--------------实现
1、
问:4)举例的 超类的 抽象方法step() 有意义吗? 超类的抽象方法可不可以不写?因为派生类总归得重写,抽象方法并达不到复用的效果?
答:有意义,不可以不写,意义在于向上造型后(在World类中),通过超类FlyingObject 的引用enemies 可以点出step()方法来, 但是派生类都重写step()了,所以最终执行的还是派生类重写之后的,意义仅在于能点出来step()方法
向上造型: 超类型的引用指向派生类的对象
Animal o = new Tiger();
4.15日下午, 158:28改成下面这样了:
2、
问:既然意义仅在于能点出来,那为何不设计为普通方法呢? 做成普通方法,在向上造型时,也能点出来,那为什么不做成普通方法?
答:普通方法意味着可以重写也可以不重写,但抽象方法是必须被重写的, 设计为抽象方法可以 强制派生类 必须重写
第七天:
1、成员内部类: 应用率低--------了解即可
1)类中套类,外面的称为外部类,里面的称为内部类
2)内部类通常只服务于外部类,对外不具备可见性
3)内部类对象只能在外部类中创建
4)内部类中可以直接访问外部类的成员(包括私有的)
内部类中有个隐式的引用指向了创建它的外部类对象
语法:外部类名.this ---------------重点记住(API会用到这个东西)
1)的举例:
class Aoo{ //外部类
class Boo{ //内部类(成员内部类,因为 是外部类的成员)
}
}
2)的举例:
public static void main(String[] args) {
Aoo o = new Aoo(); //正确
Boo o = new Boo(); //所以 编译错误(因为内部类Boo 从外面看不到)
//所以从外面new Boo是不行的
}
class Aoo{ //外部类
class Boo{ //内部类 Boo只让Aoo用,外面其他类看不到Boo
}
}
3)的举例:
class Aoo{ //外部类
void test(){
Boo o = new Boo(); //正确(从Aoo里面new Boo对象)
}
class Boo{ //内部类
}
}
4)的举例:
class Aoo{ //外部类
private int a;
void test(){
Boo o = new Boo(); //正确
}
class Boo{ //内部类
void show(){
System.out.println(a);
System.out.println(Aoo.this.a); //上面这一句写全了,是这样的
}
}
}
2、匿名内部类: 应用率高(API线程那里)-----------大大简化代码的操作(便于数据的访问)
1)若想创建一个类(派生类)的对象,并且对象只被创建一次,
此时该类不必命名,称为匿名内部类
2)匿名内部类中不能修改外面变量的值,因为在匿名内部类中默认变量为final的
--------------重点记住(API线程 会用到)
package oo.day07;
//匿名内部类的演示
public class NstInnerClassDemo {
public static void main(String[] args) {
Aoo o1 = new Aoo(); //报错,因为抽象类Aoo不能new对象
//1) 创建了Aoo的一个派生类,但是没有名字
//2) 为Aoo的 派生类创建了 一个 对象,名为o1
//3) 大括号中的为派生类的类体
Aoo o1 = new Aoo(){ //加个大括号{}就不报错了
};
//1)创建了Aoo的 另一个派生类,但是没有名字
//2)为该派生类创建了一个对象,名为o2
//3)大括号中的为派生类的类体
Aoo o2 = new Aoo(){ //如果再new个对象,就是重新又干了3件事,
//就与上面 是两个完全不同的派生类
};
//o1是派生类1号的对象,o2是派生类2号的对象
abstract class Aoo{
}
-------------------------------------------------
类似于下面这样,只不过上面是 系统帮我们做了:
public static void main(String[] args) {
Coo o1 = new Coo(); //2) 为Aoo的 派生类Coo创建了一个对象,名为o1
Coo o2 = new Coo();
Coo o3 = new Coo();
Coo o4 = new Coo(); //自己创建的派生类可以new多个对象
//但上面的 匿名内部类只能new一个
abstract class Aoo{
}
class Coo extends Aoo{ //1) 创建了Aoo的一个派生类,有名字 Coo
}
-------------------------------------------------------
public static void main(String[] args) {
int num = 5;
//1)创建了Boo的一个派生类,没有名字
//2)为该派生类创建了一个对象,名为o3
//3)大括号中的为派生类的类体
Boo o3 = new Boo(){
void show(){ //重写show()方法
System.out.println("showshow");
//num = 55; //编译错误,在匿名内部类中默认num为final的
}
};
o3.show();//抽象方法被调用时,用new出来的对象,对象.
} //show()是派生类 类体中的,想访问派生类 类体里的东西,
//得通过派生类的对象o3访问
abstract class Boo{
abstract void show(); //抽象方法
}
--------------------------------------------------------
类似于:3)的举例 eg:
class Coo extends Boo{ //Boo的派生类Coo,{}是Coo的类体
void show(){ //重写show()方法
System.out.println("showshow");
}
}
abstract class Boo{
abstract void show();//抽象方法
} //有抽象方法的类必须是抽象类
//抽象类父类Boo有抽象方法,抽象类的派生类(子类)必须要重写抽象方法
常见面试题:
问:内部类有独立的.class字节码文件吗?
答:有
做功能的步骤:
1)先写行为/方法:
1.1)若为某对象所特有的行为,则将方法设计在特定的类中
1.2)若为所有对象所共有的行为,则将方法设计在超类中
2)窗口调用:
2.1)若为定时发生的,则在定时器中调用
2.2)若为事件触发的,则在侦听器中调用------明天上午第2节课讲