zoukankan      html  css  js  c++  java
  • Java学习笔记-内部类

    内部类在Android中有着大量的运用

    内部类

    内部类提供了更好的封装;内部类可以直接访问外部类的私有数据;匿名内部类适合那些只需要使用一次的类。非静态内部类不能拥有静态成员。内部类比外部类可以多使用三个修饰符:private、protected、static

    将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类,嵌套类)

    访问特点:

    • 内部类可以直接访问外部类中的成员,包括私有成员
    • 而外部类要访问内部类中的成员必须要建立内部类的对象

    内部类的位置

    内部类定义在成员位置上

    • 可以被private static成员修饰符修饰
    • 被static修饰的内部类只能访问外部类中的静态成员

    内部类定义在局部位置上

    • 也可以直接访问外部类中的成员
    • 同时可以访问所在局部中的局部变量,但必须是被final修饰

    非静态内部类

    • 成员内部类是类的成员而局部内部类和匿名内部类则不是
    • 使用ClassName.this.Xxx来调用外部类的重名变量
    • 内部类可以访问外部类的private变量,反之则不行。如果外部类要访问内部类的成员话,则必须显式创建非静态内部类对象来调用访问其实例成员
    • 不允许在非静态内部内定义静态成员
      外部类名.内部类名 变量名 = 外部类对象.内部类对象;
      Outer.Inner in = new Outer().new Inner();
    class Outer {
    
    	private int x = 3;
    
    	class Inner {
            int x = 4;
    		void function() {
                int x = 5;
    			System.out.println("outer x: " + Outer.this.x);
    		}
    	}
    }
    

    静态内部类

    • 用static修饰的内部类,属于类本身
    • 可以包含静态成员也可以包含非静态成员
    • 静态内部类不能访问外部类的实例成员只能访问外部类的类成员。即使是静态内部类的实例方法也不能够访问外部类的实例成员
    • 外部类访问内部类的类成员可以使用类名调用,而实例成员可以通过实例调用
    • 当内部类中定义了静态成员,该内部类必须是static的
      new Outer.Inner().function();
    class Outer {
    
    	private static  int x = 3;
    	
        static class Inner {//静态内部类
    		static void function(){
    			System.out.println("innner :"+x);
    		}
    	}
    }
    

    内部类的使用

    • 接口内定义的内部类都为public static修饰的
    • 内部类的使用:
      1. 在外部类中使用内部类
      2. 在外部类中以外使用非静态内部类
        • 此时内部类不可使用private修饰
        • OuterClass.InnerClass varName
        • OuterInstance.new InnerConstructor()
        class Out{
        	class In{
        		public In (String s){···}
        	}
        }
        ···
        Out.In in = new Out().new In("test");
        //等价于
        Out.in in;
        Out out = new Out();
        in = out.new In("test");
        ···
        
        • 非静态内部类的构造器必须使用外部对象来调用。
        public class SubClass extends Out.In{
        	//显示定义SubClass的构造器
        	public SubClass ( Out out ){
        		//通过传入的Out对象显式调用In的构造器
        		out.super("hello");
        	}
        }
        
      3. 在外部类以外使用静态内部类
        • new OuterClass.InnerConstructor()
        class StaticOut{
        	static class StaticIn{
        		public StaticIn(){···}
        	}
        }
        ···
        StaticOut.StaticIn in = new StaticOut.StaticIn();
        //等价于
        StaticOut.StaticIn in;
        in = new StaticOut.StaticIn();
        

    局部内部类

    • 若一个类存在于方法体中,则这个类称之为局部内部类,仅在该方法内有效。局部内部类不能在外部类的方法以外的地方使用,因此不能够使用static修饰
    class Outer {
    
    	int x = 3;
    
    	void method(final int a) {
    		final int y = 4;
    		class Inner {
    			void function() {
    				System.out.println(y);
    			}
    		}
    		new Inner().function();
    	}
    }
    
    class Test {
    
    	public static void main(String[] args) {
    		Outer out = new Outer();
    		out.method(7); //当此语句执行完毕,释放内存
    		out.method(8); 
    	}
    }
    

    匿名内部类

    就是内部类的简化写法

    前提:

    • 内部类可以继承或实现一个外部类或者接口

    格式为:

    • new 外部类名或者接口名(){覆盖类或者接口中的代码,(也可以自定义内)}

    简单理解:

    • 就是建立一个建立一个带内容的外部类或者接口的子类匿名对象
    1. 匿名内部类其实就是内部类的简写格式
    2. 定义匿名内部类的前提:内部类必须是继承一个类或者实现接口
    3. 匿名内部类的格式:new 父类或者接口(){定义子类的内容}
    4. 其实匿名内部类就是一个匿名子类对象。可以理解为带内容的对象
    5. 匿名内部类中定义的方法最好不要超过3个
    abstract class AbsDemo {
    	abstract void show();
    }
    
    class Outer {
    	int x = 3;
    	public void function() {
    		new AbsDemo() {
    			int num = 9;
    			void show() {
    				System.out.println("num = " + num);
    			}
    			void abc() {
    				System.out.println("增加的方法");
    			}
    		}.show();
    	}
    }
    
    class Test {
    	public static void main(String[] args) {
    		new Outer().function();
    	}
    }
    

    匿名内部类的应用

    interface Inter {
    	void method();
    }
    
    class Test 
    {
    	//补足代码。通过匿名内部类。
    	/*
    	static class Inner implements Inter {
    		public void method() {
    			System.out.println("method run");
    		}
    	}
    	*/
    
    	static Inter function() {
    		return new Inter() {
    			public void method() {
    				System.out.println("method run");
    			}
    		};
    	}
    }
    
    class InnerClassTest {
    	public static void main(String[] args) {
    
    		//Test.function():Test类中有一个静态的方法function
    		//.method():function这个方法运算后的结果是一个对象。而且是一个Inter类型的对象
    		//因为只有是Inter类型的对象,才可以调用method方法
    		Test.function().method();
    		show(new Inter(){
    			public void method() {
    				System.out.println("method show run");
    			}
    		});
    	}
    
    	public static void show(Inter in) {
    		in.method();
    	}
    }
    

    没有父类及接口如何使用匿名内部类

    class InnerTest {
        public static void main(String[] args) {
    		new Object() {
    			public void function() {
    				//方法主体
    			}
    		}.function();
    	}
    }
    

    Java8改进的匿名内部类

    • 匿名内部类适合只使用一次的类,其定义格式为:
    new 实现接口() | 父类构造器(实参列表){
    	//匿名内部类的类体部分
    }
    
    • 匿名内部类不能是抽象类,因为在创建匿名内部类的同时会创建对象
    • 匿名内部类不能定义构造器。由于匿名内部类没有类名,但却可以使用初始化块
    • 最常用的创建匿名内部类的方式是需要创建某个接口类型对象
    interface Product{
    	public double getPrice();
    	public String getName();
    }
    public class AnonymousTest{
    	public void test ( Person p ){
    		System.out.println( "" + p.getName() + p.getPrice());
    	}
    	public static void main(String[] args){
    		AnonymousTest ta = new AnonymousTest();
    		ta.test(new Product(){
    			public double getPrice(){
    				return 123.4;
    			}
    			public String getName(){
    				return "书本";
    			}
    		});
    	}
    }
    
    class AnonymousProduct implements Product{
    	public double getPrice(){
    		return 123.4;
    	}
    	public String getName(){
    		return "书本";
    	}
    }
    ta.test ( new AnonymousProduct());
    
    • 在Java8以前,Java要求被局部内部类、匿名内部类访问的局部变量必须使用final修饰,从Java8开始这个限制被取消了:如果局部变量被匿名内部类访问,那么该局部变量相当于自动使用了final修饰
  • 相关阅读:
    一文读懂Lua元表
    React-Antd Pro环境搭建
    如何在QT项目中引入Boost库
    .NET Core RSA PKCS8 格式 签名/验签
    Chrome控制台Network请求过滤
    字符串拼接null值问题
    复制文件夹需要考虑的问题
    [闻缺陷则喜]关于boost的想法
    公共库开发组
    docker-compose 一键部署分布式配置中心Apollo
  • 原文地址:https://www.cnblogs.com/cj5785/p/10664861.html
Copyright © 2011-2022 走看看