java 内部类和外部类的关系

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 内部类和外部类的关系相关的知识,希望对你有一定的参考价值。

一般内部类(非静态内部类)可以直接访问外部类的private成员。反过来则不行。那public成员是能相互访问的吧?还有静态类是什么个情况,百度了一下没搞清楚,求指教
还有外部类和内部类的关系,如果A是B是外部类,那创建B对象的时候,肯定有一个A的对象让B寄存吧?那能够使用A.B.方法吗?

以下通过代码来展现内部类与外部类的关系:

public class OutClassTest
private String o1 = "外部类的变量111";
private static String o2 = "外部类的静态变量222";
public void outMethod()

System.out.println( "外部类的方法。" );


/* public C c = new C();外部类根本不知道局部内部类的存在,所以访问不了 */

class InClassTest
public String i1 = "222";
A a = new A();
InClassTest2 test2 = new InClassTest2();

/**
* 非静态内部类可以直接访问所有的外部类的成员
*/
public void inMethod()

System.out.println( "非静态内部类的方法。" );
outMethod();
System.out.println( o1 );
System.out.println( test2.i2 );
System.out.println( a.a );



class InClassTest2
public String i2 = "333";


public static class A
public int a = 10;
public static int b = 100;

/* InClassTest inClassTest=new InClassTest(); */
public void aMethod()

System.out.println( "静态内部类的方法。" );
B b = new B();

/**
* 静态内部类可直接访问外部类的静态成员,但不能直接访问外部类的非静态成员,需要实例化
*/
System.out.println( o2 );

OutClassTest outClassTest = new OutClassTest();
outClassTest.outMethod();
System.out.println( outClassTest.o1 );



public static class B
public int a = 20;
public static int b = 200;


public void cMethod()

/**
* 局部内部类跟实例内部类一样能访问外部类的所有成员
* @author Administrator
*
*/
class C
private int a = 30;
public int aa = 300;



public static void main( String[] args )

OutClassTest out = new OutClassTest();
out.outMethod();

/**
* 在外部类中不能直接访问内部类的成员,必须通过内部类的实例才可访问
*/
OutClassTest.InClassTest test = new OutClassTest().new InClassTest();

/*
* 外部类中可直接访问静态内部类中的静态变量,若要访问静态内部类中非静态变量则需要实例化才行
*/
System.out.println( A.b );

OutClassTest.A in = new OutClassTest.A();
in.a = 1000;
System.out.println( "" + in.a );

参考技术A 内部类 可以访问外部类的private,因为内部类其实是外部类的一部分,你可以认为内部类是外部类的一个属性。反过来就不行。静态类,就是不需要实现,就可以直接调用内部的静态属性以及方法的类。追问

静态类是不是就相当于类本身了?能随便调用咯?

追答

额,虽然这样说不是很恰当,但是,你可以这么认为。调用也仅仅只能调用,非私有的,静态的属性或方法。

本回答被提问者采纳

Java内部类和匿名内部类的用法

Java内部类和匿名内部类的用法
思考?内部类如何使用?静态内部类相比于实例内部类的开销2222222222
一、内部类:
为什么会有内部类?
1.若内部类无同名方法可以直接调用外部类的方法。
2. 如果内部类有同名方法必须使用"OuterClass.this.MethodName()格式调用(**其中OuterClass与MethodName换成实际外部类名及其方法;this为关键字,表示对外部类的引用);
3. 但外围类无法直接调用内部类的private方法,外部类同样无法直接调用其它类的private方法。注意:内部类直接使用外部类的方法与该方法的权限与是否static无关,它取决于内部类是否有同名方法。

public class OuterClass {
        private void outerMethod() {
            System.out.println("It's Method of OuterClass");
        }
        public static void main(String[] args) {
            OuterClass t = new OuterClass();
            OuterClass.Innerclass in = t.new Innerclass();
            in.innerMethod();
        }
        class Innerclass {
            public void innerMethod() {
                OuterClass.this.outerMethod();// 内部类成员方法与外部类成员方法同名时,使用this调用外部类的方法
                outerMethod();// 内部类没有同名方法时执行外部类的方法
            }
            private void outerMethod() {
                System.out.println("It's Method of Innerclass");
            }
        }
    }

