黑马程序员—【Java基础篇】之多态、内部类、异常及包

时间:2023-02-16 16:51:00

------- android培训java培训、期待与您交流! ---------

    大家好,这篇我们介绍和学习多态、内部类、异常和包的4大块知识点。

一、多态

1、定义

    某一类事物的多种存在形态。

/**
例:动物中猫,狗。
猫这个对象对应的类型是猫类型
猫 x = new 猫();
同时猫也是动物中的一种,也可以把猫称为动物。
动物 y = new 猫();
动物是猫和狗具体事物中抽取出来的父类型。
父类型引用指向了子类对象。
*/

2、多态的体现 

/**
(1).程序中体现:父类或者接口的引用指向或者接收自己的子类对象。
(2).好处和作用:多态的存在提高了程序的扩展性和后期可维护性
(3).前提:需要存在继承或者实现关系;要有覆盖操作
*/

3、多态的特点

/**
成员函数:
1.编译时:要查看引用变量所属的类中是否有所调用的成员。
2.在运行时:要查看对象所属的类中是否有所调用的成员。
3.成员变量:只看引用变量所属的类。
*/
    多态小实例:
abstract class Animal  
{
public abstract void eat();

}

//子类————猫
class Cat extends Animal
{
//复写父类中的抽象功能
public void eat()
{
System.out.println("吃鱼");
}

//Cat特有的功能
public static void catchMouse()
{
System.out.println("抓老鼠");
}
}


class Demo
{
public static void main(String[] args)
{
Animal a = new Cat(); //多态体现
a.eat(); //编译看左边,运行看右边
Cat c = (Cat)a; //对a进行了强转
c.catchMouse();//调用cat类,catchMouse();方法 .
}
}

4、多态的应用

/*
需求:
电脑运行实例,
电脑运行基于主板。
*/


interface PCI
{
public void open();
public void close();
}

class MainBoard
{
public void run()
{
System.out.println("mainboard run ");
}
public void usePCI(PCI p)//PCI p = new NetCard()//接口型引用指向自己的子类对象。
{
if(p!=null)
{
p.open();//编译看接口,运行看子类。
p.close();

}
}
}


class NetCard implements PCI
{
public void open()
{
System.out.println("netcard open");
}
public void close()
{
System.out.println("netcard close");

}

}
class SoundCard implements PCI
{
public void open()
{
System.out.println("SoundCard open");
}
public void close()
{
System.out.println("SoundCard close");
}
}
/*
class MainBoard
{
public void run()
{
System.out.println("mainboard run");
}
public void useNetCard(NetCard c)
{
c.open();
c.close();
}
}

class NetCard
{
public void open()
{
System.out.println("netcard open");
}
public void close()
{
System.out.println("netcard close");
}
}
*/

class DuoTaiDemo5
{
public static void main(String[] args)
{
MainBoard mb = new MainBoard();
mb.run();
mb.usePCI(null);
mb.usePCI(new NetCard());
mb.usePCI(new SoundCard());

}
}

二、内部类

1、概念

<span style="font-size:12px;">/**
将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类,嵌套类)。
访问特点:
内部类可以直接访问外部类中的成员,包括私有成员。
而外部类要访问内部类中的成员必须要建立内部类的对象。
*/</span>

2、位置

/**
1、成员位置
可以被private static成员修饰符修饰。
被static修饰的内部类只能访问外部类中的静态成员。
2、局部位置
可以直接访问外部类中的成员。
同时可以访问所在局部中的局部变量,但必须是被final修饰的。
*/

3、实例

