【Java】day11--多态、内部类、异常、

(一)多态

多态的应用场景:
        1.多态用于形参类型的时候,可以接收更多类型的数据。
        2.多态用于返回值类型的时候,可以返回更多类型的参数。

    多态的好处:提高了程序的拓展性 。

多态情况下,不能访问子类特有的成员。
    多态情况下如果需要调用子类特有的成员,需要进行强制类型转换。

    引用数据类型:
        小数据类型--》大数据类型:自动类型转换
        大数据类型--》小数据类型:强制类型转换

例如:

abstract class Animal
{
	String name;
	String color;
	public Animal(String name,String color){
		this.name=name;
		this.color=color;
	}
	public abstract void run();
}
//鱼
class Fish extends Animal
{
	public Fish(String name,String color){
		super(name,color);
	}

	public void run(){
		System.out.println(name+"摇摇尾巴游啊游~~~");
	}

	public void bubble(){
		System.out.println(name+"开心开心吐泡泡~~~");
	}
}
//兔
class Rabbit extends Animal
{
	public Rabbit(String name,String color){
		super(name,color);
	}
	public void run(){
		System.out.println(name+"蹦蹦跳跳真可爱!!!");
	}
	public void tricky(){
		System.out.println(name+"狡兔三窟。。。");
	}
}
class demo2 
{
	public static void main(String[] args) 
	{
	/*	Animal a=new Fish("锦鲤","金红色");//自动类型转换

		Fish f=(Fish)a;			//强制类型转换  把动物看成鱼

		Animal b=new Rabbit("小白兔","白色");

		Rabbit r=(Rabbit)b;

		f.run();
		f.bubble();//多态情况下不能调用子类特有方法,要用的话

		r.run();
		r.tricky();*/
	//	System.out.println("Hello World!");
		Fish f=new Fish("草鱼","黑色"); 
		print(f);
	}
	//定义一个方法可以接受任何类型的动物,在方法内部调用动物特有的方法
	public static void print(Animal a){
		if(a instanceof Fish){
			Fish f=(Fish)a;
			f.bubble();
		}else if(a instanceof Rabbit){
			Rabbit r=(Rabbit)a;
			r.tricky();
		}
	}
}

接口中的方法都是abstract,不能与static配合使用,所以接口中的函数都是非静态。
多态情况下,接口和实现类存在同名函数,永远访问实现类。

 

(二)内部类

内部类:在一个类的内部定义另一个类,另一个类就是内部类。
    内部类的类型:
        1.成员内部类:内部类作为成员,与成员变量、成员函数并列。
            class文件名:外部类名$内部类名.class  区分开内部类属于哪一个外部类。
            访问方式:
                方式一:在外部类提供一个方法创建内部类的对象进行访问。
                方式二:在其他类中直接创建内部类的对象进行访问。
                        格式 :外部类.内部类 变量名=new 外部类().new 内部类()
                注意:在其他类中直接创建静态内部类的对象进行访问。
                        格式:外部类.内部类 变量名=new 外部类.内部类()
            要注意的细节:
                1.内部类可以直接访问外部类的所有成员。
                2.内部类与外部类存在同名的成员时,在内部类中默认是访问内部类的成员。(就近原则)
                  可以通过"外部类.this.成员变量"访问外部类的成员。
                3.私有的成员内部类只能通过在外部类提供一个公共的方法进行访问,在其他类中无法访问。
                4.如果一个成员内部类定义了静态的成员,那么该类也必须使用static修饰。
                    原因:静态成员变量不依赖于对象。

例如:

class Outer
{
	//外部类的成员变量
	private String name="外部类";

	//成员内部类
	static class Inner
	{
		static int x=10;
		String name="内部类";//就近原则
		public void print(){
			System.out.println("这个是内部的print方法:"+name);
		}
	}
	//外部类成员函数
	public void newInstance(){
		Inner inner=new Inner();
		inner.print();
		//System.out.println(name);
	}
}
//其他类
class demo4 
{
	public static void main(String[] args) 
	{
		/*Outer outer=new Outer();
		outer.newInstance();*/
		//创建内部类对象(非静态)
		/*Outer.Inner inner=new Outer().new Inner();
		inner.print();*/
		//创建内部类对象(静态)
		Outer.Inner inner=new Outer.Inner();
		inner.print();
		//Inner inner=new Inner();
		//System.out.println("x:"+Outer.Inner.x);
	}
}

  2.局部内部类:在一个方法的内部定义的类称作局部内部类。
        要注意的细节:
            1.如果局部内部类要访问局部变量,局部变量需要用final修饰。
                原因:局部内部类的生命周期比局部变量的长,在访问时会对局部变量进行复制,用final修饰。

例如:

class Outer
{
	
