java 内部类为java提供的语法,有必要掌握,我这里是基于JDK8,版本不一样语法可能有变化,如final变化
内部类基本使用
定义内部类
public class Outer {
private int x = 10;
public void print() {
System.out.println(x);
}
public class Inner {
private int y = 2;
public void printXY() {
System.out.println(String.format("[%s,%s]", x, y));
x = 5;
y = 5;
System.out.println(String.format("[%s,%s]", x, y));
}
}
}
内部类的一些概念
- Outer为外部类,Inner为内部类。
- Inner可以直接使用Outer所有公有私有属性方法
- Inner内部类实例化对象必须依赖于Outer外部类实例化对象创建
实例化演示
public class OuterTest {
public static void main(String[] args) {
// 实例化外部类
Outer outer = new Outer();
outer.print();
// 通过外部类才能实例化内部类
Outer.Inner inner = outer.new Inner();
inner.printXY();
}
}
除了上述显示outer.new Inner()
创建,还可以隐式创建,添加生成内部类方法
public class Outer2 {
private int x = 10;
public void print() {
System.out.println(x);
}
public class Inner {
private int y = 2;
public void printXY() {
System.out.println(String.format("[%s,%s]", x, y));
x = 5;
y = 5;
System.out.println(String.format("[%s,%s]", x, y));
}
}
/**
* 隐式生成内部类
*/
public Inner inner() {
// return this.new Inner(); 实质上有一个this对象
return new Inner();
}
}
实例化演示
public class Outer2Test {
public static void main(String[] args) {
// 实例化外部类
Outer2 outer = new Outer2();
outer.print();
// 通过外部类才能实例化内部类
Outer2.Inner inner = outer.inner();
inner.printXY();
}
}
内部类实际使用例子一
当前使用内部类的作用是减少参数传递
,编写一个数组的迭代器
未使用内部类
数组集合
public class MyList {
private int index = 0;
private Object[] datas;
public MyList(int size) {
datas = new Object[size];
}
public void add(Object o) {
datas[index++] = o;
}
public int getIndex() {
return index;
}
public Object[] getDatas() {
return datas;
}
}
迭代器
import java.util.Iterator;
public class MyListIterator implements Iterator<Object>{
// 记录原始数据
private int index = 0;
private Object[] datas;
// 游标器
private int begin = 0;
public MyListIterator(MyList list) {
this.index = list.getIndex();
this.datas = list.getDatas();
}
@Override
public boolean hasNext() {
return begin < index;
}
@Override
public Object next() {
return datas[begin++];
}
}
测试代码
public class MyListTest {
public static void main(String[] args) {
// 创建对象并初始化数据
MyList list = new MyList(10);
list.add(1234);
list.add("张三");
list.add(11.22f);
// 转换为迭代器
Iterator<Object> iterator = new MyListIterator(list);
while (iterator.hasNext()) {
Object value = iterator.next();
System.out.println(value);
}
}
}
测试值
1234
张三
11.22
使用内部类
public class MyList2Iterator {
private int index = 0;
private Object[] datas;
public MyList2Iterator(int size) {
datas = new Object[size];
}
public void add(Object o) {
datas[index++] = o;
}
public Iterator<Object> iterator() {
return new InnerMyListIterator();
}
// 省略参数传递的代码,内部类可以直接使用外部类变量
// class 申明为private,类专用
private class InnerMyListIterator implements Iterator<Object>{
// 游标器
private int begin = 0;
@Override
public boolean hasNext() {
return begin < index;
}
@Override
public Object next() {
return datas[begin++];
}
}
}
测试代码
public class MyList2IteratorTest {
public static void main(String[] args) {
// 创建对象并初始化数据
MyList2Iterator list = new MyList2Iterator(10);
list.add(1234);
list.add("张三");
list.add(11.22f);
// 转换为迭代器
Iterator<Object> iterator = list.iterator();
while (iterator.hasNext()) {
Object value = iterator.next();
System.out.println(value);
}
}
}
匿名内部类构造函数
定义一个接口
public interface MyInterfaces {
void sayhello(String name);
}
无参数演示
public class Caller {
public MyInterfaces myInterfaces(int x) {
// 匿名内部类是没有构造函数的,这里是无参数传入
return new MyInterfaces() {
@Override
public void sayhello(String name) {
System.out.println(name + x);
}
};
}
public static void main(String[] args) {
Caller caller = new Caller();
MyInterfaces myInterfaces = caller.myInterfaces(1234);
myInterfaces.sayhello("王丽");
}
}
有参数赋值
package test.inner;
public class Caller {
public MyInterfaces myInterfaces(int x) {
// 匿名内部类是没有构造函数的,这里是无参数传入
return new MyInterfaces() {
private int y = x;
// 或者以下写法
/*{
y = x;
}*/
@Override
public void sayhello(String name) {
// x = 2; error 不属于外部类变量不允许内部类更改
y = 3;
System.out.println(name + x + y);
}
};
}
public static void main(String[] args) {
Caller caller = new Caller();
MyInterfaces myInterfaces = caller.myInterfaces(1234);
myInterfaces.sayhello("王丽");
}
}
嵌套类(静态内部类)
有层次关系的独立类
嵌套类定义
public class StaticInner {
private int x;
public static class Inner {
private int y ;
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
@Override
public String toString() {
// x = 2; error static 修饰可理解为StaticInner下独立的其他类
return y + "";
}
}
}
实例化
/**
*
* 两种没有除了层次关系没有任何联系
*/
public class StaticInnerTest {
public static void main(String[] args) {
StaticInner staticInner = new StaticInner();
StaticInner.Inner inner = new StaticInner.Inner();
}
}
内部类的继承
静态类的继承必须先实例化外部类
定义一个静态类
public class Outer {
private int x = 10;
public void print() {
System.out.println(x);
}
public class Inner {
private int y = 2;
public void printXY() {
System.out.println(String.format("[%s,%s]", x, y));
x = 5;
y = 5;
System.out.println(String.format("[%s,%s]", x, y));
}
}
}
继承演示
public class SubOuterInner extends Outer.Inner {
public SubOuterInner(Outer outer) {
// 下面这行代码必须有,不然报错
outer.super();
}
}
内部类与final关系
在jdk8中,内部类可以访问修改外部类的任何变量,但是不得修改外部类的方法入参,以及方法内定义的临时变量。jdk8不用显示使用final修饰
其中yyy = 22;
错误,不得修改外部类的方法入参z = 2342;
错误,方法内的临时变量
public class Outer3 {
private int x = 10;
public void print(int yyy) {
class Inner {
public void f() {
x = 11;
System.out.println(x);
// yyy = 22; error
// z = 2342; error
}
}
}
}
实际常发生的错误
以下代码错误,内部类修改方法内的临时变量
public class TestThread {
public void main(String[] args) {
int x = 11;
/**
* 定义一个匿名内部类
*/
Runnable runnabel = new Runnable() {
public void run() {
System.out.println(x);
// x = 1234; error
}
};
}
}
将局部变量声明到外部类变量即可修改,请注意
public class TestThread {
int x = 11;
public void main(String[] args) {
/**
* 定义一个匿名内部类
*/
Runnable runnabel = new Runnable() {
public void run() {
System.out.println(x);
x = 1234;
}
};
}
}
内部类多继承弥补
可以任意继承类数量
package test.inner;
class A{
public void f() {
System.out.println("f");
}
}
class B{
public void g() {
System.out.println("g");
x();
}
public void x() {
System.out.println("g");
}
}
// 继承A
public class Test extends A {
// 继承B
class TestB extends B {}
// 持有B对象的引用
B createB() {
return new TestB();
}
// test对象能够转换为A,B超类
public static void main(String[] args) {
Test test = new Test();
A a = test;
B b = test.createB();
}
}