Java面向对象 (四) static final常量、抽象方法、抽象类、匿名内部类、成员内部类

第六天:
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节课讲

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值