文章目录
1.内部类
什么是内部类
内部类作用
内部类分类
1.成员内部类
1)实例成员内部类
2)静态成员内部类
2.局部内部类
3.匿名内部类
1.1 成员内部类
1.1.1 实例内部类
定义:
字节码文件名: 外部类名$内部类名.class
语法:
class Outer{
private int n;
public Outer(int n) {
this.n = n;
}
public void function() {
// 2. 外部类使用内部类的数据,需要创建对象使用。
Inner inner = new Inner("hello");
inner.method();
}
//内部类 :类中的成员 ,(属于对象)
class Inner{
private String s;
public Inner(String s) {
this.s = s;
}
public void method() {
// 1. 内部类中可以直接使用外部类的成员。
// Outer.this
// System.out.println(s + "," + Outer.this.n);
System.out.println(s + "," + n);
}
}
}
public class TestInner1 {
public static void main(String[] args) {
Outer outer = new Outer(111);
// outer.function();
// 3. 在顶级类中 创建内部类对象
Outer.Inner inner = outer.new Inner("xyz");
inner.method();
}
}
1.static final 可以
2.创建对象访问;
class Outer1{
static int snn = 22;
int n = 11;// new Outer1().n
public static void sf() {
//2 创建对象访问
new Outer1().new Inner1().show();
}
class Inner1{
//1
static final int sn = 11;
public void show() {
}
}
}
区分:
class Outer2{
int n = 11;
class Inner2{
int n = 22;
public void show() {
int n = 33;
// 区分
System.out.println(n);// 33
System.out.println(this.n);// 22
System.out.println(Outer2.this.n); // 11
}
}
}
public class TestInner3 {
public static void main(String[] args) {
// 匿名的外部类对象.new
Outer2.Inner2 inner = new Outer2().new Inner2();
inner.show();
}
}
1.1.2静态内部类
定义:
语法:
class SOuter{
private int n = 11;
private static int sn = 22;
public void func() {// 实例
new SInner().method();
SInner.smethod();// 调用静态的
}
public static void sfunc() {// 静态
new SInner().method();
SInner.smethod();// 调用静态的
}
// 静态成员内部类
static class SInner{
private int num = 111;
private static int snum = 222;
public void method() {// 实例
//自己
System.out.println(num);
System.out.println(snum);
//外部类的
System.out.println(sn);
System.out.println(new SOuter().n);//
}
public static void smethod() {// 静态
System.out.println(snum);// 直接
System.out.println(new SInner().num);// 对象
System.out.println(sn);
System.out.println(new SOuter().n);
}
}
}
public class TestStaticInner1 {
public static void main(String[] args) {
//静态内部类的静态成员
SOuter.SInner.smethod();
//静态内部类的实例成员
SOuter.SInner inner = new SOuter.SInner();
inner.method();
}
}
实例:
class SOuter1{
static int sn ;
static {
sn = 11;
System.out.println("外部类静态块:static _sn " + sn);
}
/**静态内部类*/
static class SInner1{
static String str = "hello";
static {
System.out.println("静态内部类静态块: SInner1");
}
}
}
public class TestSaticInner2 {
public static void main(String[] args) {
// System.out.println(SOuter1.sn);//
System.out.println(SOuter1.SInner1.str);
}
}
1.2 局部内部类
字节码文件: 外部类类名$N内部类类名.class
语法:
示例:
public class TestLocalInner1 {
public void f() {
//局部内部类
class Base{
}
}
public static void main(String[] args) {
int n = 11;// 局部变量
//局部内部类
class Base{
int num = 22;
}
class Sub extends Base{
String str = "hello";
}
Base base = new Base();
System.out.println(base.num);
Sub sub = new Sub();
System.out.println(sub.str + "," + sub.num);
}
}
1.3 匿名内部类
语法:
匿名内部子类:父类是普通类
class Parent{
private String str;
public Parent(String str) {
this.str = str;
System.out.println("父类构造:" + str);
}
public void func() {
System.out.println("parent");
}
}
public class TestNonameInner {
//方式二:
// 调用的是父类构造
static Parent p1 = new Parent("hello") {
{ // 可以
System.out.println("构造块");
}
@Override
public void func() {
System.out.println("child");
}
public void method() {System.out.println("method");}
};
public static void main(String[] args) {
// Child child = new Child();
// child.func();
// 匿名内部子类
语法二:
TestNonameInner test = new TestNonameInner();
// test.p1.method();
test.p1.func();
// TestNonameInner.p1.func();
语法一:
new Parent() {
@Override
public void func() {
System.out.println("child");
}
public void show() {System.out.println("show");}
}.show();
}
}
class Child extends Parent{
@Override
public void func() {
System.out.println("child");
}
}
匿名内部子类;父类是抽象类
//抽象类:
abstract class Base{
// 抽象方法
public abstract void af();
}
public class TestNonameInner2 {
public static void main(String[] args) {
// 匿名内部子类
new Base() {
@Override
public void af() {
System.out.println("af");
}
}.af();
}
}
匿名内部实现类:
interface Info1{
void af();// 抽象方法
}
public class TestNonameInner3 {
// 匿名内部实现类
Info1 info1 = new Info1() {
@Override
public void af() {
System.out.println("af");
}
};
public static void main(String[] args) {
new Info1() {
@Override
public void af() {
System.out.println("af");
}
}.af();
}
}
同名:
interface IA{
void af();// public abstract void af();
}
interface IB{
void af();
}
class IAIBImpl implements IA,IB{
@Override
public void af() {
System.out.println("af");
}
// IA 的匿名内部实现类
IA ia = new IA() {
@Override
public void af() {
System.out.println("Ia_af");
}
};
// IB的匿名内部实现类
IB ib = new IB() {
@Override
public void af() {
System.out.println("ib_af");
}
};
}
2.函数式接口
函数式接口:抽象方法的个数只有一个的接口。
语法:
3.Lambda表达式
实现接口:只能实现 函数接口。
语法:
interface La{
//1.无参无返回值
void af();
//2. 无参带返回值
int af();
//3. 带参 不带返回值
void af(int n1,int n2);
//4 带参带返回值
int af(int n1,int n2);
}
public class TestLambda2 {
//4带参带返回值
La la1 = (m1,m2)->{return m1 + m2;};
La la2 = (m1,m2)->m1 + m2;
// 3 带参 不带返回值
La la1 = (n1,n2)->{System.out.println(n1 + n2);};
//2 无参带返回值
La la1 = ()->{return 11;};
La la2 = ()->11;
// 1.无参无返回值
La la1 = ()->{System.out.println("af");};
La la2 = ()->System.out.println("af");
public static void main(String[] args) {
//使用
TestLambda2 test = new TestLambda2();
test.la1.af(11, 22);
new La() {
public void af() {System.out.println();}
}.af();
}
}
接口类型举例:
@FunctionalInterface
interface Info{
int sn = 11;//常量 public static final
void af();// 抽象方法 public abstract
default void df() { } //默认public
static void sf() {} // 静态
class Inner{} // public static
interface IA{}// public static
enum Color{};// public static 底层:类
}
@FunctionalInterface
interface Info{
void af();//
}
// 方式一:
class InfoImpl implements Info{
public void af() {}
}
public class TestLamda1 {
Info info = new Info() {
@Override
public void af() {
// TODO Auto-generated method stub
}
};
public static void main(String[] args) {
//方式一:
InfoImpl info = new InfoImpl();
info.af();
//方式二:
new Info() {
public void af() {}
}.af();
}
}
系统提供的函数式接口:
IntConsumer:
抽象方法:accept(int value) ;
作用: 对数组或集合的元素遍历操作。
Arrays.stream(arr).forEach(new IntConsumer() {
@Override
public void accept(int value) {
System.out.println("元素是:" + value);
}
});
简化:
Arrays.stream(arr).forEach(new IntConsumer() {
@Override
public void accept(int value) {
System.out.println("元素是:" + value);
}
});
//Lambda
Arrays.stream(arr).forEach( v -> {System.out.println(v);});
// 方法引用
Arrays.stream(arr).forEach(System.out::println);
4.异常处理
4.1 异常
4.2 异常分类
Error :错误。 通过代码解决不了。
Exception:异常。通过代码可以解决的。
分类:
1.运行时异常;
运行期出现的。
RuntimeException和RuntimeException的子类。
2.非运行时异常(受检异常);
编译期提示的必须处理的异常。
Exception类和部分子类。
4.3 常见的异常
异常实例一:
public class TestExceptionDemo1 {
public void b() {
int n1 = 5;
int n2 = 0;
int n3 = n1 / n2;
System.out.println(n3);
}
public void a() {
b();
}
public static void main(String[] args) {
TestExceptionDemo1 test = new TestExceptionDemo1();
test.a();
System.out.println("其他代码");
}
}
Exception in thread "main" java.lang.ArithmeticException: / by zero
at TestExceptionDemo1.b(TestExceptionDemo1.java:8)
at TestExceptionDemo1.a(TestExceptionDemo1.java:12)
at TestExceptionDemo1.main(TestExceptionDemo1.java:16)
请按任意键继续. . .
异常实例二:
import java.util.Scanner;
public class TestException3 {
public void show() {
Scanner input = new Scanner(System.in);
System.out.println("--输入两个数字:");
try {
int n1 = input.nextInt();
int n2 = input.nextInt();
int n3 = n1 / n2;
System.out.println("结果:" + n3);
}catch(ArithmeticException e) {
System.out.println("出错了,请与管理员练习");
// System.out.println(e);// e
}
System.out.println("其他代码……………………");
}
public static void main(String[] args) {
new TestException3().show();
System.out.println("很多代码");
}
}
--输入两个数字:
abc
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:864)
at java.util.Scanner.next(Scanner.java:1485)
at java.util.Scanner.nextInt(Scanner.java:2117)
at java.util.Scanner.nextInt(Scanner.java:2076)
at TestException3.show(TestException3.java:12)
at TestException3.main(TestException3.java:23)
请按任意键继续. . .
4.4 异常处理方式
1.try-catch
try{
可能会引发异常的代码
}catch(异常类型 异常对象){
处理
}
public class TestException3 {
public void show() {
Scanner input = new Scanner(System.in);
System.out.println("--输入两个数字:");
try {
int n1 = input.nextInt();
int n2 = input.nextInt();
int n3 = n1 / n2;
System.out.println("结果:" + n3);
}catch(ArithmeticException e) {
System.out.println("出错了,请与管理员练习");
// System.out.println(e);// e
}
System.out.println("其他代码……………………");
}
public static void main(String[] args) {
new TestException3().show();
System.out.println("很多代码");
}
}
4.4.2 注意事项
5.编写:实例内部类 显示整头牛的信息
class Cow{
private double height;
private double weight;
public Cow(double height, double weight) {
this.height = height;
this.weight = weight;
}
/**内部类:牛腿*/
private class CowLeg{
private String color;
private int length;
public CowLeg(String color, int length) {
this.color = color;
this.length = length;
}
public void display() {
System.out.println("牛腿的颜色:" + color + ",长度:" + length);
}
}
public void show() {
System.out.println("牛的高:" + height + "重:" + weight);
CowLeg leg = new CowLeg("黑白",50);
leg.display();
}
}
public class TestInnerCow_exam {
public static void main(String[] args) {
Cow cow = new Cow(100, 500);
cow.show();
}
}
牛的高:100.0重:500.0
牛腿的颜色:黑白,长度:50
请按任意键继续. . .
6.编写:静态内部类
class Library{
static class Book{
private String name;
private String author;
private double price;
public Book(String name, String author, double price) {
this.name = name;
this.author = author;
this.price = price;
}
@Override
public String toString() {
return "Book [name=" + name + ", author=" + author + ", price=" + price + "]";
}
}
public void managerBook(){
Book book = new Book("计算机基础", "郭靖", 66.6);
System.out.println("管理图书:");
System.out.println(book);
}
}
public class TestLibrary_exam {
public static void main(String[] args) {
Library library = new Library();
library.managerBook();
}
}
管理图书:
Book [name=计算机基础, author=郭靖, price=66.6]
请按任意键继续. . .
7.编写: 异常 给数组赋值
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.Scanner;
public class TestException2_exam {
public void method() {
Scanner input = new Scanner(System.in);
int [] arr = new int[5];
System.out.println("--给数组赋值:");
try {
for(int i = 0; i < arr.length; i++) {
arr[i] = input.nextInt();
}
Arrays.stream(arr).forEach(System.out::println);
} catch (InputMismatchException e) {
System.out.println("赋值出错了");
e.printStackTrace();
} catch (Exception e) {
System.out.println("赋值出错了");
System.out.println(e);
} finally {
System.out.println("程序运行结束");
}
}
public static void main(String[] args) {
new TestException2_exam().method();
}
}
8.编写:异常 给年龄赋值
class AgeException extends Exception{
private String message;
public AgeException(String message) {
this.message = message;
}
@Override
public String getMessage() {
// TODO Auto-generated method stub
return "message:" + message;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "String :" + message;
}
@Override
public void printStackTrace() {
System.out.println("print:" + message);
}
}
class Person{
private int age;
private String sex;// 男 和 女 SexException
public int getAge() {
return age;
}
/
* 给年龄赋值
* @param age 年龄值
* @throws AgeException 年龄赋值必须是18-65之间
/
public void setAge(int age) throws AgeException{
if(age >= 18 && age <= 65) {
this.age = age;
}else {
//引发异常
throw new AgeException("年龄必须是18-65之间");
}
}
public void setAge(int age) {
if(age >= 18 && age <= 65) {
this.age = age;
}else {
//引发异常
throw new RuntimeException("年龄必须是18-65之间");
}
}
/---------------------------------------------------------------
public void setAge(int age) throws Exception{
if(age >= 18 && age <= 65) {
this.age = age;
}else {
//引发异常
throw new Exception("年龄必须是18-65之间");
}
}
}
public class TestException4 {
public static void main(String[] args) {
Person guojing = new Person();
try {
guojing.setAge(222);
} catch (AgeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(guojing.getAge());
}
}
9. 注意:
1.接口与抽象类的不同点:
语法:
抽象类和接口中的成员不同
接口可以实现多继承
概念: 抽象类只定义了类的抽象行为,没有具体的实现相应的行为
接口是一组规则的封装
设计:接口是功能模块的连接,降低耦合
抽象类是一个模板,可以说是一个半成品,
子类可以继承父类的功能,也可以添加自己的功能
2.内部类隐藏在外部类之中
分类:成员内部类:实例成员内部类,静态成员内部类
局部内部类,匿名内部类
3.字节码文件名称:外部类名$内部类名.class
4.任何类型的内部类中都可以定义static final类型的常量
5.静态方法之中只可以使用静态成员
6.类必须在主动使用时才会加载,主动被调用才能加载
7.static final修饰的必须是在编译器能够确定的才可以,不能确定的变量是不行的
8.多态里子类独特的功能被屏蔽
9.函数式接口中的抽象方法的个数只有一个
10.Stream流速度快
11.Lambda只能引用函数式接口