/**
1.位置:内部类在局部位置上
class Outer //外部类
{
int x = 3;
void method(final int a)
{
final int y = 4;
//局部内部类
class Inner//内部类,定义在局部位置上
{
void function()
{
System.out.println(y);
}
}
new Inner().function();//使用局部内部类中的方法。
}
}
class InnerClassDemo
{
public static void main(String[] args)
{
Outer out = new Outer();
out.method(7);//打印7
out.method(8);//打印8
}
}
/**1.内部类位置在成员变量class Outer{private int x = 3;class Inner//内部类{//int x = 4;void function(){//int x = 6;System.out.println("innner :"+Outer.this.x);}}/**/void method(){Inner in = new Inner();in.function();}}class  InnerClassDemo{public static void main(String[] args) {Outer out = new Outer();out.method();//直接访问内部类中的成员。//Outer.Inner in = new Outer().new Inner();//in.function();}}

4、规则

/**
一、内部类的访问规则:
1. 内部类可以直接访问外部类中的成员,包括私有。
之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式 外部类名.this
2. 外部类要访问内部类,必须建立内部类对象。

二、访问格式:
1. 当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中。同时可以直接建立内部类对象。
格式:
外部类名.内部类名 变量名 = 外部类对象.内部类对象;
Outer.Inner in = new Outer().new Inner();

2. 当内部类在成员位置上,就可以被成员修饰符所修饰。
比如: private:将内部类在外部类中进行封装。
static:内部类就具备static的特性。
当内部类被static修饰后,只能直接访问外部类中的static成员。出现了访问局限。
在外部其他类中,如何直接访问static内部类的非静态成员呢?
new Outer.Inner().function();
在外部其他类中,如何直接访问static内部类的静态成员呢?
uter.Inner.function();
注意:当内部类中定义了静态成员,该内部类必须是static的。
当外部类中的静态方法访问内部类时,内部类也必须是static的。
当描述事物时,事物的内部还有事物,该事物用内部类来描述;因为内部事务在使用外部事物的内容。

5、内部类存在的必要

/**
1、当描述事物时,事物的内部还有事物,则该事物使用内部类来描述,因为内部事物要使用外部事物内容。
举例来说:楼房内部还有家庭住户,家庭住户中还有房间,这就可以用内部类描述。(比如需要访问一个楼房里的住户,就建立一个楼房对象吧,这样子的话,那是土豪的标志象征。)
2、何时定义内部类
当一个类需要直接访问另一个类中的成员时,则当这个类放入另一个类中,并将内部类封装。
3、内部类生成文件
我们在编译一个源文件是,如果代码中有内部类,你会发现,生成的class文件中含有例如这样的文件:A$C.class。这是为什么呢?因为内部类是一种编译现象,与虚拟机无关。编译器将会把内部类翻译成用$(美元符号)分隔外部类名和内部类名的常规类文件。
*/

6、匿名内部类

(1)定义

    匿名是一种简写格式,是内部类的另一种书写方式。

    示例,如下:

/**匿名内部类:
interface Inter //接口
{
void method(); //定义抽象方法
}
class InnerClassTest //定义内部类
{
public static void main(String[] args)
{
show(new Inter() //匿名内部类
{
public void method() //覆盖接口方法
{
System.out.println("method show run");
}
});
}

public static void show(Inter in)
{
in.method();
}
}

(2)格式

/**
匿名内部类的格式:
new父类或者接口(){定义子类的内容}
*/

(3)前提条件

/**定义匿名内部类的前提:
内部类必须是继承一个类或者实现接口。
特殊情况:因为所以的类都有一个父类Object,所以在定义时也可以用Object。
其实匿名内部类就是一个匿名子类对象。可以理解为带内容的对象。
匿名内部类中定义的方法最好不要超过3个
*/

(4)利与弊

/**
匿名内部类的利与弊:
好处:简化书写
弊端:
1、不能直接调用自己的特有方法、
2、不能做强转动作。
3、如果继承的父类或接口中有很多方法时,使用匿名内部类阅读性会非常差,且调用会很麻烦。所以匿名内部类中定义的方法有一般不超过3个。
*/

(5)何时定义

/**
1、当使用的方法的参数类型是一个接口类型时,该接口的方法不超过3个,这时可以定义一个匿名内部类,把匿名内部类作为参数传进去。
2、当没有父类和接口时,可以利用Object类创建匿名内部类。
*/

(6)练习

interface Inter  //接口
{
void method();
}

class Test
{
//补足代码,通过匿名内部类
}
class InnerClassDemo
{
public static void main(String[] args)
{
Test.function().method();
}
}
/**分析:
Test.function().method();//相当于Inter in=Test.function();in.method();
Test.function():Test类中有一个静态的方法function。
.method():function这个方法运算后的结果是一个对象,而且是一个Inter类型的对象。 因为只有是Inter类型的对象,才可以调用method方法。
*/
interface Inter
{
void method();
}

class Test
{
//补足代码,通过匿名内部类
static Inter function()
{
return new Inter()
{
public void method()
{
System.out.println("内部类练习");
}
};
}
}

class InnerClassDemo
{
public static void main(String[] args)
{
Test.function().method();
}
}
    伙伴们这个例子,懂了木?那内部类的内容,我们就介绍到这里了,接下来,我们继续分享异常。

三、异常

1、理解

/**
异常是Java中的重要机制,也使用了面向对象的思想,进行了封装。我们通常使用的异常类。
异常类中所描述的就是程序中可能出现的错误或者问题。就像人生病一样,不一定经常有,但总有生病的时候,而且生病的原因不同,性质不同,对其的治疗自然也不一样。这些都可以在异常类中得以展现。
*/

2、概述

<pre name="code" class="java">/**
异常:就是程序在运行时出现不正常情况。
异常由来:
    问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述,并封装成对象;其实就是java对不正常情况进行描述后的对象体现。    问题的划分:两种:一种是严重的问题,一种非严重的问题。严重<span style="font-family: Arial, Helvetica, sans-serif;">问题</span><span style="font-family: Arial, Helvetica, sans-serif;">,java通过Error类进行描述。</span>    对于Error一般不编写针对性的代码对其进行处理。非严重的问题,java通过Exception类进行描述。对于Exception可以使用针对性的处理方式进行处理。    无论Error或者Exception都具有一些共性内容。    如:不正常情况的信息,引发原因等。Throwable|--Error|--Exception


3、异常的处理

<span style="font-size:14px;">/**
异常的处理
java 提供了特有的语句进行处理。
try
{
需要被检测的代码;
}
catch(异常类 变量)
{
处理异常的代码;(处理方式)
}
finally
{
一定会执行的语句;
}
*/</span><span style="font-size:18px;">
</span>

(1)异常处理的三种格式

<span style="font-size: 14px;"> </span><span style="font-size:14px;">/**
a、 try
{
}
catch ()
{
}
b、 try
{
}
finally
{
}
c、 try
{
}
catch ()
{
}
finally
{
}
注意: 1)finally中定义的通常是关闭资源代码。因为资源必须释放。
2)如果在一个功能中,定义了一些必须要执行的代码,可以用try{}finally{}的方式,将一定执行的代码放在finally代码块中。
3)finally只有一种情况不会执行。当执行到System.exit(0);fianlly不会执行。</span><span style="font-size:18px;">
</span>

4、Throwable中的方法

/**
1、getMessage()
获取异常信息,返回字符串。
2、toString()
获取异常类名和异常信息,返回字符串。
3、printStackTrace()
获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。
4、printStackTrace(PrintStream s)
通常用该方法将异常内容保存在日志文件中,以便查阅。
*/

5、异常练习

    示例1:

<span style="font-size:14px;">class Demo
{
int div(int a,int b)throws Exception//在功能上通过throws的关键字声明了该功能有可能会出现问题。
{
return a/b;
}
}
class ExceptionDemo
{
public static void main(String[] args)
{
Demo d = new Demo();
try
{
int x = d.div(4,1);
System.out.println("x="+x);
}
catch (Exception e)//Exception e = new ArithmeticException();
{
System.out.println("除零啦");
System.out.println(e.getMessage());// / by zero;
System.out.println(e.toString());// 异常名称 : 异常信息。

e.printStackTrace();//异常名称,异常信息,异常出现的位置。
//其实jvm默认的异常处理机制,就是在调用printStackTrace方法。
//打印异常的堆栈的跟踪信息。
}
System.out.println("over");

}
}</span>
    示例2:
/**
需求:
毕老师用电脑上课。
考上课中出现的问题有:
1、电脑蓝屏。
2、电脑冒烟。
要对问题进行描述,封装成对象。

电脑冒烟后分享:可是当冒烟发生后,出现讲课进度无法继续。
第3个问题:出现了讲师的问题:课时计划无法完成。
*/

class LanPingException extends Exception//对问题进行描述,封装对象
{
LanPingException(String message)
{
super(message);
}
}
class MaoYanException extends Exception
{
MaoYanException(String message)
{
super(message);
}
}
class NoPlanException extends Exception
{
NoPlanException(String msg)
{
super(msg);
}
}

class Computer//对电脑描述,进行封装
{
private int state = 3;
public void run()throws LanPingException,MaoYanException
{
if(state==2)
throw new LanPingException("蓝屏了");
if(state==3)
throw new MaoYanException("冒烟了");

System.out.println("电脑运行");
}
public void reset()
{
state = 1;
System.out.println("电脑重启");
}
}
class Teacher
{
private String name;
private Computer cmpt;

Teacher(String name)
{
this.name = name;
cmpt = new Computer();

}

public void prelect()throws NoPlanException
{
try
{
cmpt.run();
}
catch (LanPingException e)
{
cmpt.reset();
}
catch (MaoYanException e)
{

test();
throw new NoPlanException("课时无法继续"+e.getMessage());

}
System.out.println("讲课");
}
public void test()
{
System.out.println("练习");
}

}



class ExceptionTest
{
public static void main(String[] args)
{
Teacher t = new Teacher("毕老师");
try
{
t.prelect();
}
catch (NoPlanException e)
{
System.out.println(e.toString());
System.out.println("换老师或者放假");
}

}
}
/**
throws与throw的联系:
(1)throws用于标识函数暴露出的异常。
(2)throw用于抛出异常对象。
throws与throw的区别:
(1)thorws用在函数上,后面跟异常类名。
(2)throw用在函数内,后面跟异常对象。
*/
电脑蓝屏时,结果为:
黑马程序员—【Java基础篇】之多态、内部类、异常及包

当电脑起火时,结果为:
黑马程序员—【Java基础篇】之多态、内部类、异常及包

四、包

1、概述

/**
java中的包就相当于系统中的文件夹。
当我们需要将各个类分门别类的存放的时候,或者含有不同功能的相同类名的时候,需要用到包(package)。包可以将相关的类放在一起,并可以将两个或多个相同文件名的文件放在不同包中。
*/

2、作用

/**
1、为避免多个类重名的情况,如果出现两个相同名字的类,可通过包将两者区分,从而避免冲突
2、对类文件进行分类管理,可以将相关的一些类放在同一个包中。
3、给类提供多层命名空间,如a包中的Demo.class文件即packagea.Demo.class
*/

3、规则

/**
1、写在程序的第一行,因为是包下的类,先有包了,才能将类放进去。
2、类名的全称:包名.类名
3、包是一种封装形式,是java封装性的体现。
*/

4、包与包之间的访问

/**
1、要访问其他包中的类,需要定义类名的全名:包名.类名
2、如果包不再当前目录下,需要设置classpath,告知虚拟机包的执行路径
3、有了包,范围变大,一个包中的类要被访问,必须有足够大的权限。
*/

5、注意事项

/**
1.包与包间进行访问,被访问的包中的类以及类中的成员,需要public修饰。
2.不同包中的子类还可直接访问父类中被protected权限修饰的成员。包与包间可使用的权限有两种:public和protected。
3.其中protected只用于覆盖。
*/

6、示例

package pack;

/**
为了简化类名的书写,使用一个关键字,import.
import 导入的是包中的类。
建议,不要写通配符 * ,需要用到包中的哪个类,就导入哪个类。
c:\myclass\packb\DemoA.class
c:\myclass\packb\haha\DemoZ.class
import packb.*;
import packb.haha.*;
建立包名小技巧:建立定包名不要重复,可以使用url来完成定义,url是唯一的。
package cn.itcast.demo
package cn.itcast.test
*/

import packb.haha.hehe.heihei.*;
import packa.*;
import packb.*;
class PackageDemo
{
public static void main(String[] args)
{

DemoC c = new DemoC();

//packa.DemoA d = new packa.DemoA();
//d.show();

//packb.DemoB d = new packb.DemoB();
//d.method();
}
}
<pre name="code" class="java">/**
总结:
包与包之间进行访问,被访问的包中的类以及类中的成员,需要public修饰。
不同包中的子类还可以直接访问父类中被protected权限修饰的成员。

包与包之间可以使用的权限只有两种,public protected。
public protected default private
同一个类中 ok ok ok ok
同一个包中 ok ok ok
子类 ok ok
不同包中 ok

java.lang : java的核心包 jdk1.2版本以后,该包中的类自动导入。
java.awt: 用于制作图形界面。
java.io:input output 用于操作设备上的数据。
java.util : 这里定义是java的工具类。集合,日期。
java.net:用于网络通讯的。
java.applet: application let server let servlet java server page jsp
class haha implements Servlet
class hehe extends HttpServlet
*/
    好了,伙伴们今天这篇就到这里了,下篇见。




------- android培训java培训、期待与您交流! ---------