概述
摘要: Java内部类 ①内部类是在一个java类体内,再定义一个类,即外部类的内部再定义一个类(相对的)。 ②内部类分为四类: 成员内部类、局部内部类、静态内部类、匿名内部类 ③内部类作为外部类的一个成员,并依附于外部类而存在。包括:成员内部类、局部内部类、匿名内部类 ④内部类可以由private、public、protected
Java内部类
①内部类是在一个java类体内,再定义一个类,即外部类的内部再定义一个类(相对的)。
②内部类分为四类:
成员内部类、局部内部类、静态内部类、匿名内部类
③内部类作为外部类的一个成员,并依附于外部类而存在。包括:成员内部类、局部内部类、匿名内部类
④内部类可以由private、public、protected、default访问修饰符和static修饰;
⑤而外部类,即和public类平行的,只能有default修饰(空白修饰符),总之,由public和default访问修饰符修饰。
⑥ 内部类和外部类的实例变量可以共存,
内部类中访问实例变量:this.属性。eg: this.age
内部类中访问外部类的实例变量:外部类名.this.属性。InnerClass.this.id
⑦内部类是一个编译时的概念,编译成功,就会成为完全不同的两个类 eg:InnerClass.class和InnerClass$Classx1.class
⑧内部类里不能定义静态的属性和方法;
注:此处内部类(除静态内部类外);
加载类时,静态默认在内存中实例化的并存放。即可以直接调用不用手动实例化使用。内部类的实例化依赖于外部类,内部类不能直接被实例化,必须在外部类实例化后再实例化。
外部类public class或class是不能默认加载的,只有调用new关键字手动实例化时才分配内存。
所以内部类不能定义静态的属性和方法。
所有代码编译图为:
成员内部类:
package com.classx.inner;
public class InnerClass {
//外部类private属性
private int id=4466;
private static String name ="shasha";
//外部类getter和setter方法
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public static String getName() {
return name;
}
public static void setName(String name) {
InnerClass.name = name;
}
//************************成员内部类***********************************//
//成员内部类,作为外部类的成员,可以访问外部所有
//内部类中的定义的private属性,比外部的private还小的访问权限
//作为一个外部类的成员存在,和外部类的属性、方法并列
//可以有private、public、protected、default修饰
class Classx1{
private int age=5555;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void getN1(){
System.out.println("inner1");
System.out.println("成员内部类:"+InnerClass.this.id+"*"+this.age);
}
}
//外部类内部调用成员内部类
public void getC1(){
Classx1 c1 = new Classx1();
c1.getN1();
System.out.println("外部类内部调用成员内部类:完毕!");
}
}
测试类:
package com.classx.inner;
public class Test {
public static void main(String[] args) {
//*****外部类调用成员内部类********//
//外部类对象ic
InnerClass ic = new InnerClass();
/***成员内部类***/
//内部调用
ic.getC1();
//外部调用
// InnerClass.Classx1 icc1 = new InnerClass().new Classx1();
InnerClass.Classx1 icc1 = ic.new Classx1();
icc1.getN1();
}
}
输出结果:
inner1
成员内部类:4466*5555
外部类内部调用成员内部类:完毕!
inner1
成员内部类:4466*5555
编译后的class字节码反编译为:
InnerClass类:
package com.classx.inner;
import java.io.PrintStream;
public class InnerClass
{
private int id = 4466;
private static String name = "shasha";
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public static String getName() {
return name;
}
public static void setName(String name) {
name = name;
}
public void getC1()
{
Classx1 c1 = new Classx1();
c1.getN1();
System.out.println("外部类内部调用成员内部类:完毕!");
}
class Classx1
{
private int age = 5555;
Classx1() { }
public int getAge() { return this.age; }
public void setAge(int age) {
this.age = age;
}
public void getN1() {
System.out.println("inner1");
System.out.println("成员内部类:" + InnerClass.this.id + "*" + this.age);
}
}
}
成员内部类Classx1:
package com.classx.inner;
import java.io.PrintStream;
class InnerClass$Classx1
{
private int age = 5555;
InnerClass$Classx1(InnerClass paramInnerClass) { }
public int getAge() { return this.age; }
public void setAge(int age) {
this.age = age;
}
public void getN1() {
System.out.println("inner1");
System.out.println("成员内部类:" + InnerClass.access$0(this.this$0) + "*" + this.age);
}
}
局部内部类:
此后外部类代码,不变,替换内部类:
//************************局部内部类***********************************//
public void drawIC(){
//在外部类方法体中定义的类叫局部内部类,不能有修饰符(包括static),能访问外部类实例变量,且只能访问方法体中的final类型的局部变量
final String fstr = "lalala";
System.out.println("inner2");
//局部内部类
//外部类外不可直接生成局部内部类,对外不可见
class Classx2{
private int width = 333;
public Classx2(){
super();
System.out.println("局部内部类默认构造方法在drawIC中new时候执行");
}
public void getN2(){
System.out.println("局部内部类:"+fstr+"&"+id+"$"+width);
}
}
//使用局部内部类,要生成对象,对象调用方法,在方法中才能调用其局部内部类
//局部内部类使用new,方法调用
Classx2 icmc = new Classx2();
System.out.println("局部内部类对象调用getN2开始");
icmc.getN2();
}
测试代码:
此后,main中的代码,其他省略:
//*****外部类调用成员内部类********//
//外部类对象ic
InnerClass ic = new InnerClass();
/***局部内部类***/
//调用局部内部类
ic.drawIC();
代码输出为:
inner2
局部内部类默认构造方法在drawIC中new时候执行
局部内部类对象调用getN2开始
局部内部类:lalala&4466$333
编译后的InnerClass类:
此后,只替换变化代码,其他不变:
public void drawIC()
{
String fstr = "lalala";
System.out.println("inner2");
Object icmc = new Object()
{
private int width = 333;
public void getN2()
{
System.out.println("局部内部类:lalala&" + InnerClass.this.id + "$" + this.width);
}
};
System.out.println("局部内部类对象调用getN2开始");
icmc.getN2();
}
编译后的Classx2类:
package com.classx.inner;
import java.io.PrintStream;
class InnerClass$1Classx2
{
private int width = 333;
public InnerClass$1Classx2(InnerClass paramInnerClass) {
System.out.println("局部内部类默认构造方法在drawIC中new时候执行");
}
public void getN2() {
System.out.println("局部内部类:lalala&" + InnerClass.access$0(this.this$0) + "$" + this.width);
}
}
静态内部类
//************************静态内部类***********************************//
//静态内部类
//外部类只能有public和default修饰符,而成员内部类可以有private、public、protected、default和static修饰
//只能访问外部类静态成员
public static class Class3{
private static int length = 169;
public void getN3(){
System.out.println("inner3");
System.out.println("静态内部类:"+length+InnerClass.name);
}
}
测试代码:
/***静态内部类***/
//调用静态内部类
//不需要通过生成外部类的对象来生成,实际上,成为了顶级类
// Class3 c3 = new InnerClass.Class3();
InnerClass.Class3 c3 = new InnerClass.Class3();
c3.getN3();
输出为:
inner3
静态内部类:169shasha
编译后:
InnerClass类:
public static class Class3
{
private static int length = 169;
public void getN3() { System.out.println("inner3");
System.out.println("静态内部类:" + length + InnerClass.name);
}
}
Class3类:
package com.classx.inner;
import java.io.PrintStream;
public class InnerClass$Class3
{
private static int length = 169;
public void getN3() { System.out.println("inner3");
System.out.println("静态内部类:" + length + InnerClass.access$0());
}
}
匿名内部类:
In接口:
package com.classx.inner;
public interface In {
public abstract int extend();
}
Ac抽象类:
package com.classx.inner;
public abstract class Ac {
public abstract int extend();
}
InnerClass类:
//************************匿名内部类***********************************//
//匿名内部类
//①是特殊的局部内部类,所以局部内部类的限制对它生效,不能有访问修饰符和static修饰
//②唯一一个无构造方法的类(使用范围很有限),不能定义任何静态成员、方法、类
//③一个匿名内部类一定是在new后面,用它隐含的实现一个接口或实现一个类
//④没有类名(不能有),所以不能引用它。根据多态,可使用它的父类(接口)名
//⑤没办法引用它,必须在创建时,作为new语句的一部分来声明它(特殊形式new语句),形式:new 类名或接口名(){类的主体}
//通过上new语句声明形式,声明一个新的匿名类,它对一个给定类进行扩展,或实现一个给定的接口
//并且还创建给定类或给定接口的新实例(只能创建匿名内部类的一个实例),并把它作为语句的结果返回
//⑥内部匿名类,就是建立一个内部的类,但没有给你命名,也就是没有引用实例的变量。
//⑦匿名类扩展了给定类,可以访问该被扩展类的成员、覆盖它的方法等(标准类一致)
//⑧匿名类实现了接口,它的主体必须实现接口的方法
//⑨如果一个对象编译时类型为接口,那么运行时类型为实现这个接口的类
//10编译时系统自动起名:InnerClass$1.class
//*匿名内部类实现一个接口,可以解决多继承出现方法冲突问题*/
//可以直接返回return,也可作为方法返回值(给定接口或类的实例)返回
public In getExtendI(){
return new In() {
@Override
public int extend() {
System.out.println("inner4");
System.out.println("匿名内部类:我实现了接口In的方法");
return 0;
}
};
}
//一般new对象,InnerClass ic = new InnerClass();
//小括号后为;分号,结束,即new出了对象语句结束
//匿名内部类,new In() {...}
//小括号后为{}大括号,大括号中是该new出对象的具体实现方法
//一个抽象类不能直接使用(new对象),不能生成对象,必须继承使用,后进行new出对象使用
//*匿名内部类,可以对抽象类进行实现(实现类为匿名内部类),和extends继承父类,实现抽象是一样的 */
public Ac getExtendC(){
return new Ac() {
@Override
public int extend() {
System.out.println("inner5");
System.out.println("匿名内部类:我扩展了抽象类AC的方法"+(InnerClass.this.id));
return 0;
}
};
}
//*匿名内部类不能对InnerClass类扩展,方法不可用"unused"*/
测试类:
/***匿名内部类***/
//匿名内部类实现接口的调用
In in = ic.getExtendI();
in.extend();
//匿名内部类作为抽象类的实现类
Ac ac = ic.getExtendC();
ac.extend();
输出结果:
inner4
匿名内部类:我实现了接口In的方法
inner5
匿名内部类:我扩展了抽象类AC的方法4466
编译后:
InnerClass类:
public In getExtendI()
{
return new In()
{
public int extend() {
System.out.println("inner4");
System.out.println("匿名内部类:我实现了接口In的方法");
return 0;
}
};
}
public Ac getExtendC()
{
return new Ac()
{
public int extend() {
System.out.println("inner5");
System.out.println("匿名内部类:我扩展了抽象类AC的方法" + InnerClass.this.id);
return 0;
}
};
接口实现匿名内部类:
package com.classx.inner;
import java.io.PrintStream;
class InnerClass$1
implements In
{
InnerClass$1(InnerClass paramInnerClass)
{
}
public int extend()
{
System.out.println("inner4");
System.out.println("匿名内部类:我实现了接口In的方法");
return 0;
}
}
抽象类实现类(匿名内部类)
package com.classx.inner;
import java.io.PrintStream;
class InnerClass$2 extends Ac
{
InnerClass$2(InnerClass paramInnerClass)
{
}
public int extend()
{
System.out.println("inner5");
System.out.println("匿名内部类:我扩展了抽象类AC的方法" + InnerClass.access$0(this.this$0));
return 0;
}
}
注:最尾提供全部代码
Java多继承方法(名)冲突
当类或接口或(抽象)父类,三个不同组合,发生方法(名)冲突的时候,此时必须使用内部类来解决。
匿名内部类、成员内部类
接口配合内部类,可以实现真正完全的多继承。
接口In:
package com.classx.inner;
public interface In {
public abstract int extend(int id);
}
抽象类Ac:
package com.classx.inner;
public abstract class Ac {
public abstract int extend(int id);
}
实现类InnerClassSolveMultipleForAcOrIn:
package com.classx.inner;
//当类或接口或(抽象)父类,三个不同组合,发生方法(名)冲突的时候,此时必须使用内部类来解决
//接口配合内部类,可以实现真正完全的多继承
public class InnerClassSolveMultipleForAcOrIn implements In{
public int id = 3355;
@Override
public int extend(int id) {
System.out.println("外部类实现接口In中的extend()方法"+id);
return 1;
}
//内部类作为外部类的成员(非静态)
//内部类可以对外部类状态完全进行修改,和直接调用(使用)InnerClassSolveMultipleForAcOrIn是一样的
private class InnerC extends Ac{
@Override
public int extend(int id) {
System.out.println("成员内部类实现抽象父类Ac中的extend()方法"+id);
return 2;
}
}
//内部类为private的,除了当前外部类,其他类都是不可见的
//而此方法,返回值为直接向上转型(实现了抽象父类)的抽象父类的引用,对外暴露抽象父类,隐藏了InnerC的存在
public Ac getInnerCInstance(){
return new InnerC();
}
//匿名内部类解决冲突
public Ac getgetInnerNoInstance(){
return new Ac() {
@Override
public int extend(int id) {
System.out.println("匿名内部类实现抽象父类Ac中的extend()方法"+id);
return 3;
}
};
}
}
测试类:
package com.classx.inner;
public class TestAcIn {
public static void main(String[] args) {
//外部类对象
InnerClassSolveMultipleForAcOrIn iaci = new InnerClassSolveMultipleForAcOrIn();
In in = iaci;
//外部类实现接口方法
in.extend(1);
//用"成员内部类"解决(实现)抽象类和接口同名方法
Ac ac = iaci.getInnerCInstance();
ac.extend(2);
//用"匿名内部类"解决(实现)抽象类和接口同名方法
Ac acn = iaci.getgetInnerNoInstance();
acn.extend(3);
}
}
输出结果:
外部类实现接口In中的extend()方法1
成员内部类实现抽象父类Ac中的extend()方法2
匿名内部类实现抽象父类Ac中的extend()方法3
实现内部类,全部代码:
内部类InnerClass代码:
package com.classx.inner;
public class InnerClass {
//外部类private属性
private int id=4466;
private static String name ="shasha";
//外部类getter和setter方法
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public static String getName() {
return name;
}
public static void setName(String name) {
InnerClass.name = name;
}
//************************成员内部类***********************************//
//成员内部类,作为外部类的成员,可以访问外部所有
//内部类中的定义的private属性,比外部的private还小的访问权限
//作为一个外部类的成员存在,和外部类的属性、方法并列
//可以有private、public、protected、default修饰
class Classx1{
private int age=5555;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void getN1(){
System.out.println("inner1");
System.out.println("成员内部类:"+InnerClass.this.id+"*"+this.age);
}
}
//外部类内部调用成员内部类
public void getC1(){
Classx1 c1 = new Classx1();
c1.getN1();
System.out.println("外部类内部调用成员内部类:完毕!");
}
//************************局部内部类***********************************//
public void drawIC(){
//在外部类方法体中定义的类叫局部内部类,不能有修饰符(包括static),能访问外部类实例变量,且只能访问方法体中的final类型的局部变量
final String fstr = "lalala";
System.out.println("inner2");
//局部内部类
//外部类外不可直接生成局部内部类,对外不可见
class Classx2{
private int width = 333;
public Classx2(){
super();
System.out.println("局部内部类默认构造方法在drawIC中new时候执行");
}
public void getN2(){
System.out.println("局部内部类:"+fstr+"&"+id+"$"+width);
}
}
//使用局部内部类,要生成对象,对象调用方法,在方法中才能调用其局部内部类
//局部内部类使用new,方法调用
Classx2 icmc = new Classx2();
System.out.println("局部内部类对象调用getN2开始");
icmc.getN2();
}
//************************静态内部类***********************************//
//静态内部类
//外部类只能有public和default修饰符,而成员内部类可以有private、public、protected、default和static修饰
//只能访问外部类静态成员
public static class Class3{
private static int length = 169;
public void getN3(){
System.out.println("inner3");
System.out.println("静态内部类:"+length+InnerClass.name);
}
}
//************************匿名内部类***********************************//
//匿名内部类
//①是特殊的局部内部类,所以局部内部类的限制对它生效,不能有访问修饰符和static修饰
//②唯一一个无构造方法的类(使用范围很有限),不能定义任何静态成员、方法、类
//③一个匿名内部类一定是在new后面,用它隐含的实现一个接口或实现一个类
//④没有类名(不能有),所以不能引用它。根据多态,可使用它的父类(接口)名
//⑤没办法引用它,必须在创建时,作为new语句的一部分来声明它(特殊形式new语句),形式:new 类名或接口名(){类的主体}
//通过上new语句声明形式,声明一个新的匿名类,它对一个给定类进行扩展,或实现一个给定的接口
//并且还创建给定类或给定接口的新实例(只能创建匿名内部类的一个实例),并把它作为语句的结果返回
//⑥内部匿名类,就是建立一个内部的类,但没有给你命名,也就是没有引用实例的变量。
//⑦匿名类扩展了给定类,可以访问该被扩展类的成员、覆盖它的方法等(标准类一致)
//⑧匿名类实现了接口,它的主体必须实现接口的方法
//⑨如果一个对象编译时类型为接口,那么运行时类型为实现这个接口的类
//10编译时系统自动起名:InnerClass$1.class
//*匿名内部类实现一个接口,可以解决多继承出现方法冲突问题*/
//可以直接返回return,也可作为方法返回值(给定接口或类的实例)返回
public In getExtendI(){
return new In() {
@Override
public int extend() {
System.out.println("inner4");
System.out.println("匿名内部类:我实现了接口In的方法");
return 0;
}
};
}
//一般new对象,InnerClass ic = new InnerClass();
//小括号后为;分号,结束,即new出了对象语句结束
//匿名内部类,new In() {...}
//小括号后为{}大括号,大括号中是该new出对象的具体实现方法
//一个抽象类不能直接使用(new对象),不能生成对象,必须继承使用,后进行new出对象使用
//*匿名内部类,可以对抽象类进行实现(实现类为匿名内部类),和extends继承父类,实现抽象是一样的 */
public Ac getExtendC(){
return new Ac() {
@Override
public int extend() {
System.out.println("inner5");
System.out.println("匿名内部类:我扩展了抽象类AC的方法"+(InnerClass.this.id));
return 0;
}
};
}
//*匿名内部类不能对InnerClass类扩展,方法不可用"unused"*/
}
测试Test代码:
package com.classx.inner;
public class Test {
public static void main(String[] args) {
//*****外部类调用成员内部类********//
//外部类对象ic
InnerClass ic = new InnerClass();
/***成员内部类***/
//内部调用
ic.getC1();
//外部调用
// InnerClass.Classx1 icc1 = new InnerClass().new Classx1();
InnerClass.Classx1 icc1 = ic.new Classx1();
icc1.getN1();
/***局部内部类***/
//调用局部内部类
ic.drawIC();
/***静态内部类***/
//调用静态内部类
//不需要通过生成外部类的对象来生成,实际上,成为了顶级类
// Class3 c3 = new InnerClass.Class3();
InnerClass.Class3 c3 = new InnerClass.Class3();
c3.getN3();
/***匿名内部类***/
//匿名内部类实现接口的调用
In in = ic.getExtendI();
in.extend();
//匿名内部类作为抽象类的实现类
Ac ac = ic.getExtendC();
ac.extend();
}
}
输出结果:
inner1
成员内部类:4466*5555
外部类内部调用成员内部类:完毕!
inner1
成员内部类:4466*5555
inner2
局部内部类默认构造方法在drawIC中new时候执行
局部内部类对象调用getN2开始
局部内部类:lalala&4466$333
inner3
静态内部类:169shasha
inner4
匿名内部类:我实现了接口In的方法
inner5
匿名内部类:我扩展了抽象类AC的方法4466
package com.classx.inner;
public class Test {
public static void main(String[] args) {
//*****外部类调用成员内部类********//
//外部类对象ic
InnerClass ic = new InnerClass();
/***成员内部类***/
//内部调用
ic.getC1();
//外部调用
// InnerClass.Classx1 icc1 = new InnerClass().new Classx1();
InnerClass.Classx1 icc1 = ic.new Classx1();
icc1.getN1();
/***局部内部类***/
//调用局部内部类
ic.drawIC();
/***静态内部类***/
//调用静态内部类
//不需要通过生成外部类的对象来生成,实际上,成为了顶级类
// Class3 c3 = new InnerClass.Class3();
InnerClass.Class3 c3 = new InnerClass.Class3();
c3.getN3();
/***匿名内部类***/
//匿名内部类实现接口的调用
In in = ic.getExtendI();
in.extend();
//匿名内部类作为抽象类的实现类
Ac ac = ic.getExtendC();
ac.extend();
}
}
==================================================
使用内部类让Java实现“多继承”
使用内部类让Java实现“多继承”
众所周知,Java没有像c++那样支持多继承,但是我们可以使用接口或内部类来模拟实现多继承。
我们使用内部类来实现一个继承自消费者,又继承自生产者的派生类。
实际上Java之所以设计出内部类这个概念,一方面是为了更好的封装性,另一方面就是借助内部类模拟实现多继承。
首先我们定义一个消费者抽象基类
以下是生产者抽象基类/**
* Consumer Class
*@author android
*Last Modified:2011-12-13 上午11:04:56
*/
public abstract class Consumer {
protected float buyPrice;
protected abstract void buyGoods();
}
使用内部类实现“多继承”的派生子类/**
* Producer Class
*@author androidyue
*Last Modified:2011-12-13 上午11:04:02
*/
public abstract class Producer {
protected float cost;
protected abstract void produce();
}
在程序入口调用/**
*Java实现“多继承”
*@author androidyue
*Last Modified:2011-12-13 上午11:00:25
*/
public class InnerClassDemo extends Producer {
private ConsumerBuyer buyer;
public void desribeMySelf(){
System.out.println("使用Java模拟多继承");
this.produce();
this.buyer=new ConsumerBuyer();
this.buyer.buyGoods();
}
@Override
protected void produce() {
this.cost=100f;
System.out.println("我是生产者,我以每件"+this.cost+"RMB的成本生产一件产品,然后以20000元价格对外出售");
}
class ConsumerBuyer extends Consumer{
@Override
protected void buyGoods() {
this.buyPrice=0f;
System.out.println("我是消费者,我以"+this.buyPrice+"RMB 买了一件售价20000元的商品,不信吧,因为我也是生产者!^_^");
}
}
}
/**
* the entrance of application
*@author androidyue
*Last Modified:2011-12-13 上午11:20:06
*/
public class AppMain {
public static void main(String[] args){
InnerClassDemo demo=new InnerClassDemo();
demo.desribeMySelf();
}
}
使用Java模拟多继承
我是生产者,我以每件100.0RMB的成本生产一件产品,然后以20000元价格对外出售
我是消费者,我以0.0RMB 买了一件售价20000元的商品,不信吧,因为我也是生产者!^_^
最后
以上就是跳跃大侠为你收集整理的Java多继承方法(名)冲突和成员内部类、局部内部类、静态内部类、匿名内部类的全部内容,希望文章能够帮你解决Java多继承方法(名)冲突和成员内部类、局部内部类、静态内部类、匿名内部类所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复