内部类的共性
内部类分为: 成员内部类、静态嵌套类、方法内部类、匿名内部类。
(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(){
};
}
}
分享到:
相关推荐
- 不同类型的内部类(静态内部类、成员内部类、局部内部类和匿名内部类)的区别和用法 - 内部类的优缺点以及使用场景 这些目标将帮助你理解和掌握内部类的概念,并能够在适当的时候使用内部类来解决问题...
这个类对学习java很有帮助,这个类对学习java很有帮助,这个类对学习java很有帮助,这个类对学习java很有帮助,这个类对学习java很有帮助,这个类对学习java很有帮助,这个类对学习java很有帮助,这个类对学习java很...
15.java静态内部类(相当于外部类).zip15.java静态内部类(相当于外部类).zip15.java静态内部类(相当于外部类).zip15.java静态内部类(相当于外部类).zip15.java静态内部类(相当于外部类).zip15.java静态内部...
该资源主要是理解匿名内部类的用法和概念,形式上以代码的样式,主要由外部类和内部类以及测试类三个部分组成,另外匿名内部类没有类名
029集-Activity、内部类、外部类实现点击事件响应视频教程。
1)Father类为外部类,类中定义一个私有的String类型的属性name,name的值为“zhangjun”。 2)Child类为Father类的内部类,其中定义一个introFather()方法,方法中调用Father类的name属性。 3)定义一个测试类Test...
包含内部类的类也被称为外部类(有的地方也叫宿主类) 匿名内部类就是没有名字的内部类 正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写 但使用匿名内部类还有个前提条件:必须继承一个父类或...
扩大内部类作用域的2种方法、内部类获取外部类引用扩大内部类作用域的2种方法内部类的作用域:外部类对象val students = new ArrayBuffer
利用自定义数据可以把单个的私有成员打包,然后将外部变量的地址指向类内部的私有成员数据地址,就可以实现修改外部变量的同时,类内部的私有成员数据也发生了变化。从而实现了类内部私有成员的数据可以直接操作的...
在那些修改中,引人注目的是内部类和匿名类。如运用得当,它们可使程序更易理解和维护。本文介绍内部类和匿名类在Java代码中是如何具体工作的,如何正确使用它们,以及如何避免一些常见的错误。 下面来看看这些特性...
利用自定义数据可以把单个的私有成员打包,然后将外部变量的地址指向类内部的私有成员数据地址,就可以实现修改外部变量的同时,类内部的私有成员数据也发生了变化。从而实现了类内部私有成员的数据可以直接操作的...
内部类是指在一个外部类的内部再定义一个类。类名不需要和文件夹相同。内部类可以是静态static的,也可用public,default,protected和private修饰。(而外部顶级类即类名和文件名相同的只能使用public和default)。
java中内部类与外部类的学习资料.docx
(1)、内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号 。 (2)、内部类不能用普通的方式访问。 (3)、内部类声明成静态的,不能随便的访问外部类的...
A、内部类仍然是一个独立的类,在编译之后会内部类会被编译成独立的.class文件,但是前面冠以外部类的类命和$符号。 B、内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由地访问外部类的...
定义在一个类内部的类叫内部类,包含内部类的类称为外部类。内部类可以声明public、protected、private等访问限制,可以声明为abstract的供其他内部类或外部类继承与扩展,或者声明为static、final的,也可以实现...
如果您已了解静态类和内部类,则应该熟悉使用Java代码中的嵌套类的基础知识。在这个相关的技巧中,我将带您了解嵌套类的陷阱之一,这是内部类在JVM中导致内存泄漏和内存不足错误的潜力。 之所以会发生这种类型的内存...
内部类的定义和普通类的定义没什么区别,它可以直接访问和引用它的外部类的所有变量和方法(包括private),就像外部类中的其他非static成员的功能一样。区别是,外部类只能声明为public和default,而内部类可以声明...
在该内部类所在的外部类的普通方法中创建该内部类对象 可以使用this作为外部类对象 This.new内部类类名(实参列表); 此时this可以忽略不写,所以可以简写为new 内部类类名(实参列表); 当外部类属性与内部类属性重名时...
Java内部类总是躲在它的外部类里,像一个幕后英雄一样。但是幕后英雄也有用武之地,在很多时候,恰当的使用Java内部类能起到让人拍案叫绝的作用。本文试图谈一谈让这个幕后英雄也有用武之地的四个场景,希望引起大家...