运行结果:
It’s Method of OuterClass
It’s Method of Innerclass
(2)内部类访问外部类的变量必须声明为final

  1. 方法中的局部变量,方法结束后这个变量就要释放掉,final保证这个变量始终指向一个对象。
  2. 首先,内部类和外部类其实是处于同一个级别,内部类不会因为定义在方法中就会随着方法的执行完毕而跟随者被销毁.
  3. 问题就来了如果外部类的方法中的变量不定义final那么当外部类方法执行完毕的时候,这个局部变量肯定也就被GC了,然而内部类的某个方法还没有执行完,这个时候他所引用的外部变量已经找不到了。
  4. 如果定义为final,java会将这个变量复制一份作为成员变量内置于内部类中,这样的话,由于final所修饰的值始终无法改变,所以这个变量所指向的内存区域就不会变。
 public class OuterClass {
	int num1 = 0;// 成员变量
    private void outerMethod() {
		int num2 = 0;// 方法内的局部变量
		class Innerclass_1 {
			public void innerMethod() {
				System.out.println(num1);// 方法中内部类的方法,可以正常访问外部类的成员变量
				System.out.println(num2);// JDK1.8以前,方法中内部类的方法,不能直接访问外部类的方法的局部变量,必须声明为final
			}
		}
	}
}

如果使用JDK1.8以前的版本,Eclipse会出现如下错误提示:
在这里插入图片描述
(3)内部类的实例化
内部类实例化不同于普通类,普通类可以在任意需要的时候实例化,而内部类必须在外层类实例化以后方可实例化,并与外部类建立关系
因此在外部类中的非static方法中,是可以实例化内部类对象

	private void outerMethod() {
		System.out.println("It's Method of OuterClass");
		Innerclass in = new Innerclass();//在外部类的outerMethod方法中实例化内部类是可以啊
	}

但在static方法中,就要注意啦!!!! 不能在static方法中直接new内部类,否则出现错误:
No enclosing instance of type OuterClass is accessible. Must qualify the allocation with an enclosing instance of type OuterClass (e.g. x.new A() where x is an instance of OuterClass).
这是因为静态方法是在类实例化之前就可以使用的,通过类名调用,这时动态内部类都还没实例化呢,怎么用,总不能调用一个不存在的东西吧。
如果想在Static方法中new内部类,可以把内部类声明为Static

public class OuterClass {
	private void outerMethod() {
		System.out.println("It's Method of OuterClass");
	}
 
	public static void main(String[] args) {
		Innerclass in = new Innerclass();
		in.innerMethod();
	}
 
	static class Innerclass {//把内部类声明为static
		public void innerMethod() {
			System.out.println("It's Method of innerMethod");
 
		}
	}
 
}

当然,一般不使用static的方式,而是推荐这种方法:x.new A() ,其中 x是外部类OuterClass的实例,A是内部类Innerclass

package innerclass;
public class OuterClass {
	private void outerMethod() {
		System.out.println("It's Method of OuterClass");
	}
	public static void main(String[] args) {
		OuterClass.Innerclass in = new OuterClass().new Innerclass();//使用x.new A()的方式
		in.innerMethod();
	}
	class Innerclass {
		public void innerMethod() {
			System.out.println("It's Method of innerMethod");
		}
	}
}

x.new A() ,其中 x是外部类OuterClass的实例,A是类部类Innerclass,当然可以拆分如下,这样就显然很明白啦:

public static void main(String[] args) {
  OuterClass out = new OuterClass();//外部实例
  OuterClass.Innerclass in = out.new Innerclass();//外部实例.new 外部类
  in.innerMethod();
}

