JAVA 多态 异常 泛型
多态
多态性是指同一个操作作用于某一类对象,可以有不同的解释,产生不同的执行结果
多态的必要条件和作用
多态的三个必要条件
- 需要存在继承和实现关系
- 同样的方法调用而执行不同操作 运行不通代码(重写)
- 在运行父类或接口的引用变量可以引用某子类的对象
多态的作用
1 多态通过分离做什么和怎么做,从一个角度将接口和实现进行分离
2 多态消除了类型之间的耦合关系
3 多态的存在提高了程序的扩展性和后期的可维护性
有子类转型成父类 叫向上转型。向上转型是从一个较为专业类型向通用类型转换,所以总是安全的。向上转型会造成方法丢失
向下转型则不安全,要先进行判断 判断是否能进行转型(需要instanceof协助)
abstract class Animal{
abstract void eat();
}
class Dog extends Animal{
public void eat() {
// TODO Auto-generated method stub
System.out.println("狗吃骨头");
}
public void sleep() {
System.out.println("狗狗睡觉");
}
}
class Cat extends Animal{
public void eat() {
// TODO Auto-generated method stub
System.out.println("猫吃鱼");
}
}
public class Test {
public static void main(String[] args) {
Animal an1 = new Dog();
Animal an2 = new Cat();
an1.eat();
//an1.sleep(); //向上转型造成方法丢失
an2.eat();
if(an2 instanceof Cat){ //向下转型要先进行判断 判断是否能进行转型
System.out.println("lm");
Cat cat = (Cat)an2;
cat.eat();
}
}
}
多态的好处:用打印机案例来呈现
import java.util.logging.Handler;
class Dayinji
{
public String binpai;
public void print(String contex){
}
}
class caise extends Dayinji
{
public void print(String contex) {
// TODO Auto-generated method stub
System.out.println("彩色打印"+contex);
}
}
class Heibai extends Dayinji
{
public void print(String contex) {
// TODO Auto-generated method stub
System.out.println("黑白打印"+contex);
}
}
class Zhenshi extends Dayinji
{
public void print(String contex) {
// TODO Auto-generated method stub
System.out.println("针式打印"+contex);
}
}
class School
{
public Dayinji dayinji;
public void anZhuang(Dayinji dayinji){
this.dayinji = dayinji;
}
public void print(String contex){
dayinji.print(contex);
}
}
public class Test {
public static void main(String[] args) {
School s = new School();
caise c = new caise();
s.anZhuang(c);
s.print("linruimiao");
Heibai h = new Heibai();
s.anZhuang(h);
s.print("lrm");
Zhenshi z = new Zhenshi();
s.anZhuang(z);
s.print("linmu");
}
}
异常
所谓异常是指在程序运行的过程中发生的一些不正常事件。(如:除0溢出,数组下标越界,所要读取的文件不存在)。
JAVA程序的执行过程中取出现异常事件,可以生成一个异常类对象,该异常对象封装了异常事件的信息,并将其被提交给JAVA运行时系统,这个过程称为抛出异常,不处理的话会导致程序直接中断。
设计良好的程序应该在程序异常发生时提供处理这些异常的方法,是的程序不会因为异常的发生而阻断或发生不可预见的结果。
异常的分类
受查异常 Exception及其子类 必须处理
非受查异常 Error和RuntimeException及其子类 可以不处理
JAVA异常处理机制
Try-catch-finally
try:监控区域,执行可能产生异常的代码
catch:捕获 处理异常
finally 善后处理 无论是否发生异常,代码总能执行 一般同来释放资源
异常处理
import java.util.Scanner;
class Person
{
String name;
int a;
int b;
double c;
}
public class Test {
public static void main(String[] args) {
Person p1 = null;
Person p2 = new Person();
try{
p1.name = "dfasf";
}catch(java.lang.NullPointerException e){
System.out.println("空指针");
};
p2.a = 10;
p2.b = 0;
p2.c = 0;
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个数");
p2.b = sc.nextInt();
try{
p2.c = p2.a/p2.b;
}catch(java.lang.ArithmeticException e){//Exception e 捕获所有异常
System.out.println("输入错误 重新输入一个数");
p2.b = sc.nextInt();
p2.c = (double)p2.a/p2.b;
};
System.out.println("c="+p2.c);
System.out.println("end");
}
}
JAVA: 除数为double 0,不会报错,为无穷大
异常抛出
throw用于手动抛出异常。作为程序员可以在任意位置手动抛出异常。后面跟上要抛出的异常类对象
throws用于在方法上标识要暴露的异常。抛出的异常交由调用者处理。后面跟上可能要抛出的异常类名
class Bar{
int age;
public Bar(int age){
this.age = age;
}
void check()throws nianjitaixiaoException{ //声明异常
if(age < 18){
throw new nianjitaixiaoException("年纪太小");//手动抛出异常
}
}
}
class nianjitaixiaoException extends Exception //自定义异常
//受查异常 不处理编译通不过
{
private String message;
public nianjitaixiaoException(String message){
this.message = message;
}
}
public class Test {
public static void main(String[] args) {
Bar b = new Bar(2);
try{
b.check();
}catch(nianjitaixiaoException e){
System.out.println("年纪太小");
}
System.out.println("end");
}
}
泛型
泛型可以在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的(防止误操作)
泛型的原理就是“类型的参数化”就像方法的形式参数是运行时传递的值得占位符一样
泛型可以提高代码的扩展性和重用性
泛型特点
1 泛型类可以设置多个类型参数
2 泛型的类型参数也可以是泛型
import javax.swing.text.GapContent;
class Stduent<T>
{
T a;
public Stduent(T a){
this.a = a;
}
public T getdata(){
return a;
}
}
class Teacher<T1,T2> //泛型类可以设置多个类型参数
{
T1 a;
T2 b;
public Teacher(T1 a, T2 b){
this.a = a;
this.b = b;
}
public T1 getdata1(){
return a;
}
public T2 getdata2() {
return b;
}
}
public class Test {
public static void main(String[] args) {
Stduent<Integer> s = new Stduent<Integer>(5);
System.out.println("s="+s.getdata());
Stduent<String> a = new Stduent<String>("linruimiao");
System.out.println("a="+a.getdata());
Teacher<Integer, String> t1 = new Teacher<Integer, String>(100, "lrm");
System.out.println("data="+ t1.getdata1());
System.out.println("data="+ t1.getdata2());
System.out.println("data=" + (t1.getdata2()+t1.getdata1()));
Teacher<Integer, Integer> t2 = new Teacher<Integer, Integer>(10, 20);
System.out.println("data=" +(t2.getdata1()+t2.getdata2()));//都是整形数可以相加
Stduent<Stduent<Integer>> b = new Stduent<Stduent<Integer>>(new Stduent<Integer>(100)); //泛型的类型参数也可以是泛型
System.out.println("data="+ b.getdata().getdata());
}
}
3 泛型类可以继承泛型类
4 泛型类可以实现接口
abstract class Stduent<T> // 抽象泛型类
{
T a;
public Stduent(T a){
this.a = a;
}
public T getdata(){
return a;
}
abstract void printnfo();
}
interface Student2<T3> //泛型接口
{
abstract void printnfot3(T3 t);
}
class Teacher <T,T2,T3> extends Stduent<T> implements Student2<T3> // 继承泛型类 接口
{
T2 b;
public Teacher(T a, T2 b){
super(a);
this.b = b;
}
public T2 getdata2() {
return b;
}
@Override
void printnfo() {
// TODO Auto-generated method stub
System.out.println("data="+a);
System.out.println("data="+b);
}
public void printnfot3(T3 t) {
// TODO Auto-generated method stub
System.out.println("data="+t);
}
}
public class Test {
public static void main(String[] args) {
Teacher<String, Integer,Integer> t = new Teacher<String, Integer,Integer>("linruimiao",100);
t.printnfo();
t.printnfot3(450);
}
}
若要限制泛型可用类型 在定义类型时 使用extends关键字指定这个类型必须是继承某个类,或者实现某个接口
当没有指定泛型继承的类型或接口是,默认使用extends Object,所以默认情况下任何类型都可以传入
泛型继承接口都用 extends
class Animal
{
}
class Dog extends Animal
{
int data;
public Dog(int data){
this.data = data;
}
public int getdata3(){
return data;
}
}
interface Move
{
abstract void printInfo();
}
abstract class Stduent1<T extends Move> // 泛型继承接口都用 extends
{
}
abstract class Stduent<T>
{
T a;
public Stduent(T a){
this.a = a;
}
public T getdata(){
return a;
}
abstract void printnfo();
}
interface Student2<T3>
{
abstract void printnfot3(T3 t);
}
class Teacher <T ,T2 extends Dog,T3> extends Stduent<T> implements Student2<T3>
{
T2 b;
public Teacher(T a, T2 b){
super(a);
this.b = b;
}
public T2 getdata2() {
return b;
}
@Override
void printnfo() {
// TODO Auto-generated method stub
System.out.println("data="+a);
System.out.println("data="+b.getdata3());
}
public void printnfot3(T3 t) {
// TODO Auto-generated method stub
System.out.println("data="+t);
}
}
public class Test {
public static void main(String[] args) {
Teacher<String, Dog, String> t = new Teacher<String, Dog,String>("linruimiao",new Dog(10));
t.printnfo();
t.printnfot3("lrm");
}
}
泛型通配符
1 “?”代表任意类型
2 extends限定通配符上限
3 super限定通配符下限
import javax.naming.ldap.ExtendedRequest;
class Animal
{
}
class Dog extends Animal
{
}
class Stduent<T>
{
T a;
public Stduent(T a){
this.a = a;
}
public T getdata(){
return a;
}
}
public class Test {
public static void main(String[] args) {
Stduent<Integer> s1 = new Stduent<Integer>(10);
Stduent<String> s2 = new Stduent<String>("linruimiao");
Stduent<?> s3; // ? 代表任意类型
Stduent<? extends Animal> s4; // 必须是Amimal的子类 上限
Stduent<? super Dog> s5; // 必须是Dog的父类 下限
Stduent<Dog> s6 = new Stduent<Dog>(new Dog());
s3 = s1;
s3 = s2;
s4 = s6;
s5 = s6;
}
}
泛型方法
相比泛型类更加灵活 但仅对本方法有效 类中的其他方法不能使用当前方法生命的泛型
是否拥有泛型方法,与其所在的类是否泛型没有关系 要定义泛型方法 只需要将泛型参数列表置于返回值前
什么时候使用泛型方法,而不是泛型类
1 添加类型约束只作用于一个方法的多个参数之间,而不是涉及类中的其他方法时
2 施加类型约束的方法为静态方法,只能将其定义为泛型方法,因为静态方法不能使用其所在类的类型约束
abstract class Animal
{
abstract void eat();
}
class Dog extends Animal
{
@Override
void eat() {
// TODO Auto-generated method stub
System.out.println("狗啃骨头");
}
}
class Cat extends Animal
{
@Override
void eat() {
// TODO Auto-generated method stub
System.out.println("猫吃鱼");
}
}
class Person extends Animal
{
@Override
void eat() {
// TODO Auto-generated method stub
System.out.println("人吃饭");
}
}
class A<T>
{
public void printInfo3(T t){
System.out.println(t);
}
}
class D
{
public <T> void printInfo(T t){ //泛型方法
System.out.println(t);
}
public static <T,T2> void printInfo(T t, T2 t2) { // 泛型方法重载
System.out.println(t);
System.out.println(t2);
// System.out.println(t1+t1); 方法类型不确定 不能加
}
public static <T extends Animal>void printfnfo2(T t) {
t.eat();
}
}
public class Test {
public static void main(String[] args) {
A<Integer> a = new A<Integer>(); // 只能输出一种类型
a.printInfo3(100);
// a.printInfo3("ssa");
D d = new D(); // 输出任意类型 更加灵活
d.printInfo("哈哈");
d.printInfo(124);
d.printInfo(0.2);
d.printInfo('a');
d.printInfo("linruimiao", 100);
D.printfnfo2(new Dog()); //施加类型约束的方法为静态方法,只能将其定义为泛型方法,因为静态方法不能使用其所在类的类型约束
D.printfnfo2(new Person());
D.printfnfo2(new Cat());
}
}