内部类定义:就是将类的定义放在另一个类的内部。
一. 内部类的创建
创建就直接将内部类的定义放在另一个类的内部就可以了。代码如下:
package Test_1;
public class Outer {
class Inner{
}
public Inner getInner(){
return new Inner();
}
public static void main(String[] args){
Outer o = new Outer();
Outer.Inner i = o.getInner();
}
}
需要注意的地方是:如果想从外部类的非静态方法之外的任意位置创建某个内部类的对象,那么就必须在main()中那样指明这个对象的类型:OuterClassName.InnerClassName
如果想要直接创建内部类对象,就需要.new语句
public class Outer {
public class Inner{}
public static void main(String[] args){
Outer o = new Outer();
Outer.Inner i = o.new Inner();
}
}
通过外部类的对象来创建内部类的对象;由于内部类对象在创建时会与外部类对象链接起来,所以不可能在创建外部类之前创建内部类的对象。但如果创建的是静态的内部类,那么就不需要对外部类对象的引lei类对象链接起来。
二 . 内部类的特殊之处:
作为内部类,它能够访问其他素有外部对象的所有成员,而不需要任何特殊条件,而且还拥有其外部类所有元素的访问权。强的不行。
内部类具有这个特性的原因是:当外部类的对象创建了一个内部类对象时,此内部类对象会秘密的捕获一个指向那个外部类对象的引用。因此在你通过内部类对象访问外部时,其实等同于外部类自己的对象进行访问。
以下是内部类访问外部类的例子:
package Test_1;
interface Selector{
boolean end();
Object current();
void next();
}
public class Sequence {
private Object[] items;
private int next = 0;
public Sequence(int size){
items = new Object[size];
}
public void add(Object x){
if(next < items.length)
items[next++] = x;
}
public static class content{
public content(String s){
this.s = s;
}
public String s;
public String toString(){
return s;
}
}
private class SequenceSelector implements Selector{
private int i = 0;
public boolean end(){return i == items.length;}
public Object current() { return items[i];}
public void next() { if(i < items.length) i++;}
}
public Selector selector(){
return new SequenceSelector();
}
public static void main(String[] args){
Sequence sequence = new Sequence(2);
sequence.add(new content("Hello"));
sequence.add(new content("world!"));
while(!selector.end()){
System.out.print(selector.current() + " ");
selector.next();
}
}
}
内部类SequenceSelector很轻松的就访问了外围的元素items。
注:但是在这里有一个问题是我在编写时发现的,搜索后找到了解决方法。就是大家在看到第二个ms。但是在这里有一个问题是我在编写时发现的,搜索后找到了解决方法。就是大家在看到第二个内部类content可以发现它在定义的时候定义为static静态的,这是为什么呢?因为在main()方法中我直接用new content()来实例化对象,通过add()方法添加到sequence中时,出现了报错(No enclosing instance of type Sequence is accessible. Must qualify the allocation with an enclosing instance of type Sequence (e.g. x.new A() where x is an instance of Sequence).)意思就是没有访问Sequence的内部类的实例,必须要分配一个合适的实例。在搜索了一下发现原因是,我写的内部类是动态的(public class定义),而在主程序public static void main()是静态的。在java中静态的方法无法直接调用动态类的方法。所以将content改为static问题得到解决。
三. 特殊的内部类用法
- 定义在方法中的内部类
interface Destination{
String readLabel();
}
public class test {
public Destination destination(String s){
class PDestination implements Destination{
private String label;
private PDestination(String whereTo){
label = whereTo;
}
public String readLabel(){
return label;
}
}
return new PDestination(s);
}
public static void main(String[] args){
test t = new test();
Destination d = t.destination("Hello World!");
}
}
该内部类的作用于只在方法中,在该方法以外都无法访问内部类
2. 在任意作用域使用内部类
public class test {
private void f(boolean b){
if(b){
class A{
A(){
System.out.println("A");
}
}
A a = new A();
}
}
public static void main(String[] args){
test t = new test();
t.f(true);
}
}
在任何作用域中都可以定义内部类,但是仅存于该作用域。
3.匿名内部类
interface Content{
int value();
}
public class test {
public Content content(){
return new Content(){
private int i = 1;
public int value(){
return i;
}
};
}
public static void main(String[] args){
test t = new test();
Content c = t.content();
}
}
匿名内部类的语法意思是:创建一个继承自Content的匿名内部类的对象。如果匿名内部类需要引用一个外部定义的对象时,需要用到final关键字。
interface Destination{
String readLabel();
}
public class test {
public Destination destination(final String dest,final float price){
return new Destination(){
private int cost;{
cost = Math.round(price);
if(cost > 100){
System.out.print("Over Budget!");
}
}
private String label = dest;
public String readLabel(){
return label;
}
};
}
public static void main(String[] args){
test t = new test();
Destination d = t.destination("Hello", 101);
}
}
上例展示了通过外部对象,初始化内部匿名类。由于匿名类没有名字,也就是没有构造器,所以实例初始化就是它的构造器。