4)什么情况下使用内部类
1.内部类继承自某个类或实现某个接口,内部类的代码操作创建其的外层类的对象。所以你可以认为内部类提供了某种进
入其外层类的窗口。
2.使用内部类最吸引人的原因是:每个内部类都能独立地继承自一个(接口的)实现,所以无论外层类是否已经继承了某个(接口的)实现,对于内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了“多重继承”。
(5)在静态方法中实例化内部类例子:(内部类放在静态方法中

package javatest2;
public class JavaTest2 {
	public static void main(String[] args) {
		class Boy implements Person {
			public void say() {// 匿名内部类自定义的方法say
				System.out.println("say方法调用");
			}
			@Override
			public void speak() {// 实现接口的的方法speak
				System.out.println("speak方法调用");
			}
		}
		Person per = new Boy();
		per.speak();// 可调用
		per.say();// 不能调用
	}
}
interface Person {
	public void speak();
}

font color=per.speak()可调用,而per.say()不能调用,这时因为per是Person对象,要想调用子类的方法,可以强制向下转型为:((Boy) per).say();或者直接改为Boy per = new Boy();。 从中可发现,要想调用内部类的自定义的方法,必须通过内部类的对象来调用。那么,匿名内部类连名字都没有,怎么调用内部类自定义的方法?
(二)匿名内部类
1, 匿名内部类也就是没有名字的内部类正因为没有名字
2.所以匿名内部类只能使用一次,它通常用来简化代码编写,但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口,但最多只能继承一个父类,或实现一个接口。
关于匿名内部类还有如下两条规则:
1)匿名内部类不能是抽象类,因为系统在创建匿名内部类的时候,会立即创建内部类的对象。因此不允许将匿名内部类定义成抽象类。
2)匿名内部类不等定义构造器(构造方法),因为匿名内部类没有类名,所以无法定义构造器,但匿名内部类可以定义实例初始化块
怎样判断一个匿名类的存在啊?看不见名字,感觉只是父类new出一个对象而已`,没有匿名类的名字。
先看段伪代码


class SonOne extends Father{
  ...       //这里的代码和上面匿名内部类,大括号中的代码是一样的
}
public class Test{
   Father f1 = new SonOne() ;
}

先看一个例子,体会一下匿名内部类的用法:在这里插入图片描述运行结果:eat something
可以看到,我们直接将抽象类Person中的方法在大括号中实现了,这样便可以省略一个类的书写。并且,匿名内部类还能用于接口上

public class JavaTest2 {
	public static void main(String[] args) {
		Person per = new Person() {
			public void say() {// 匿名内部类自定义的方法say
				System.out.println("say方法调用");
			}
			@Override
			public void speak() {// 实现接口的的方法speak
				System.out.println("speak方法调用");
			}
		};
		per.speak();// 可调用
		per.say();// 出错,不能调用
	}
}
 
interface Person {
	public void speak();
}

这里per.speak()是可以正常调用的,但per.say()不能调用,为什么呢?注意Person per = new Person()创建的是Person的对象,而非匿名内部类的对象。其实匿名内部类连名字都没有,你咋实例对象去调用它的方法呢?但继承父类的方法和实现的方法是可以正常调用的,本例子中,匿名内部类实现了接口Person的speak方法,因此可以借助Person的对象去调用。
若你确实想调用匿名内部类的自定义的方法say(),当然也有方法:
(1)类似于speak方法的使用,先在Person接口中声明say()方法,再在匿名内部类中覆写此方法。
(2)其实匿名内部类中隐含一个匿名对象,通过该方法可以直接调用say()和speak()方法;代码修改如下:


public class JavaTest2 {
	public static void main(String[] args) {
		new Person() {
			public void say() {// 匿名内部类自定义的方法say
				System.out.println("say方法调用");
			}
 
			@Override
			public void speak() {// 实现接口的的方法speak
				System.out.println("speak方法调用");
			}
		}.say();// 直接调用匿名内部类的方法
	}
}
interface Person {
	public void speak();
}

https://blog.csdn.net/guyuealian/article/details/51981163

以上是关于java 内部类和外部类的关系的主要内容,如果未能解决你的问题,请参考以下文章

java中内部类

Java的外部类和内部类+静态变量和非静态变量的组合关系

java 内部类和静态内部类的区别

java静态内部类

Java内部类

静态类和内部类的区别是啥