内部类与异常

前言:目标确定之后就要坚持走下去,达到目标的过程中,每一个困难都会淘汰一批人,克服不了自己也会淘汰,然后又换目标,
发现干一段时间又有困难,困难不克服永远没法成功!

内部类

定义在一个类当中的类被称为内部类 为什么要使用内部类: 内部类是共享数据最最简单的方式之一 *:内部类也是类

内部类的分类:

成员内部类,静态内部类,局部内部类,匿名内部类

成员内部类:

成员内部类共享外部类的所有[静态+非静态]成员[属性+方法] 如何创建对象呢? Outer.Inner in = new Outer().new Inner(); #:成员内部类与外部类的关系 就像蛔虫与牛的关系 *:相当于孙悟空变成苍蝇飞到妖怪的肚子里,妖怪的心肝脾肺肾都能被孙悟空访问到,妖怪就是外部类,孙悟空相当于内部类 ------ public class Test01 { public static void main(String[] args){ Outer.Inner in = new Outer().new Inner(); in.test(); /* 10 20 30 Outer类的show()方法 */ } } class Outer{ int a = 10; static int b = 20; public void show(){ System.out.println("Outer类的show()方法"); } class Inner{ int c = 30; public void test(){ System.out.println(a); System.out.println(b); System.out.println(c); show(); } } } ------

静态内部类

静态内部类共享外部类的静态成员 如何创建对象? Outer.Inner in = new Outer.Inner(); #:静态内部类与外部类的关系,就像CPU与电脑 #:静态内部类只能访问外部类的静态成员,但这不是目的,因为其他类都可以 通过类名.访问外部类的静态成员。静态内部类不是用来共享数据的,而是表示内部类与 外部类有特定关系的,比如电脑与CPU ------ public class Test02 { public static void main(String[] args){ Outer.Inner in = new Outer.Inner(); in.test(); } } class Outer{ int a = 3; static int b = 9 ; static class Inner{ int x = 7; static int y = 9; public void test(){ System.out.println(a);//无法从静态上下文中引用非静态 变量 a System.out.println(b);//true System.out.println(x);//true System.out.println(y);//true } } } ------

局部内部类:

