一、内部类
1.成员内部类
1.1实例内部类
需要注意的地方:
-
实例内部类内部不允许定义任何静态内容
(内部类是归对象所有(和成员变量同一级别),static静态的是归类所有) -
外部类静态方法中不能直接访问实例内部类数据
-
如果外部类成员变量、内部类成员变量、内部类方法中局部变量同名
class Outer1{
static int snn = 22;
public static void sf() {
//静态方法可以直接访问静态成员
System.out.println(snn);
//2.外部类静态方法不能直接访问实例内部类数据(2.可以创建对象访问)
new Outer1().new Inner1().show();
}
class Inner1{
//static int snn = 22;//1.报错:实例内部类中不允许定义任何静态内容
//1.任何内部类中都可以static final的常量(因为编译期就能确定常亮的值)
static final int sn = 11;
public void show () {}
}
}
----------------------------------------------------
class Outer2{
int n = 11;
class Inner2{
int n = 22;
public void show() {
int n =33;
//3.区分
System.out.println(n);//33
System.out.println(this.n);//22
System.out.println(Outer2.this.n);//11
}
}
}
基本使用语法
//外部类(顶级类)
class Outer{
//类中的成员归对象所有(成员变量、构造器、内部类)
private int n;
public Outer(int n) {
this.n = n;
}
public void function() {
//2.外部类使用内部类的数据,需要穿件对象使用
Inner inner = new Inner("hello");
inner.method();
System.out.println("我是外部类的方法!");
}
//内部类(实例成员内部类):它是类中的成员,属于外部类对象,用外部类对象调用
class Inner{
private String s;
public Inner(String s) {
this.s = s;
}
public void method() {
//1.内部类中可以直接访问外部类的成员。
//因为每一个内部类对象中 都隐含了一个外部类对象
System.out.println(s+","+Outer.this.n);//写全了
System.out.println(s+","+n);//简写
}
}
}
public class TestInner1 {
public static void main(String[] args) {
//3.在其他顶级类中,只能创建内部类对象使用
//创建外部类对象
Outer outer = new Outer(111);
//在外部类的基础上创建内部类对象
Outer.Inner inner = outer.new Inner("aaa");
//new Outer(111).new Inner("ccc").method();
inner.method();//aaa,111
}
}
1.2静态内部类
顶级类不能用static修饰。
遵循静态方法的使用原则,属于外部类所有
注意:它是一个类,只有在主动使用的时候才会加载,才会初始化。
基本使用语法:
//外部类(顶级类)
class Souter1{
private int n =11;
private static int sn = 22;
public void fun() {//实例
new Sinner1().method();//建对象访问
Sinner1.smethod();//
}
public static void sfun() {//静态
new Sinner1().method();//建对象访问
Sinner1.smethod();//
}
//静态成员内部类
static class Sinner1{
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 Souter1().n);//建对象访问
}
public static void smethod() {//静态方法
System.out.println(snum);//直接访问
System.out.println(new Sinner1().num);//建对象访问
System.out.println(sn);//直接
System.out.println(new Souter1().n);//间接访问
}
}
}
public class TestStaticInner {
public static void main(String[] args) {
//静态内部类的静态成员
Souter1.Sinner1.smethod();
//静态内部类的实例成员
Souter1.Sinner1 inner1 = new Souter1.Sinner1();
inner1.method();
}
}
2.局部内部类
定义: 在方法里面声明一个类,在方法中使用是有效的。
可以继承
字节码文件:外部类类名$N内部类类名.class(N是避免命名冲突)
注意:
- 局部内部类不能声明静态成员
- 局部内部类处于静态方法中只能直接访问外部类静态成员
- 局部内部类处于实例方法中可以直接访问外部类静态成员和实例成员
3.匿名内部类
匿名对象: 当类只使用一次的时候,可以用匿名内部类的方式使用(要么是子类,要么是实现类)
注意:
1.必须实现一个类或一个接口
2.不能定义静态数据
3.不能定义父类构造(可以定义构造块)
4.不能是抽象的
1.匿名内部子类(父类是普通类)的基本语法:
//父类
class Parent1{
private String s;
public Parent1(String s) {
this.s = s;
System.out.println("父类构造:"+s);
}
public void func () {
System.out.println("Perent");
}
}
public class TestNonameInner {
//2.匿名内部子类的语法二:是一个多态的形式,父类引用指向了子类对象
//static可以修饰(可以调用父类构造)
static Parent1 p1 = new Parent1("hello") {
{
System.out.println("可以定义:构造块");
}
@Override
public void func() {
System.out.println("child111");
}
public void show() {}//子类特有的属性和行为不能实现
};
public static void main(String[] args) {
/*Child child = new Child();
child.func();*/
/** 匿名内部类 没有名字(要么是子类,要么是实现类)
* new Parent1()用来创建一个(Parent1子类)的对象
* Parent1是用来标识匿名内部类的,创建的是子类,并且是子类得对象
* {大括号里面是匿名内部类的类体部分(定义成员、方法)}
* new Parent1(){}.调方法(它也是对象)
*/
//1.匿名内部子类的语法一+调用
/*new Parent1() {
@Override
public void func() {
System.out.println("child");
}
}.func();*/
//2.语法二的调用
TestNonameInner aa = new TestNonameInner();
aa.p1.func();
}
}
2.匿名内部子类(父类是抽象类)的基本语法:
//抽象类
abstract class Base{
//抽象方法
public abstract void af();
}
public class TestNonameInner1 {
public static void main(String[] args) {
//匿名内部子类语法(父类是抽象类)
new Base() {
@Override
public void af() {
System.out.println("af");
}
}.af();
}
}
3.匿名内部子类(父类是接口)的基本语法:
interface Info{
void af();//抽象方法
}
public class TestNonameInner2 {
//2.匿名内部实现类语法二(给对象起了一个名字)既是一个匿名内部实现类,又是一个匿名内部实现类对象
Info info = new Info() {
@Override
public void af() {
System.out.println("我是af方法");
}
};
public static void main(String[] args) {
//1.语法一
new Info() {
@Override
public void af() {
System.out.println("我是af方法");
}
}.af();
}
}
二、函数式接口
抽象方法的个数只有一个的接口是函数式接口
作用: 通常作为参数来传递
//接口(是一个接口,也是一个函数式接口)
@FunctionalInterface//注解
interface Info{
//成员
//int sn = 11;//常量 public static final
void af();//抽象方法 public abstract
//default void df() { };//(default方法:可以有方法体) public
//static void sf() {}//静态方法
//class Inner{}//public static(静态内部类)
//interface IA {}//public static(接口)
//enum Color{};//public static(枚举:底层是类)
}
//1.定义(老方法)
class InfoImpl implements Info{
@Override
public void af() {}
}
public class TestLamdal {
public static void main(String[] args) {
//1.使用
InfoImpl info = new InfoImpl();
info.af();
//2.定义+使用(内部类)
new Info() {
@Override
public void af(){}
}.af();
}
}
三、Lambda表达式
作用: 实现接口的。可读性差(只能实现函数式接口)
//函数式接口(只能有一个抽象方法)
interface La{
//void af1();//1.无参无返回值
//int af2();//2.无参带返回值
//void af3(int n1,int n2);//3.带参无返回值
int af4(int n3,int n4);//4.带参带返回值
}
public class TestLambd2 {
//1.无参无返回值
//La la1 = ()->{System.out.println("af1");};
//方法体中如果只有一行代码,可以省略掉大括号
//La la11 = ()->{System.out.println("af1");};
//2.无参带返回值
//La la2 = ()->{return 11;};//return语句必须写
//方法体中如果只有一行代码,又是return语句,可以省略return
//La la22 = ()->11;
//3.定义
//La la3 = (a1,a2)->{System.out.println(a1+a2);};
//4.定义
//La la4 = (n3,n4)->{return n3+n4;};
//La la5 = (n3,n4)->n3+n4;
public static void main(String[] args) {
//3.使用
//TestLambd2 test = new TestLambd2();
//test.la3.af3(11, 22);//33
//4.使用
//TestLambd2 test = new TestLambd2();
//System.out.println(test.la4.af4(33, 44));
/*内部类
new La() {
@Override
public void af() {}
};*/
}
}
Consumer:
四、异常处理
学会抛异常(比如:年龄、性别)