内部类
1 概述
如果一个类存在的意义就是为指定的另一个类,可以把这个类放入另一个类的内部。就是把类定义在类的内部的情况就可以形成内部类的形式。
A类中又定义了B类,B类就是内部类。B类可以当做A类的一个成员看待。
2 特点
1、 内部类可以直接访问外部类中的成员,包括私有成员
2、 外部类要访问内部类的成员,必须要建立内部类的对象
3、 在成员位置的内部类是成员内部类
4、 在局部位置的内部类是局部内部类
3 成员内部类
被private修饰
package cn.tedu.inner;
//测试内部类被private修饰
public class Test5_InnerClass2 {
public static void main(String[] args) {
//TODO 创建内部类对象,并执行show()
// Outer2.Inner2 oi = new Outer2().new Inner2();//报错,Inner2已经被private了
//3,测试被private的内部类的资源能否执行!
new Outer2().test();
}
}
class Outer2{
//2,如果想要访问private的内部类,可以访问外部类提供的对应方法
public void test() {
//访问内部类方法
new Inner2().show();
}
//位置在类里方法外--成员内部类
//1,内部类可以被private修饰,但是外界无法直接创建对象了!
private class Inner2{
public void show() {
System.out.println("Inner2.show()");
}
}
}
被static修饰
package cn.tedu.inner;
//测试内部类被static修饰
public class Test6_InnerClass3 {
public static void main(String[] args) {
// 创建内部类对象测试show()
// Outer3.Inner3 oi = new Outer3().new Inner3();//报错,原因是Inner3是静态的内部类
Outer3.Inner3 oi = new Outer3.Inner3();//Outer3.Inner3通过类名.调用类中的静态资源
oi.show();
Outer3.Inner3.show2();//调用静态内部类里的静态方法
}
}
class Outer3{
//1,内部类被static修饰--随着类的加载而加载,会造成内存资源浪费,并不常用!
static class Inner3{
public void show() {
System.out.println("Inner3.show()");
}
static public void show2() {
System.out.println("Inner3.show2()");
}
}
}
4 局部内部类
package cn.tedu.inner;
//测试局部内部类
public class Test7_InnerClass4 {
public static void main(String[] args) {
//创建对象测试test()的执行
Outer4 out = new Outer4();
out.show();
}
}
class Outer4{
public void show() {
//位置如果在方法里--局部内部类--减少类的作用范围,提高效率节省内存,不常见!
class Inner4{
public void test() {
System.out.println("Inner4.test()");
}
}
//触发内部类的功能
new Inner4().test();
}
}
5 匿名内部类
匿名内部类属于局部内部类,并且是没有名字的内部类。
通常使用 局部内部类 + 匿名对象完成
package cn.tedu.inner;
//测试匿名内部类
public class Test8_InnerClass5 {
public static void main(String[] args) {
new Hello() {// 匿名对象,本身接口不能new,这里new Hello()匿名对象,就相当于Hello接口的实现类
// 匿名内部类
@Override
public void save() {
System.out.println("save()..");
}
@Override
public void update() {
System.out.println("update()..");
}
}.update();// 触发指定的方法
new Hello2() {//抽象类的匿名内部类
@Override
public void show() { }
}.show();
new Animal() {//普通类的匿名内部类
@Override
public void eat() { }
};
}
}
//TODO 创建匿名对象+匿名内部类测试
class Animal{
public void eat() {}
}
abstract class Hello2 {
abstract public void show();
public void delete() { }
}
// 定义接口
interface Hello {
void save();
void update();
}
package cn.tedu.inner;
//测试 匿名内部类--匿名对象+局部内部类
//好处: 优化程序的继承结构
public class Test1 {
public static void main(String[] args) {
//TODO 1, 直接创建接口对象--这个匿名对象没名字,一次只能执行一个任务
new A(){
//匿名内部类--直接创建接口的对象,并在匿名内部类里重写抽象方法
@Override
public void save() {
System.out.println("数据增加成功");
}
}.save();//调用指定的方法
//jdk1.8提供的lambda表达式
A a = ()->{ System.out.println("数据增加成功");} ;
a.save();
//TODO 2, 直接创建接口对象--b是这个对象的名字,可以用b执行好几个任务
B b = new B(){
//匿名内部类--直接创建接口的对象,并在匿名内部类里重写抽象方法
@Override
public void save() {
System.out.println("save");
}
@Override
public void delete() {
System.out.println("delete");
}
};
b.save();
b.delete();
//TODO 3, 直接创建抽象类对象--需要重写所有抽象方法,至于普通方法想改才重写
new C(){
@Override
public void save(){
System.out.println("save..");
}
}.save();
}
}
abstract class C{
//抽象类里的方法可以是普通的或者是抽象的
public abstract void save();
public void get(){
System.out.println("get");
}
}
interface B{
void save();//public abstract void save();
void delete();
}
interface A{
void save();//public abstract void save();
}
2, 使用接口
//class B implements A{
// //3,实现了接口后,需要重写接口里的 所有抽象方法,否则是一个抽象类
// @Override
// public void save() {
// System.out.println("save");
// }
//}
6 -jdk1.8 Lambda 表达式,函数式接口
package cn.tedu;
//jdk8 Lambda表达式
//要求: 只针对接口可以使用, 而且接口里只能有一个抽象方法
//好处: 优化了匿名内部类的使用 -- 函数式编程
public class Test_JDK8 {
public static void main(String[] args) {
//TODO 1, 使用匿名内部类测试
A a = new A(){//匿名对象+匿名内部类
@Override
public void save() {//重写抽象方法
System.out.println("save..");
}
};
a.save();//方法调用
//TODO 2, 使用Lambda表达式优化匿名内部类
//语法: ( 参数列表 ) -> { 方法体 }
A a2 = ( ) -> { System.out.println("hello"); } ;
a2.save();
//TODO B--B接口里的get(int id)是需要参数的
B b = ( int m ) -> { System.out.println("get::"+m); } ;
b.get(1000);//把1000交给m
//TODO C--C接口的int delete(String id)需要参数有返回值
//方法的返回值通过return关键字
C c = ( String n ) -> { return 100; } ;
//把"jack"交给n,x保存返回来的100
int x = c.delete("jack");
System.out.println(x);
}
}
//TODO 提供接口
interface C{
int delete(String id);
}
interface B{
void get(int id);
}
interface A{
void save();
}