什么是内部类
内部类作用
内部类分类
1.成员内部类
实例成员内部类
静态成员内部类
2.局部内部类
3.匿名内部类
内部类与外部类的联系
1、内部类是一个编译时概念,编译后外部类及其内部类会生成两个独立的class文件: OuterClass.class和OuterClass$InnerClass.class
2、内部类可以直接访问外部类的元素,但是外部类不可以直接访问内部类的元素
3、外部类可以通过内部类引用间接访问内部类元素
4、对于静态内部类来说,静态内部类是不依赖于外部类的,也就说可以在不创建外部类对象的情况下创建内部类的对象。另外,静态内部类是不持有指向外部类对象的引用的
1.成员内部类
文件类型:外部文件名$内部文件名.class
1.1 实例内部类
定义:
class a{
class aa{}
}
package com.test.niebulei;
import com.test.niebulei.A.Aa;
class A{
private int i = 99;
class Aa{
int num = 88;
public void ff(){
// 1. 内部类中访问外部类的数据
System.out.println(i);
}
public void cc(){
System.out.println("这是愉快的额一天");
}
}
public void f(){
Aa aa = new Aa();
System.out.println("nihao ");
aa.ff();
}
}
public class TestSL {
public static void main(String[] args) {
// TODO Auto-generated method stub
A a = new A();
a.f();
Aa aa = a.new Aa();
aa.ff();
aa.cc();
System.out.println();
}
}
上述代码可以看出,内部类可以直接使用外类的属性。
1. static final 编译期能确定数据 的 除外;
2.创建对象使用;
3.this ,外部类.this
package com.test.niebulei;
import com.test.niebulei.A.Aa;
class A{
private int i = 99;
static int w = 88;
class Aa{
int num = 88;
int w = 11;
public void ff(){
int w = 22;
System.out.println(this.w);
// 1. 内部类中访问外部类的数据
System.out.println(w);
System.out.println(new A().w);
//f();
}
public void cc(){
System.out.println("这是愉快的额一天");
}
}
public static void f(){
new A().new Aa().cc();
System.out.println(new A().i);
System.out.println(w);
}
}
public class TestSL {
public static void main(String[] args) {
// TODO Auto-generated method stub
A a = new A();
a.f();
Aa aa = a.new Aa();
aa.ff();
// aa.cc();
//
// System.out.println();
}
}
上述代码:外部类的静态方法不能直接访问内部类的成员属性,非静态的也是要创建对象才能访问。静态的需要new 外部类对象.内部类对象.内部类属性。
1.2静态内部类
定义:
静态内部类的创建是不需要依赖于外围类,可以直接创建
静态内部类不可以使用任何外围类的非static成员变量和方法,而内部类则都可以
package com.test.niebulei;
import com.test.niebulei.B.Bb;
class B{
private int q= 4;
static int e = 7;
public void f(){
System.out.println("外部类方法");
System.out.println(new B().q);
System.out.println(e);
new Bb().ff();
new Bb().f1();
}
static class Bb{
int i = 9;
static int s = 7;
public void ff(){
System.out.println("内部类方法");
System.out.println(new B().q);
System.out.println(e);
}
public static void f1(){
System.out.println("内部类静态方法");
System.out.println(new B().q);
System.out.println(e);
}
}
}
public class TestJN {
public static void main(String[] args) {
// TODO Auto-generated method stub
B b = new B();
b.f();
B.Bb.f1();
Bb bb = new Bb();
bb.ff();
bb.f1();
}
}
2.局部内部类
字节码文件名:
外部类名$N内部类名.class
package com.test.niebulei;
public class TestJB {
//局部内部类
public static void main(String[] args) {
// TODO Auto-generated method stub
class Base{
int x = 99;
public void bb(){
System.out.println("这是一个局部内部类");
}
}
class Sub extends Base{
int y = 1;
public void ss(){
System.out.println(y);
}
}
Sub sub = new Sub();
int i = new Base().x + new Sub().y;
System.out.println(i);
System.out.println(sub.x);
System.out.println(sub.y);
}
}
3.匿名内部类
字节码文件名:
外部类类名$N.class
匿名内部类其实就是一个没有名字的方法内部类,所以它符合方法内部类的所有约束,初次之外,还有一些地方需要注意:
匿名内部类是没有访问修饰符的。
匿名内部类必须继承一个抽象类或者实现一个接口
匿名内部类中不能存在任何静态成员或方法
匿名内部类是没有构造方法的,因为它没有类名。
一般使用匿名内部类的场景是,要继承或实现的接口只有一个抽象方法:
1.匿名内部类 必须 以匿名内部子类 或者 实现类的方式存在(二选一);
2匿名内部类 不能定义构造,但是可以定义构造块;
3.匿名内部类 创建对象时可以调用父类构造,可以给父类构造传递参数。
package com.test.niebulei;
class Base{
Base(int n){
System.out.println(n);
}
public void f(){
System.out.println("haha ");
}
//class Sub extends Base{
// public void f(){
// System.out.println("我重写了这个方法");
// }
}
public class TestNM {
public static void main(String[] args) {
// TODO Auto-generated method stub
// TestNM tn = new TestNM();
// tn.base.f();
new Base(55){
public void method(){
}
public void f(){
System.out.println("重写了这个方法 ");
}
}.method();
}
// Base base = new Base(9){
// {
// System.out.println("构造快");
// }
// public void method(){
//
// }
// public void f(){
// System.out.println("重写了这个方法 ");
//
// }
//};
}
// Sub sub = new Sub();
// sub.f();
// Base base = new Base();
// base.f();
// new Base().f();
父类是抽象类:
package com.test.niebulei;
abstract class Q{
public void ff(){
}
}
public class TestCN {
// Q q= new Q(){
// public void ff(){
// System.out.println("重写了ff方法");
// }
// };
public static void main(String[] args) {
// TODO Auto-generated method stub
TestCN t = new TestCN();
//t.q.ff();
new Q(){
public void ff(){
System.out.println("重写了ff方法");
}
}.ff();
}
}
实现一个接口;
package com.test.niebulei;
interface AA{
void kk();
}
public class TestJk {
public static void main(String[] args) {
// TODO Auto-generated method stub
//TestJk testJk = new TestJk();
new AA(){
@Override
public void kk() {
// TODO Auto-generated method stub
System.out.println("实现了这个方法");
}
}.kk();
}
}
区分两个接口中同名的抽象方法:
package com.test.niebulei;
interface AA{
void kk();
}
interface BB{
void kk();
}
//区分两个接口中同名的抽象方法:
public class TestJk {
public static void main(String[] args) {
// TODO Auto-generated method stub
//TestJk testJk = new TestJk();
new AA(){
@Override
public void kk() {
// TODO Auto-generated method stub
System.out.println("这是重写AA的方法");
}
}.kk();
new BB(){
@Override
public void kk() {
// TODO Auto-generated method stub
System.out.println("这是重写BB的方法");
}
}.kk();
}
}
五、函数式接口
函数式接口:接口中抽象方法的个数只有一个的方法。
语法:
六、Lambda表达式
Lambda 只能 实现 函数式 接口。
语法:
package com.test.niebulei;
@FunctionalInterface
interface La{
// 1) 无参无返回值
// void af();
//void af();
// 2) 无参带返回值
//String af();
// 3) 带参不带返回值
//void af(int n1, int n2);
// 4) 带参 带返回值
int af(int n,int n1);
}
public class TestHJK {
// 3. Lambda表达式
// 1) 无参无返回值
//Ca a = (n)-> n;
//La la = ()->{System.out.println("af");};
// 2) 无参带返回值
// La la2 = ()->{return "hello";};
// La La3 = ()->"hello";// 只有一行代码,而且是return语句,可以省略return 关键字
// 3)带参不带返回值
// La la4 = (num1,num2)->{System.out.println(num1 + num2);};
La la5 = (n,n1)->{System.out.println(n+n1);return n;};
// 4) 带参 带返回值
public static void main(String[] args) {
// TODO Auto-generated method stub
TestHJK t = new TestHJK();
t.la5.af(4,7);
}
}