	public void print(){
		final int y=90;//y的生命周期:执行该语句的时候存在在内存中,方法执行完毕消失。
		class Inner
		{
			int x=10;
			public void show(){
				System.out.println("这是内部类的show方法"+y);//若y已消失,还需要访问y,感觉y的生命周期被拉长
				/*解决方法:让局部内部类访问局部变量的复制品,即用final定义*/
			}
		}
		//创建一个局部内部类对象
		Inner inner=new Inner();//Inner对象的生命周期比y的长:执行到该语句时存在在内存中,方法执行完毕时还没有消失,等待垃圾回收期回收
		inner.show();
	}
}
class demo5 
{
	public static void main(String[] args) 
	{
		Outer outer=new Outer();
		outer.print();
	//	System.out.println("Hello World!");
	}
}

3.匿名内部类(用最多)

匿名内部类:没有类名的内部类就称为匿名内部类。
        好处:简化书写。
        使用前提:必须存在继承或实现的关系。
        注意事项:
            1.匿名内部类只是没有类名而已,其他的一切成员都有。

例如:

abstract class Animal
{
	public abstract void run();
	public abstract void memory();
}
class Outer
{
	public void print(){
		//匿名内部类,创建对象时,由于没有类名,只能借用父类名
		//new的是一个Animal的子类对象,必须要实现Animal中的抽象方法
		//多态 父类的引用类型变量指向了子类的对象
		Animal a=new Animal(){
			//大括号里面是匿名内部类的成员,也可以写专属成员变量
			String name;
			public void run(){
				System.out.println("鱼在游~~~");
			}
			public void memory(){
				System.out.println("鱼只有七秒钟记忆哦。。。");
				//return this;//代表了当前对象,可以调用专有函数.memory().run()
			}
		};//可以直接在这里调用函数,对象.函数名()
		a.run();
		a.memory();
		/*new Animal(){
			//匿名内部类的成员
			public void run(){
				System.out.println("鱼在游~~~");
			}
		}.run();*/
	}
}
class demo6 
{
	public static void main(String[] args) 
	{
		Outer outer=new Outer();
		outer.print();
	}
}

(接口)实现关系下的匿名内部类:

interface A
{
	public void add();
}
class Outer
{
	//实现关系下的匿名内部类
	public void print(){
		//创建的是接口实现类的对象
		new A(){
			//匿名内部类的对象
			public void add(){
				System.out.println("添加~");
			}
		}.add();
	}
}

 

          

    内部类的好处:可以直接访问外部类的所有成员。
    应用场景:我们在描述A事物的时候,A事物内部还维护了另一个B事物,而且B事物还必须要访问到A事物的成员,这时候就可以使用内部类描述B事物。

 

(三)java中的异常体系

java异常体系:描述不正常情况的类的集合。
    异常:
    Throwable常用的方法:
        1.toString() //返回的是用于描述该异常情况的类的完整类名。(包名+类名=完整类名)
        2.getMessage()  //返回创建Throwable对象的时候传入的消息字符串
        3.printStackTrace()//打印异常的栈消息

Throwable
        Error:错误一般都是由于jvm或者硬件引发的问题,所以一般不会通过代码处理。
        Exception:异常  如果程序出现了异常,那么一般就需要通过代码去处理了。
    程序出现了不正常情况,怎么区分到底是错误还是异常呢?
        如果不正常情况的消息是以Error结尾的,是错误。
        如果不正常情况的消息是以Exception结尾的,是异常。
 

    疑问:怎么会有异常的栈信息出现呢?
            异常的栈信息是通过printStackTrace的方法打印的,那么异常对象从何而来?
        
    原因:java虚拟机在执行a/b代码的时候,发现b(除数)等于0,在现实生活中属于一种不正常的情况,
    jvm一旦发现了不正常的情况,那么马上就会创建一个相应的异常对象,并且调用该异常对象的
    printStackTrac方法把异常的栈信息打印出来。

    异常的处理方式:
        方式一:捕获处理
            捕获处理的格式:
                try{
                    可能会发生异常的代码
                }catch(异常的类型 变量名){
                    异常处理代码;
                }
            捕获处理要注意的细节:
                1.如果一个try块的代码出现了异常,经过处理之后,那么try-catch块外面的代码可以正常执行。
                2.如果一个try块的代码出现了异常,那么在try块中出现异常的代码后面的所有代码都无法正常执行。

class demo9 
{
	public static void main(String[] args) 
	{
		div(8,0);
	}
	public static void div(int a,int b){
		int c=0;
		try{
			c=a/b;
			System.out.println("我能执行吗?");
		}catch(ArithmeticException e){			//jvm会在该句创建一个异常对象
			//异常的处理代码
			System.out.println("出错了。。");
			System.out.println(e.toString());
		}
		//int c=a/b;//jvm会创建一个异常对象,调用相应的方法,打印栈信息
		System.out.println(c);
	}
}


            

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值