局部内部类共享外部类的成员取决于所在方法是不是静态修饰 如果不是静态,则能够共享所有成员 如果是静态,则只能共享静态成员 另外还能访问其所在方法中final修饰的局部变量 *:JDK8开始可以不加final,但是也必须是最终变量(不能修改) 如何创建对象呢? Inner in = new Inner(); *:注意必须在定义完成后,所在方法结束前![局部] *:注意局部内部类及局部变量都不能用static修饰 static为什么不能修饰局部变量? static修饰的变量要求当类第一次被加载的时候 内存空间里面就要有他 但是局部变量是当所在的方法调用的时候 内存空间才会有这个变量 类的加载永远再前面 方法的调用永远再后面 着两个时间点 赶不上一起 于是static不能修饰局部变量 ------ public class Test03 { public static void main(String[] args){ Outer out = new Outer(); out.show(30); } } class Outer{ int a = 10; static int b = 20; public void show(int c){ static int d = 40; class Inner{ int x = 50; public void test(){ System.out.println(a);//10 System.out.println(b);//20 System.out.println(c);//30 System.out.println(d);//40 System.out.println(x);//50 } } Inner in = new Inner(); in.test(); } } ------ public class Test03 { public static void main(String[] args){ Outer out = new Outer(); out.show(30); } } class Outer{ int a = 10; static int b = 20; public static void show(int c){ int d = 40; class Inner{ int x = 50; public void test(){ System.out.println(a);//无法从静态上下文中引用非静态 变量 a System.out.println(b);//20 System.out.println(c);//30 System.out.println(d);//40 System.out.println(x);//50 } } Inner in = new Inner(); in.test(); } } ------

匿名内部类:

*:假如我们生个孩子就是为了卖钱的,事实上就不用给孩子起名字了 *:在某些时候我们去找父母的朋友办事,此时我们的名字根本就不重要,人家只关心你父母是谁, 你叫什么名字并没有谁在意(匿名内部类当成参数传递) 如何创建匿名内部类对象? 父类类型 对象名字 = new 父类/接口(可能会传参){ 完成方法实现或者方法覆盖; }; 匿名内部类能够共享什么取决于定义它的位置,它能够等价于上述三种的任何一种~ ------ public class Test04 { public static void main(String[] args){ Set<Integer> set = new TreeSet<>(new Comparator<Integer>(){ @Override public int compare(Integer i1,Integer i2){ return i1 - i2; } }); Collections.addAll(set,44,33,66,77,55); System.out.println(set);//[33, 44, 55, 66, 77] } } /*class QQB implements Comparator<Integer>{ @Override public int compare(Integer i1 , Integer i2){ return i1 = i2; } }*/ ------ public class Test05 { public static void main(String[] args){ Teacher tea = new Teacher(); tea.eat();//老师吃食物 Person stu = new Person("陈浩南",20){ @Override public void eat(){ System.out.println("学生吃扇贝"); } }; stu.eat();//学生吃扇贝 } } abstract class Person{ String name; int age; public Person(String name,int age){ this.name = name; this.age = age; } public abstract void eat(); } class Teacher extends Person{ public Teacher(){ super("孔子",2000); } @Override public void eat(){ System.out.println("老师吃食物"); } } ------

共享数据的三种方法:

1.多个类共享一个类的静态成员,即使用静态变量完成数据的共享~ ------ public class Test06 { public static void main(String[] args){ 吕布 lxb = new 吕布(); 董卓 dxz = new 董卓(); lxb.play();//吕小布play貂蝉 dxz.play();//董小卓play貂蝉 } } class 漱芳斋{ static Object 貂蝉 = new Object(){ @Override public String toString(){ return "貂蝉"; } }; } class 吕布{ public void play(){ System.out.println("吕小布play"+漱芳斋.貂蝉); } } class 董卓{ public void play(){ System.out.println("董小卓paly"+漱芳斋.貂蝉); } } ------ 2.使用参数传递完成共享 ------ public class Test07 { public static void main(String[] args){ Object 貂蝉 = new Object(){ @Override public String toString(){ return "貂蝉"; } }; 吕布 lxb = new 吕布(貂蝉); 董卓 dxz = new 董卓(貂蝉); lxb.play();//吕小布play貂蝉 dxz.play();//董小卓play貂蝉 } } class 吕布{ Object obj; public 吕布(Object obj){ this.obj = obj; } public void play(){ System.out.println("吕小布play"+obj); } } class 董卓{ Object obj; public 董卓(Object obj){ this.obj = obj; } public void play(){ System.out.println("董小卓play" + obj); } } ----- 3.使用内部类完成数据共享 ----- public class Test08 { public static void main(String[] args){ 漱芳斋 sfz = new 漱芳斋(); 漱芳斋.吕布 lxb = sfz.new 吕布(); 漱芳斋.董卓 dxz = sfz.new 董卓(); lxb.play();//吕小布play貂蝉 dxz.play();//董小卓play貂蝉 } } class 漱芳斋{ Object 貂蝉 = new Object(){ @Override public String toString(){ return "貂蝉"; } }; class 吕布{ public void play(){ System.out.println("吕小布play"+貂蝉); } } class 董卓{ public void play(){ System.out.println("董小卓play"+貂蝉); } } } ----- 注意:传参完成赋值的职业选手是setter方法,而不是构造方法 ----- public class Test09 { public static void main(String[] args){ Teacher t = new Teacher(?); Student s = new Student(?);//这里怎么传参初始化,此时就需要用setter来完成赋值 } } class Student{ Teacher tea; public Student(Teacher tea){ this.tea = tea; } } class Teacher{ Student stu; public Teacher(Student stu){ this.stu = stu; } } ----- public class Test09 { public static void main(String[] args){ Student s = new Student(); Teacher t = new Teacher(); s.setTea(t); t.setStu(s); } } class Student{ Teacher tea; public void setTea(Teacher tea){ this.tea = tea; } } class Teacher{ Student stu; public void setStu(Student stu){ this.stu = stu; } } -----

异常 Exception

例外->程序运行过程中方出现的例外情况 Throwable[可抛出的]类 Error类 Exception类 [错误] [异常] RuntimeException [运行时异常] *:Error 和 Exception有什么区别? Error是指由于底层硬件或者系统原因导致的程序员通过代码无法解决的问题,统称为Error Exception是指程序运行过程中出现了例外的情况 *:RuntimeException 和 Exception有什么区别? Exception是RuntimeException的父类 运行时异常指的是在编译时不需要给出处理方案 编译就能通过,问题会在运行时直接体现 非运行时异常指的是在编译时必须要给出问题的处理方案,否则编译无法通过 *:常见的运行时异常 ArithmeticException 算术异常 ArrayIndexOutOfBoundsException 数组索引值超出边界异常 NegativeArraySizeException 负数数组大小异常 StringIndexOutOfBoundsException 字符串索引值超出边界异常 NullPointerException 空指针异常 NumberFormatException 数字格式异常 ClassCastException 类造型异常 IndexOutOfBoundsException 索引值超出边界异常 IllegalStateException 非法状态异常 IllegalArgumentException 非法参数异常 ConcurrentModificationException 并发修改异常 *:常见的非运行时异常 ClassNotFoundException FileNotFoundException NoSuchMethodException CloneNotSupportedException IOException ------ public class TestRuntimeException{ public static void main(String[] args){ //ConcurrentModificationException => 并发修改异常 //IllegalStateException => 非法状态异常 List<Integer> list3 = new ArrayList<>(); Collections.addAll(list3,11,22,55,33,44); Iterator<Integer> car = list3.iterator(); car.next(); car.remove(); car.remove(); System.out.println(list3);//? //IndexOutOfBoundsException => 索引值超出边界异常 List<Integer> list2 = new ArrayList<>(); System.out.println(list2.get(0)); //IllegalArgumentException => 非法的参数异常 List<Integer> list = new ArrayList<>(-8); //NumberFormatException => 数字格式异常 String str3 = "123a"; int num = Integer.parseInt(str3); //ClassCastException => 类造型异常 Object stu = new Student(); Cacti cc = (Cacti)stu; //StringIndexOutOfBoundsException => 字符串索引值超出边界异常 String str2 = "123"; System.out.println(str2.charAt(5)); //NullPointerException => 空指针异常 String str = null; System.out.println(str.length());//? //ArrayIndexOutOfBoundsException => 数组索引值超出边界异常 => 下标越界 int[] data2 = new int[]{1,2,3}; System.out.println(data2[3]); //NegativeArraySizeException => 负的数组大小异常 int[] data1 = new int[-3]; //ArithmeticException => 算术异常 System.out.println(5.0 / 0); } } class Student{}//学生 class Cacti{}//仙人掌 ------ 为什么要处理异常? a> 非运行时异常如果不去处理,连编译都无法通过 b> 一旦程序出现异常,程序会直接中断结束,不能继续之后 如何处理异常呢? 1.抛还上级 throws 本方法当中出现指定种类的异常 本方法不作处理,抛还给调用的上级方法当中进行处理 2.自行处理 try catch finally try{ 可能出现异常的语句;//一条语句可以出现多个异常,但是这多个异常也是细分下来一个操作抛出一个异常 }catch(要捕获的异常种类 异常代号){ //可以什么都不做,无视 //1.简明扼要 System.out.println(异常代号.getMessage()); //2.非常详细 e.printStackTrace();//看异常信息的时候从上往下找到第一个你写的类 }finally{ 无论是否出现异常,最终都要执行的操作 通常是释放关闭资源的操作; *:这里不应该出现return 和 throw *:System.exit(0);退出虚拟机,以后代码都不执行了 } 注意: try{ return 5/0; }catch(Exception e){ return 10; }finally{ System.out.println(“我很帅”); } 5/0运行后会出现异常,然后执行catch分支,catch分支是return,则先不执行,去执行finally语句, 执行完回到catch,return语句返回;如果try没捕获到异常,则return之前先去执行finally然后回到try语句块执行return语句 *:一个try可以跟着多个catch,但是必须由小到大(最多并列)的范围 *:JDK7.0开始,我们可以在一个catch用|连接多个不同种类异常 throw 和 throws的区别: throw 用在方法体当中,在没有异常出现的情况下主动制造异常出现的场景 throws 用在方法签名的最后,表示本方法当中出现指定的异常,本方法不作处理,抛还给调用的上级(方法)处理 ----- public class Test08{ public static void main(String[] args){ test(0); } public static int test(int x){ try{ return 5 / x; }catch(Exception e){ return 0; }finally{ System.out.println("EtoakViva"); } } } ----- //finally当中永远不应当出现return语句~ public class Test9{ public static void main(String[] args){ System.out.println(test(100)); System.out.println(test(50)); System.out.println(test(0)); System.out.println(test(50)); System.out.println(test(100)); } public static int test(int x){ try{ return 100 / x; }catch(Exception e){ System.out.println("吖 出事了吖~"); return 0; }finally{ return 7777; } } }

扩展知识:*********

1:当一个成员变量通过调用一个有一场声明的方法来赋值的时候, 我们可以借助初始化块来完成异常处理 ------- public class Test01 { public static void main(String[] args)throws Exception{ A a = new A(); System.out.println(a.a); } } class A{ /*第一种,通过构造方法初始化成员变量,然后构造方法抛出异常 int a ; public A()throws Exception { a = get(); } */ //第二种:通过代码块进行try{}catch(){}处理 int a; { try { a = get(); } catch (Exception e) { e.printStackTrace(); } } public static int get() throws Exception{ int lucky = (int)(Math.random()*10); if(lucky == 2 || lucky == 4){ throw new Exception("NotJiLiException"); } return lucky; } } ----- 2:当我们执行多个关闭释放资源时,如果一个出现异常,其他关闭操作无法执行,此时 我们可以挨个try{}catch(){},或者foreach循环try{}catch(){},循环操作之前必须要保证 多个操作属于同一种类型或者实现同一个接口,这样可以使用多态解耦特点来实现 ----- public class Test10 { public static void main(String[] args) { SLT slt1 = new SLT(); SLT slt2 = new SLT(); SLT slt3 = new SLT(); /*try{ slt1.close(); }catch(Exception e){ e.printStackTrace(); } try{ slt2.close(); }catch(Exception e){ e.printStackTrace(); } try{ slt3.close(); }catch(Exception e){ e.printStackTrace(); }*/ //这种方式有个弊端,假如第一个catch中有return语句,那么剩下两个try catch不会执行,所以应该如下表示 /*try{ slt1.close(); }catch(Exception e){ e.printStackTrace(); }finally{ try{ slt2.close(); }catch(Exception e){ e.printStackTrace(); }finally{ try{ slt3.close(); }catch(Exception e){ e.printStackTrace(); } } }*/ //这种代码层级太多,可以写一个closeAll()方法 closeAll(slt3, slt2, slt1); } public static void closeAll(SLT... slt){ for(SLT s : slt){ try{ s.close(); }catch(Exception e){ e.printStackTrace(); } } } } class SLT{ public void close()throws Exception{ int lucky = (int)(Math.random()*2); if(lucky == 0) throw new Exception("水龙头关闭异常!"); System.out.println("正常关闭水龙头"); } } ----- 假如不是同一种类型,则可以让不同种类的水龙头实现相同的接口,代码如下: ----- public class Test11 { public static void main(String[] args){ SLTA slta = new SLTA(); SLTB sltb = new SLTB(); SLTC sltc = new SLTC(); closeAll(sltc,sltb,slta); } public static void closeAll(CloseableSLT... slt){ for(CloseableSLT s : slt){ try{ s.close(); }catch(Exception e){ e.printStackTrace(); } } } } interface CloseableSLT{ void close(); } class SLTA implements CloseableSLT{ @Override public void close(){ int lucky = (int)(Math.random()*2); if(lucky == 0) throw new RuntimeException("水龙头SLTA关闭异常!!!"); System.out.println("水龙头SLTA正常关闭"); } } class SLTB implements CloseableSLT{ @Override public void close(){ int lucky = (int)(Math.random()*2); if(lucky == 0) throw new RuntimeException("水龙头SLTB关闭异常!!!"); System.out.println("水龙头SLTB正常关闭"); } } class SLTC implements CloseableSLT{ @Override public void close(){ int lucky = (int)(Math.random()*2); if(lucky == 0) throw new RuntimeException("水龙头SLTC关闭异常!!!"); System.out.println("水龙头SLTC正常关闭"); } } ----- 3:所有方法默认抛出RuntimeException,子类覆盖父类方法时,表面上父类方法没有抛出异常,子类抛出了多个RuntimeException 但实际上都抛出RuntimeException。 ----- public class Test12 { public static void main(String[] args){ B b = new B(); b.test(); } } class A{ public void test(){ System.out.println("父类A中的test()方法"); } } class B extends A{ @Override public void test()throws NullPointerException,IllegalArgumentException{ System.out.println("子类B中的test()方法"); } } ----- 4:当调用抛出异常的方法给局部变量赋值时,可以将初始化语句放在try{}catch(){}外 ----- public class Test13 { public static void main(String[] args){ int x = 0;//局部变量没有初始值,必须要保证在使用之前已经赋值了 try{ x = get(); }catch(Exception e){ e.printStackTrace(); } System.out.println(x); } public static int get()throws Exception{ int lucky = (int)(Math.random()*2); if(lucky == 0) throw new Exception("有一定概率牺牲!!"); return lucky; } } ----- 5:讨论:将来的将来是否可以用try catch取代传统的分支结构,包括if else / switch case ----- public class Test14 { public static void main(String[] args){ System.out.println(check("a1213131"));//false System.out.println(check("1213131"));//true System.out.println(check("-1"));//true } public static boolean check(String str){ /** * 要求,如果参数str是由全数字组成则方法返回true * 否则返回false */ try{ Integer.parseInt(str); return true; }catch(Exception e){ return false; } } } -----
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值