精华内容
下载资源
问答
  • 内部类和匿名内部类

    2019-06-27 08:57:52
    内部类和匿名内部类 内部类 匿名内部类 1. 内部类 概述:定义在类中的类称作内部类 内部类访问特点 内部类可以直接访问外部类的成员,包括私有。 外部类要访问内部类的成员,必须创建对象。 ...

    内部类和匿名内部类

    1. 内部类
    2. 匿名内部类
    3. 内部接口

    1. 内部类

    1. 概述:定义在类中的类称作内部类
    2. 内部类访问特点
      1. 内部类可以直接访问外部类的成员,包括私有。
      2. 外部类要访问内部类的成员,必须创建对象。
    3. 分类:
      1. 成员内部类:将内部类定义到外部类的成员位置(类中方法外)
      2. 局部内部类:将内部类定义到 外部类的局部位置(方法中)
    class A{
    
        class B { 
       		 //成员内部类
     	}
    
        public void waiShow(){
            class C{ 
            //局部内部类
            }
        }
    }
    
    
    1. 成员内部类访问特点:
      1. 内部类可以直接访问外部类的成员,包括私有的属性和方法
      2. 外部类不能直接访问内部类的成员,需要创建内部类的对象(创建类的对象)
      3. 在测试类中直接访问内部类的成员。
        格式: 外部类名.内部类名 对象名 =new 外部类对象.new 内部类对象;
      4. 未用staitc修饰的内部类的创建对象的语法
        外部类名.内部类名 对象名 =new 外部类对象.new 内部类对象;
        static 修饰内部类,那么创建内部类对象的语法:(静态内部类,只能访问外部类的静态成员)
        外部类名.内部类名 对象名 =new 外部类对象.内部类对象;
        Ps:内部类可以用private修饰,但是私有的内部类,外界(Test类)不能创建其对象了
        使用时只能通过外部类(内部类上一级)new内部类然后调用内部类中的成员和方法
    public classTest {
        public static void main(String[] args) {
            //调用内部类的方法,要创建内部类的对象
            Outer.Inner inner=new Outer().new Inner();
            inner.innnerShow();
            //外部类想要调用内部类的成员,得创建内部类对象
    
    
        }
    }
    public class Outer {
        int num=10;
    
        private int a=20;
    
        class Inner{    //成员内部类
            int aa=1;
            public void innnerShow(){
                System.out.println("内部类的show方法");
                System.out.println(num);
                System.out.println(a);
                outerShow();      //调用外部类方法
                outerTest();		//调用外部类私有方法
            }
    
        }
    
        public void  outerShow(){
            System.out.println("这是外部类的方法");
        }
    
        private void  outerTest(){
            System.out.println("外部类的私有方法");
        }
    
        public void test(){
            //外部类想要访问内部类的成员,得创建内部类的对象
            Inner inner = new Inner();
            System.out.println(inner.aa);
        }
    
    }
    
    
    1. 局部内部类访问特点:
      1. 可以直接访问外部类的成员
      2. 局部内部类,在外界没有直接创建其对象语法
      3. 可以创建内部类对象(在外部类),通过对象调用内部类方法,来使用局部内部类功能
      4. 局部内部类访问局部变量必须用final修饰
        因为局部变量会随着方法的调用完毕而消失,这个时候,局部对象并没有立马从堆内存中消失,还要使用那个变量。
        为了让数据还能继续被使用,就用fianl修饰,使其变成一个常量
    public class MyTest {
        public static void main(String[] args) {
    
            Outer outer = new Outer(); //创建外部类对象
            outer.waiShow();
    
        }
    }
    
    
    class Outer{
        int num=100;
        private int a=10;
        public void waiShow(){
    
            class Inner{ //局部内部类
                int aa=2;
                public void neiShow(){
                    System.out.println("内部类的show方法");
                    System.out.println(num);	//可直接访问外部类成员
                    System.out.println(a);		//可直接访问外部类私有成员
                    hehe();  				    //可直接访问外部类方法
                }
    
            }
    
            Inner inner = new Inner();  //创建局部内部类对象
            inner.neiShow();			//调用局部内部类方法
    
        }
    
        private void hehe(){
    
        }
    
        public void waiTest(){
    
    
        }
    
    }
    
    

    2. 匿名内部类

    1. 概述:
      1. 匿名内部类: 就是局部内部类的简化写法
      2. 本质上是一个该类或实现了接口的子类对象
      3. 前提: 存在一个类或者接口;这里的类可以是具体类也可以是抽象类
    2. 格式:
      new 类名或者接口名(){
      重写方法;
      } ;
    public class MyTest2 {
        public static void main(String[] args) {
    
            new Animal(){			  	 //匿名内部类
                @Override
                public void eat() {
                    System.out.println("吃鸡");
                }
            }.eat();          			 //调用该对象的eat方法
    
    
            new MyInterface(){			 //匿名内部类
                @Override
                public void show() {
                    System.out.println("hehhehe");
                }
            }.show(); 					//调用该对象的show方法
    
    
        }
    }
    
    abstract class Animal{
        public abstract void eat();
    }
    
    
    interface MyInterface{
        void show();
    }
    
    
    1. this关键字的使用
    interface Inter {
    	public static final int a = 23;
    }
    
    public class Test {
    
    		public static void main(String[] args) {
    
    			new Inter() {
    				int a=50;
    				public void show() {
    				// 这个this表示的是匿名内部类的这个对象
    					System.out.println(this.a);  	 //匿名内部类(对象)的a值
    					System.out.println(Inter.a);	 //Inter 接口的a值
    				}
    			}.show();
    		}
    	}
    

    在这里插入图片描述

    3. 内部接口

    就是在类中定义一个接口

    public class MyTest {
        public static void main(String[] args) {
          
            //方式1
            new Outer().outerShow();  //直接访问outer类中的outershow方法
    
            //方式2
            Outer.MyInterface myInterface = new Outer.MyInterface() {  //创建内部接口的对象(匿名内部类)
    
                @Override
                public void show() {
                    System.out.println("重写show方法");
                }
            };
    
            myInterface.show();
    
        }
    }
    
    class Outer{
    
        //定义成员内部接口
        interface MyInterface{
            void show();
        }
    
        public void outerShow(){
            new MyInterface(){
    
                @Override
                public void show() {
                    System.out.println("匿名内部类的show方法");
                }
            }.show();
    
        }
    
    }
    
    
    展开全文
  • Java内部类和匿名内部类的用法

    万次阅读 多人点赞 2016-07-21 15:46:41
    Java内部类和匿名内部类的用法 【尊重原创,转载请注明出处】http://blog.csdn.net/guyuealian/article/details/51981163一、内部类: (1)内部类的同名方法 内部类可以调用外部类的方法,如果内部类有同名方法...

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

        【尊重原创,转载请注明出处】http://blog.csdn.net/guyuealian/article/details/51981163
    一、内部类: 
          (1)内部类的同名方法
            内部类可以调用外部类的方法,如果内部类有同名方法必须使用"OuterClass.this.MethodName()"格式调用(其中OuterClass与MethodName换成实际外部类名及其方法;this为关键字,表示对外部类的引用);若内部类无同名方法可以直接调用外部类的方法。
            但外围类无法直接调用内部类的private方法,外部类同样无法直接调用其它类的private方法。注意:内部类直接使用外部类的方法与该方法的权限与是否static无关,它取决于内部类是否有同名方法。
    package innerclass;
    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
          方法中的局部变量,方法结束后这个变量就要释放掉,final保证这个变量始终指向一个对象。
       首先,内部类和外部类其实是处于同一个级别,内部类不会因为定义在方法中就会随着方法的执行完毕而跟随者被销毁。问题就来了,如果外部类的方法中的变量不定义final,那么当外部类方法执行完毕的时候,这个局部变量肯定也就被GC了,然而内部类的某个方法还没有执行完,这个时候他所引用的外部变量已经找不到了。如果定义为final,java会将这个变量复制一份作为成员变量内置于内部类中,这样的话,由于final所修饰的值始终无法改变,所以这个变量所指向的内存区域就不会变。
         注意,若使用JDK1.8,方法中内部类的方法是可以直接访问外部类的方法的局部变量,并且不需要声明为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)什么情况下使用内部类
         典型的情况是,内部类继承自某个类或实现某个接口,内部类的代码操作创建其的外层类的对象。所以你可以认为内部类提供了某种进
    入其外层类的窗口。
        使用内部类最吸引人的原因是:每个内部类都能独立地继承自一个(接口的)实现,所以无论外层类是否已经继承了某个(接口的)实
    现,对于内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。从这个角
    度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了“多重继承”。
       (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();
    }
           per.speak()可调用,而per.say()不能调用,这时因为per是Person对象,要想调用子类的方法,可以强制向下转型为:((Boy) per).say();或者直接改为Boy per = new Boy();。从中可发现,要想调用内部类的自定义的方法,必须通过内部类的对象来调用。那么,匿名内部类连名字都没有,怎么调用内部类自定义的方法?
    (二)匿名内部类
          匿名内部类也就是没有名字的内部类正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写,但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口,但最多只能继承一个父类,或实现一个接口。
    关于匿名内部类还有如下两条规则:
        1)匿名内部类不能是抽象类,因为系统在创建匿名内部类的时候,会立即创建内部类的对象。因此不允许将匿名内部类定义成抽象类。
        2)匿名内部类不等定义构造器(构造方法),因为匿名内部类没有类名,所以无法定义构造器,但匿名内部类可以定义实例初始化块,
        怎样判断一个匿名类的存在啊?看不见名字,感觉只是父类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() ;
    }
    
         先看一个例子,体会一下匿名内部类的用法:

        运行结果: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();
    }











    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,953
精华内容 2,781
关键字:

内部类和匿名内部类