`
peonyzzdx
  • 浏览: 583118 次
  • 性别: Icon_minigender_2
  • 来自: 杭州
社区版块
存档分类
最新评论

外部类和内部类

 
阅读更多
内部类的共性

内部类分为: 成员内部类、静态嵌套类、方法内部类、匿名内部类。
(1)、内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号 OutClass$InterClass.class
(2)、内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由地访问外部类的成员变量,无论是否是private的。
(3)、内部类声明成静态的,就不能随便的访问外部类的成员变量,仍然是只能访问外部类的静态成员变量。
(4)内部类不能定义静态变量。

因为内部类特殊,他被定向为是和成员变量,方法一样的外部类成员
他必须跟外部类实例相关联才能初始化,这是他的特点之一,为了这个其他东西都要让路
而静态成员是不需要实例就初始化的
如果一个非静态内部类有了静态成员,静态成员不依托于任何内部类实例,那结果也就是此内部类不需要外部类实例就初始化了变量,严重侵害了内部类的定向


成员内部类
成员内部类的优点:
⑴ 内部类作为外部类的成员,可以访问外部类的私有成员或属性。(即使将外部类声明为PRIVATE,但是对于处于其内部的内部类还是可见的。)
⑵ 用内部类定义在外部类中不可访问的属性。这样就在外部类中实现了比外部类的private还要小的访问权限
注意:内部类是一个编译时的概念,一旦编译成功,就会成为完全不同的两类。对于一个名为outer的外部类和其内部定义的名为inner的内部类。编译完成后出现outer.class和outer$inner.class两类。
class Outer {
class Inner{}
}
编译上述代码会产生两个文件:Outer.class和Outer$Inner.class。



方法内部类(局部内部类)

顾名思义,把类放在方法内。
class Outer {
public void Dosomething(){
class Inner{
public void seeOuter(){
}
}
}
}

A、方法内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化。









局部内部类特点:1.方法内创建的类,不能加访问修饰符。
(2)、方法内部类对象不能使用该内部类所在方法的非final局部变量。
即局部内部类只能使用方法局部final变量
原因入下:
(1)设方法f被调用,从而在它的调用栈中生成了变量i,此时产生了一个局部内部类对象inner_object,它访问了该局部变量i .当方法f()运行结束后,局部变量i就已死亡了,不存在了.但:局部内部类对象inner_object还可能   一直存在(只能没有人再引用该对象时,它才会死亡),它不会随着方法f()运行结束死亡.这时:出现了一个"荒唐"结果:局部内部类对象inner_object要访问一个已不存在的局部变量i!
   (2)如何才能实现?当变量是final时,通过将final局部变量"复制"一份,复制品直接作为局部内部中的数据成员.这样:当局部内部类访问局部变量时,其实真正访问的是这个局部变量的"复制品"(即:这个复制品就代表了那个局部变量).因此:当运行栈中的真正的局部变量死亡时,局部内部类对象仍可以访问局部变量(其实访问的是"复制品"),给人的感觉:好像是局部变量的"生命期"延长了.


把类放在方法内
class Outer {
public void doSomething(){
class Inner{
public void seeOuter(){
}
}
}
}
值得注意的是:方法内创建的类,不能加访问修饰符。
(1)、方法内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化。

class Outer {
public void doSomething(){
final int a =10;
class Inner{
public void seeOuter(){
System.out.println(a);// 若把a去掉final,则会错。
}
}


匿名内部类(是局部内部类,存在方法和作用域内的)

顾名思义,没有名字的内部类。表面上看起来它们似乎有名字,实际那不是它们的名字。
在使用匿名内部类时,要记住以下几个原则:
·一个匿名类,它通过实例初始化实现构造,所以匿名类不可能有构造器
·匿名内部类不能定义任何静态成员、静态方法。
·匿名内部类不能是public,protected,private,static。
·只能创建匿名内部类的一个实例。
·一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
·因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。



匿名类本身就是通过继承类或者接口来实现的。但是不能再显式的extends 或者implements了



1.怎样判断一个匿名类的存在啊?看不见名字,感觉只是父类new出一个对象而已,没有匿名类的名字。

先看段伪代码
abstract class Father(){
....
}
public class Test{
   Father f1 = new Father(){ .... }  //这里就是有个匿名内部类
}
一般来说,new 一个对象时小括号后应该是分号,也就是new出对象该语句就结束了。
但是出现匿名内部类就不一样,小括号后跟的是大括号,大括号中是该new 出对象的具体的实现方法。

因为我们知道,一个抽象类是不能直接new 的,必须先有实现类了我们才能new出它的实现类。
上面的伪代码就是表示new 的是Father的实现类,这个实现类是个匿名内部类。
其实拆分上面的匿名内部类可为
class SonOne extends Father{
  ...//这里的代码和上面匿名内部类,大括号中的代码是一样的
}
public class Test{
   Father f1 = new SonOne() ;
}

匿名内部类

注意,匿名内部类后面的分号不可缺少!

匿名内部类由于没有名字,所以它没有构造函数(但是如果这个匿名内部类继承了一个只含有带参数构造函数的父类,创建它的时候必须带上这些参数,并在实现的过程中使用 super 关键字调用相应的内容)。如果你想要初始化它的成员变量,有下面几种方法:
1. 如果是在一个方法的匿名内部类,可以利用这个方法传进你想要的参数,不过记住,这些参数必须被声明为 final 。

class Outer {
public void doSomething() {
final int a = 10;
class Inner extends MyTest implements interTest{
public void seeOuter() {
System.out.println(a);
}
}

new Outer(){
};


}

public static void main(String args[]){
new Outer(){
};
}
}


A、继承式的匿名内部类
public class Car {
public void drive(){
System.out.println("Driving a car!");
}
public static void main(String[] args) {
Car car = new Car(){
public void drive() {
System.out.println("Driving anther car!");
}
};
car.drive();
}
}
结果输出了:Driving another car! Car引用变量不是引用Car对象,而是Car匿名子类的对象。
B、接口式的匿名内部类。
interface Vehicle {
public void drive();
}
class Test{
public static void main(String[] args) {
Vehicle v = new Vehicle(){
public void drive(){
System.out.println("Driving a car!");
}
};
v.drive();
}
}
上面的代码很怪,好像是在实例化一个接口。事实并非如此,接口式的匿名内部类是实现了一个接口的匿名类。而且只能实现一个接口。
C、参数式的匿名内部类。
class Bar{
void doStuff(Foo f){}
}
interface Foo{
void foo();
}
class Test{
static void go(){
Bar b = new Bar();
b.doStuff(new Foo(){
public void foo(){
System.out.println("foofy");
}
});
}
}

静态嵌套类
静态内部类中可以定义静态或者非静态的成员。
从技术上讲,静态嵌套类不属于内部类。因为内部类与外部类共享一种特殊关系,更确切地说是对实例的共享关系。而静态嵌套类则没有上述关系。它只是位置在另一个类的内部,因此也被称为顶级嵌套类。
静态的含义是该内部类可以像其他静态成员一样,没有外部类对象时,也能够访问它。静态嵌套类仅能访问外部类的静态成员和方法。


class Outer{
static class Inner{}
}
class Test {
public static void main(String[] args){
Outer.Inner n = new Outer.Inner();
}
}

嵌套类可以作为接口的内部类。正常情况下,你不能在接口内部放置任何代码,但嵌套类可以作为接口的一部分,因为它是static 的。只是将嵌套类置于接口的命名空间内,这并不违反接口的规则。


public interface Test {

static class mm {

}

}


为什么需要内部类

为何要内部类?
    a、内部类提供了某种进入外围类的窗户。
    b、也是最吸引人的原因,每个内部类都能独立地继承一个接口,而无论外围类是否已经继承了某个接口。
  因此,内部类使多重继承的解决方案变得更加完整,内部类有效地实现了“多重继承”。

  在项目中,需要多重继承,如果是两个接口,那么好办,接口支持多重继承。
  如果是两个类呢?这时只有使用内部类了。



//内部类可以作为一个父类被继承
内部类被继承,由于内部类有一个指向外围类对象的秘密引用,所以在继承内部类的时候,该秘密引用必须被初始化。解决方法是
enclosingClassReference.super();语法,看一下代码:
   
class Outer{  
     class Inner {      
  }  
}
  
class AnoClass extends Outer.Inner{  
     AnoClass (Outer wi){  
             wi.super(); //这里是必须的,否则出错
    
  }
}





//成员内部类 实例化

public class OuterTest {

	public class InterTest {

		public InterTest(String m) {
			System.out.println(m);
		}
	}

	public static void main(String[] args) {
		OuterTest ot = new OuterTest();
      //创建某个内部类的对象方法一
		OuterTest.InterTest it = ot.new InterTest("88");
	}
}




public class OuterTest {
	public class InterTest {

		public InterTest(String m) {
			System.out.println(m);
		}
	}

	public InterTest Inter(String strs) {
		return new InterTest(strs);
	}

	public static void main(String[] args) {
		OuterTest ot = new OuterTest();
		// OuterTest.InterTest it = ot.new InterTest("88");
//创建某个内部类的对象方法二
		OuterTest.InterTest it = ot.Inter("88");
	}
}



public class OuterTest {
	private int i = 9;

	public int decrease(int m) {
		return (m -= 1);
	}

	public class InterTest {
		private int lable = 6;

		public InterTest(String m) {
			System.out.println(m);
		}

		public int increase() {
			// 内部类调用外部类的字段i
			return this.lable = ++i;
		}

		public int voke() {
			// 内部类调用外部类的方法decrease(int m)
			return decrease(lable);
		}
	}

	public static void main(String[] args) {
		OuterTest ot = new OuterTest();
		OuterTest.InterTest it = ot.new InterTest("88");
		System.out.println("内部类调用外部类的字段i:" + it.increase());
		System.out.println("内部类调用外部类的方法decrease():" + it.increase());
	}
}






//内部类实现接口
public interface Test {
	boolean start();

	int current();

	void end();
}


public class OuterTest {
	private int i = 9;

	public int decrease(int m) {
		return (m -= 1);
	}

	public class InterTest implements Test  {
		private int lable = 6;

		@Override
		public boolean start() {
			return true;
		}

		@Override
		public int current() {
			this.lable = 8;
			return 0;
		}

		@Override
		public void end() {
		}

	}

	public static void main(String[] args) {
		OuterTest ot = new OuterTest();
		OuterTest.InterTest it = ot.new InterTest();
		it.start();
		it.current();
		it.end();

		Test inter = ot.new InterTest();
		inter.start();
		inter.current();
		inter.end();

	}
}


//内部类可以继承类或实现接口

package ldd;

class Outer {
	public void doSomething() {
		final int a = 10;
		class Inner [color=red]extends MyTest implements interTest[/color]{
			public void seeOuter() {
				System.out.println(a);
			}
		}
	
		new Outer(){
		};
		
	}
	
	public static void main(String args[]){
		new Outer(){
		};
	}
}

0
12
分享到:
评论

相关推荐

    Java的内部类讲解案例代码(成员内部类、局部内部类、匿名内部类、静态内部类、外部类访问四种内部类、其他类访问四种内部类...)

    - 不同类型的内部类(静态内部类、成员内部类、局部内部类和匿名内部类)的区别和用法 - 内部类的优缺点以及使用场景 这些目标将帮助你理解和掌握内部类的概念,并能够在适当的时候使用内部类来解决问题...

    Java内部类和外部类的关系

    这个类对学习java很有帮助,这个类对学习java很有帮助,这个类对学习java很有帮助,这个类对学习java很有帮助,这个类对学习java很有帮助,这个类对学习java很有帮助,这个类对学习java很有帮助,这个类对学习java很...

    15.java静态内部类(相当于外部类).zip

    15.java静态内部类(相当于外部类).zip15.java静态内部类(相当于外部类).zip15.java静态内部类(相当于外部类).zip15.java静态内部类(相当于外部类).zip15.java静态内部类(相当于外部类).zip15.java静态内部...

    匿名内部类

    该资源主要是理解匿名内部类的用法和概念,形式上以代码的样式,主要由外部类和内部类以及测试类三个部分组成,另外匿名内部类没有类名

    029集-Activity、内部类、外部类实现点击事件响应

    029集-Activity、内部类、外部类实现点击事件响应视频教程。

    定义一个Father和Child类,并进行测试。

    1)Father类为外部类,类中定义一个私有的String类型的属性name,name的值为“zhangjun”。 2)Child类为Father类的内部类,其中定义一个introFather()方法,方法中调用Father类的name属性。 3)定义一个测试类Test...

    Java内部类和包装类.ppt

    包含内部类的类也被称为外部类(有的地方也叫宿主类) 匿名内部类就是没有名字的内部类 正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写 但使用匿名内部类还有个前提条件:必须继承一个父类或...

    fenghaotong#spark#5扩大内部类作用域的2种方法、内部类获取外部类引用1

    扩大内部类作用域的2种方法、内部类获取外部类引用扩大内部类作用域的2种方法内部类的作用域:外部类对象val students = new ArrayBuffer

    e语言-类的私有成员实现从外部访问

    利用自定义数据可以把单个的私有成员打包,然后将外部变量的地址指向类内部的私有成员数据地址,就可以实现修改外部变量的同时,类内部的私有成员数据也发生了变化。从而实现了类内部私有成员的数据可以直接操作的...

    Java的内部类和匿名类剖析

    在那些修改中,引人注目的是内部类和匿名类。如运用得当,它们可使程序更易理解和维护。本文介绍内部类和匿名类在Java代码中是如何具体工作的,如何正确使用它们,以及如何避免一些常见的错误。 下面来看看这些特性...

    类的私有成员实现从外部访问

    利用自定义数据可以把单个的私有成员打包,然后将外部变量的地址指向类内部的私有成员数据地址,就可以实现修改外部变量的同时,类内部的私有成员数据也发生了变化。从而实现了类内部私有成员的数据可以直接操作的...

    Java内部类

    内部类是指在一个外部类的内部再定义一个类。类名不需要和文件夹相同。内部类可以是静态static的,也可用public,default,protected和private修饰。(而外部顶级类即类名和文件名相同的只能使用public和default)。

    java中内部类与外部类的学习资料.docx

    java中内部类与外部类的学习资料.docx

    深入理解Java?内部类

     (1)、内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号 。  (2)、内部类不能用普通的方式访问。  (3)、内部类声明成静态的,不能随便的访问外部类的...

    JAVA语法总结 - 内部类

    A、内部类仍然是一个独立的类,在编译之后会内部类会被编译成独立的.class文件,但是前面冠以外部类的类命和$符号。 B、内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由地访问外部类的...

    java语言内部类总结

    定义在一个类内部的类叫内部类,包含内部类的类称为外部类。内部类可以声明public、protected、private等访问限制,可以声明为abstract的供其他内部类或外部类继承与扩展,或者声明为static、final的,也可以实现...

    详细分析内部类的发生内存泄漏的原因

    如果您已了解静态类和内部类,则应该熟悉使用Java代码中的嵌套类的基础知识。在这个相关的技巧中,我将带您了解嵌套类的陷阱之一,这是内部类在JVM中导致内存泄漏和内存不足错误的潜力。 之所以会发生这种类型的内存...

    java内部类的使用

    内部类的定义和普通类的定义没什么区别,它可以直接访问和引用它的外部类的所有变量和方法(包括private),就像外部类中的其他非static成员的功能一样。区别是,外部类只能声明为public和default,而内部类可以声明...

    java(Day12)---内部类

    在该内部类所在的外部类的普通方法中创建该内部类对象 可以使用this作为外部类对象 This.new内部类类名(实参列表); 此时this可以忽略不写,所以可以简写为new 内部类类名(实参列表); 当外部类属性与内部类属性重名时...

    浅谈Java内部类的四个应用场景

    Java内部类总是躲在它的外部类里,像一个幕后英雄一样。但是幕后英雄也有用武之地,在很多时候,恰当的使用Java内部类能起到让人拍案叫绝的作用。本文试图谈一谈让这个幕后英雄也有用武之地的四个场景,希望引起大家...

Global site tag (gtag.js) - Google Analytics