内部类 --> 了解
类中定义类
当一类中的成员,作为另外一种事物的时候,这个成员就可以定义为内部类
分类:
成员内部类
静态内部类
私有内部类
局部内部类
匿名内部类
成员内部类:
一个类定义在外部类的成员位置就称为成员内部类
具有类的特点,继承,实现
成员内部类具有成员的特点,被成员修饰符修饰
注意:
在成员内部类中不饿能定义静态内容,除了静态常量,静态内部类才能任意定义静态内部
在成员内部类中可以使用外部类中的成员,包括私有的,静态的
在外部类中可以跟随成员内部类的对象使用成员内部类的成员
成员内部类的对象需要通过外部类对象构建 外部类型.内部类类名 引用 = new 外部类().new 内部类();
跟随内部类的对象使用内部类的成员,注意访问权限
public class Class001_Outer { //成员: 类中方法外 private int i = 1; private static int j = 5; //成员内部类 class Inner{ private int a = 10; public void testInner(){ System.out.println("成员内部类中的成员方法"); System.out.println(i); System.out.println(j); //outer(); } } public void outer(){ System.out.println("成员方法"); Inner in = new Inner(); System.out.println(in.a); in.testInner(); } } //成员内部类的测试 import com.yjx.inner01.Class001_Outer.Inner; public class Class002_Test { public static void main(String[] args) { //测试成员内部类使用 //成员内部类的对象性需要通过外部类对象构建 //1) Class001_Outer out = new Class001_Outer(); //外部类对象 Class001_Outer.Inner in = out.new Inner(); //2) Inner in = new Class001_Outer().new Inner(); in.testInner(); } }
静态内部类:
可以定义静态内容(成员),成员内部类中不可以直接定义静态内容除了静态常量以外。
静态内部类中可以直接使用外部类中的静态内容,需要通过外部类对象使用外部类中的成员(因为内部类本身是静态的)
外部类中可以直接通过内部类对象使用内部类成员,可以通过内部类的类名使用内部类静态内容
其他类中使用静态内部类中内容:
静态内部类中的静态内容:外部类类名.内部类类名.静态内容
静态内部类中的成员内容:new 外部类类名.内部类类名();
通过内部类对象调用它成员
public class Class004_Outer { //成员: 类中方法外 private int i = 1; private static int j = 5; //静态内部类 static class Inner{ //成员变量 int a = 1; //静态变量 static int b = 10; //成员方法 public void test(){ System.out.println(j); System.out.println(new Class004_Outer().i); } //静态方法 public static void testStatic(){ System.out.println(j); System.out.println(new Class004_Outer().i); } } void outer(){ //静态内部类对象 Inner in = new Inner(); System.out.println(in.a); System.out.println(in.b); System.out.println(Inner.b); Inner.testStatic(); in.test(); } } //静态内部类测试 import com.yjx.inner01.Class001_Outer.Inner; public class Class002_Test { public static void main(String[] args) { //测试静态内部类的使用 //静态内部类中的静态内容 : 外部类类名.内部类类名.静态内容 System.out.println(Class004_Outer.Inner.b); Class004_Outer.Inner.testStatic(); //静态内部类中的成员内容: new 外部类类名.内部类类名(); 通过内部类对象调用它成员 Class004_Outer.Inner in2 = new Class004_Outer.Inner(); in2.test(); System.out.println(in2.a); } }
私有内部类:
只能在当前外部类中通过内部类对象使用
public class Class005_Outer { private int i = 1; private static int j = 2; //私有的 private class Inner{ int a = 2; static final int B = 10; void test(){ System.out.println("私有内部类中的成员方法"); System.out.println(i); System.out.println(j); } } void outer(){ System.out.println("外部类中的成员方法"); Inner in = new Inner(); System.out.println(in.a); System.out.println(in.B); System.out.println(Inner.B); } }
局部内部类:
1.不能被成员修饰符等修饰(public private protected static)
2.局部内部类中不能定义静态内容,除了静态常量
3.局部内部类中可以直接使用外部类成员,可以使用所在方法中的局部变量
4.局部内部类只能在当前所在的方法中通过内部类对象使用,其他位置无法使用
5.在局部内部类中使用了所在方法中的局部变量|形参,这个局部变量会默认被final修饰
jdk8开始默认被final修饰
jdk7及之前需要显示被final修饰
public class Class006_Outer { //成员位置 private int i = 1; private static int j = 2; public void test(){ //局部位置 int c = 1; //c = 2; //局部内部类 class Inner{ static final int a = 1; int b = 2 void inner(){ System.out.println("局部内部类中的成员方法"); System.out.println(c); System.out.println(i); System.out.println(j); } } //1.测试所在方法中能够使用局部内部类中的内容 Inner in = new Inner(); System.out.println(in.b); in.inner(); } void outer(){ }
匿名内部类:(重点)
作用:用来简化没有本身自己作用的实现类|子类
上层:接口|抽象类
使用:
1.匿名内部类对象:没有引用指向的匿名对象,只能在当前行使用一次
2.引用指向的匿名内部类对象:通过引用后可以使用多次
3.匿名内部类对象作为实参传递
public class Class007_Outer { public static void main(String[] args) { //匿名对象 : 只能在当前行使用一次 new String(); //创建 实现类对象调用重写后的抽象方法 new Demo().smoking(); //匿名内部类 //1) 没有引用指向的匿名对象 new Smoke() {//实现类的类体 @Override public void smoking() { System.out.println("一边哈哈笑一边吸烟..."); } }.smoking(); //2. 引用指向的匿名内部类对象 Smoke s = new Smoke(){ @Override public void smoking() { System.out.println("一边吸气一边吸烟"); } }; s.smoking(); s.smoking(); //3.匿名内部类对象作为实参传递 test( new Smoke(){ @Override public void smoking() { System.out.println("一边吸气一边吸烟"); } }); //通过匿名 内部类简化子类 Car car = new Car(){ @Override void run() { System.out.println("run...."); } }; car.run(); } static void test(Smoke smoke){ smoke.smoking(); } } //抽象类 abstract class Car{ abstract void run(); } //接口 interface Smoke{ void smoking(); } //实现类 ,重写抽象方法 class Demo implements Smoke{ @Override public void smoking() { System.out.println("一边呲着牙一边吸烟..."); } }
Lambda 表达式:(重点)
jdk8新增的
作用:为了简化匿名内部类对象
前提:函数式接口
函数式接口:只有一个必须被重写的抽象方法的接口
强制检测是否为函数式接口:
注解:@FunctionalInterface
语法:
() -> {}
() : 匹配要重写的抽象方法的参数列表
-> : 箭头函数 箭头符号
{} : 要重写的抽象方法的方法体
写法:1.() -> {}
2. 当方法体只有一句,前后的{}可以省略
3.当方法具有参数,参数的类型可以省略
4.当方法的参数只有一个,前后的()可以省略
5.当方法存放返回值,并且{}语句体只有依据,就是return语句,前后的{}与return关键字可以一起省略
public class Class001_Lambda { public static void main(String[] args) { //匿名内部类对象 Run r = new Run(){ @Override public void run() { System.out.println("run...."); } }; //lambda写法1 : ()->{} Run r = ()->{ System.out.println("run...."); }; r.run(); //lambda写法2: 当方法体只有一句 ,前后的{}可以省略 Run r = ()->System.out.println("跑...."); r.run(); //lambda写法3: 当方法具有参数,参数的类型可以省略 Run r = (a,b)->System.out.println("跑...."+(a+b)); r.run(1,2); //lambda写法4: 当方法的参数只有一个 ,前后的()可以省略 Run r = a -> System.out.println("跑...."+(a)); r.run(1); //lambda写法5: 当方法存放返回值,并且{}中的语句体只有一句,就是return语句,前后的{}与return关键字可以一起省略 Run r = a -> a>0; r.run(1); test(new Run() { @Override public boolean run(int x) { return false; } }); //注意: 当方法的形参为一个函数式接口,实参可以为lambda表达式 test((i)->{return i>18;}); test(i->i>18); } static void test(Run run){ run.run(1); } } @FunctionalInterface interface Run{ boolean run(int x); static void test(){} }
有关程序的异常:
异常:
程序无法正常执行完毕
异常体系: Throwable / \ Error Exception
Error : 错误,一般由虚拟机生成并脱出,无需要程序猿管理 Exception : 异常 CheckedException 编译时异常|检查时异常: 发生在程序编译期间 程序如果遇到编译时异常没有处理,程序无法正常运行 RuntimeException 运行时异常 : 发生程序运行期间 一般可以通过增强程序健壮性的代码处理 if
注意 :
如果程序遇到异常没有处理,无法继续执行
常见的一些运行时异常: 1.空指针异常 NullPointerException 2.数组越界异常 ArrayIndexOutOfBoundsException 3.数组长度负数异常 NegativeArraySizeException 4.类型转换异常 ClassCastException 5.数学异常 ArithmeticException 6.数字格式异常 NumberFormatException
public class Class001_Exception { public static void main(String[] args) { int i = -3; //增强程序健壮性的代码 if(i>0){ int[] arr = new int[i]; System.out.println(arr[5]); } Object obj = new String(); if(obj instanceof Person){ Person p = (Person)obj; } //System.out.println(5/0); String str = "12abc3"; //System.out.println(Integer.valueOf(str)); //InputStream is = new FileInputStream(""); } } class Person{}
异常处理方案: 异常抛出 : throws 把异常抛出到上一层,谁调用谁解决 异常捕获 : try..catch try{ 有可能出现异常的代码; }catch(FileNotFoundException e){ 处理异常代码; }catch(NullPointerException e){ 处理异常代码; }catch(Exception e){ 所有异常都能接收; }finally{ 无论try中是否会出现异常,都会执行finally中的代码 //资源的关闭等代码 }
一个try的后面可以接 1~n个catch try中如果一旦出现异常,try下面的代码不会执行,直接进入catch的判断 catch从上到下一次判断,满足哪一个catch捕获的类型,就执行对应的语句体 异常一旦捕获,程序执行过程中出现的异常按照指定方案解决,不会影响后续代码的执行
public class Class002_Exception { public static void main(String[] args) { System.out.println("主方法开始了"); //异常捕获 try{ System.out.println("try开始了"); //System.out.println(5/0); test(); System.out.println("try结束了"); }catch (FileNotFoundException e){ System.out.println("这是文件未找到异常"); e.printStackTrace(); }catch (Exception e){ e.printStackTrace(); }finally { System.out.println("最终的代码无论是否出现异常都会执行"); } System.out.println("主方法结束了"); } public static void test() throws FileNotFoundException { InputStream is = new FileInputStream("D:\\AAA\\DDD\\haha.txt"); } }
自定义异常: 了解 自定义的异常类型 所有自定义的异常类型必须直接或者间接继承自Exception 如果自定义异常为运行时期异常,需要直接或者间接的继承自RuntimeException throw 制造异常
public class Class003_DefinedException { public static void main(String[] args) { User user = new User(); user.setUsername("zhangsan"); int age = 8; //增强程序健壮性 /*if(age>=18 && age<=100){ user.setAge(age); }*/ try { user.setAge(28); } catch (AgeException e) { try { user.setAge(18); } catch (AgeException ageException) { ageException.printStackTrace(); } } System.out.println(user); } } //自定义异常 class AgeException extends Exception{ public AgeException() { } public AgeException(String message) { super(message); } } class User{ private String username; private int age; public User() { } public User(String username, int age) { this.username = username; this.age = age; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public int getAge() { return age; } public void setAge(int age) throws AgeException { if(age<18 || age>100){ throw new AgeException(age+"不合法"); } this.age = age; } @Override public String toString() { return "User{" + "username='" + username + '\'' + ", age=" + age + '}'; } }