精华内容
下载资源
问答
  • 闭包内部类中英文社区中,比较常见对闭包定义是引用了自由变量一段代码或函数,被引用自由变量函数(一段代码)共同存在,即使离开了创造它环境内部类按照我理解,scala/java中虽然并不存在语法级地...

    闭包与内部类

    中英文社区中,比较常见的对闭包的定义是

    引用了自由变量的一段代码或函数,被引用的自由变量和函数(一段代码)共同存在,即使离开了创造它的环境

    内部类

    按照我的理解,scala/java中虽然并不存在语法级地支持或是定义,对于闭包而言,一些概念和闭包的概念一致。一般理解scala中的一些概念,我会倾向于从Java开始。

    Java中的内部类

    在java中,内部类有:

    成员内部类

    静态内部类

    局部内部类

    匿名内部类

    成员内部类

    class Outer1{

    private int a1;

    private static int s1;

    void f1() {

    }

    class Inner1{

    int a2;

    void f2(){

    //access outer's field,function

    int b=a1; //可以直接引用或是Outer1.this.a1;

    Outer1.this.f1();

    int c=Outer1.s1;

    }

    }

    }

    拿以上代码举例,成员内部类可以访问到外部类中的所有字段、方法,包括私有。

    内部类的实现均是通过编译器构造字节码实现的。上述类经过编译产生的类大概如下

    class Outer1{

    private int a1;

    private static int s1;

    void f1() {

    }

    static int access$000(Outer1 outer){

    return outer.a1;

    }

    int access$100(){

    return a1;

    }

    }

    class Inner1{

    int a1;

    final Outer1 this$0;

    Inner1(Outer1 outer){

    this.this$0=outer;

    }

    void f2(){

    int b=Outer1.access$000(this$0);

    this$0.f1();

    int c=Outer1.access$100();

    }

    }

    可以看到,在外部类中添加了相应的方法,给内部类调用来达到访问外部类的private成员或是方法的目的。在内部类中,会添加一个this$0的对外部对象的引用。

    静态内部类

    静态内部类并不具有内部类和外部类之间的依赖关系,静态内部类和在一个文件中写两个类没啥却别,一般用privat static内部类来隐藏实现。

    class SomeInterface{

    void function();

    }

    class SomeInterfaceFactory{

    private static class SomeInterfaceImpl implements SomeInterface{

    }

    static newInstance(){

    return new SomeInterfaceImpl()

    }

    }

    局部内部类

    内部类可以写在函数中,除了外部类的变量和方法外,内部类还可以访问到函数中的局部变量.

    class Outer3{

    int a1;

    void function(){

    int used=0;

    int notUsed=-1;

    class Inner3{

    void f2(){

    int t1=used;

    int t2=a1;

    }

    }

    }

    }

    上述代码构造出的类如下:

    class Outer3{

    int a1;

    void function(){

    int used=0;

    int notUsed=-1;

    }

    }

    class Inner3{

    final int val$used; //从这里看出不能对外部变量赋值

    final Outer3 this$0;

    Inner3(Outer3 outer,int a){

    this.this$0=outer;

    this.val$used=a

    }

    void f2(){

    int t1=val$used;

    int t2=this$0.a1;

    }

    }

    从上面可以看出,局部内部类除了像成员内部类那样添加了外部对象的引用,还添加了对引用到的局部变量的引用,并且这些属性会通过构造函数进行初始化。

    此外,在Inner3的f2中,不能执行类似used=10的操作,是因为这些引用是final的,当然,对于对象类型,对象内部还是可以修改的,scala中的局部内部类可以更改执行类似used=10的操作,就是这个原理。

    匿名内部类

    匿名内部类和局部内部类没有太大区别,只是生成的类的类名不含用户的标识。

    class Outer4{

    int a1;

    void function(){

    int used=0;

    int notUsed=-1;

    Runnable t=new Runnable() {

    @Override

    public void run() {

    int t1=used;

    int t2=a1;

    }

    };

    }

    }

    上述代码构造出的类如下:

    class Outer4{

    int a1;

    void function(){

    int used=0;

    int notUsed=-1;

    Runnable t=new Outer4$1();

    }

    }

    class Outer4$1 implements java.lang.Runnable{

    final int val$used;

    final Outer4 this$0;

    public void run(){

    //...

    }

    }

    总结

    除静态内部类外,java编译器会做以下事情:

    在内部类添加字段,类型是外部类,即内部对象持有外部类对象的引用。

    当内部类访问到外部类的private的属性时,编译器会在外部类中添加相应的getter/setter,内部类用它们对private属性访问。

    对局部内部类和匿名内部类而言,使用到的局部变量会转换为不可变的成员变量。

    Scala中的内部类

    scala中,内部类的实现与java基本一致,其中函数实现类似实现AbstractFunction接口的的匿名内部类。

    成员内部类

    成员内部类与java基本一致,对private属性的处理稍微有些不同,在scala中,其实所有成员变量均是private的,编译器自动为其添加相应的getter/setter,因此如果内部类访问了外部类的私有属性,则编译器只需调整相应的getter的访问权限。

    局部内部类

    局部内部类也与java基本一致,只是局部内部类中可以修改外部的局部变量。其实现原理也很简单,在局部变量外再包一层,如int改为IntRef,比如

    final int[] data=new int[1]

    data[0]=1 //set

    int tmp=data[0] //get

    匿名内部类

    scala中,除了像java那样定义匿名内部类外,函数实现也是匿名内部类实现。如函数

    class Outer4{

    private val a1=-1

    val f1: Int => Int = (a: Int) => a + 1

    val f2: Int => Int = (a: Int) => a + a1

    }

    会生成类似如下匿名内部类

    //对应f1

    public final class Outer4$$anonfun$3 extends scala.runtime.AbstractFunction1$mcII$sp implements scala.Serializable {

    public static final long serialVersionUID=0L;

    public final int apply(int){

    //计算逻辑

    }

    public Outer4$$anonfun$3(Outer4 outer){

    //...

    }

    }

    //对应f1

    public final class Outer4$$anonfun$3 extends scala.runtime.AbstractFunction1$mcII$sp implements scala.Serializable {

    public static final long serialVersionUID=0L;

    private final Outer4 $outer;

    public final int apply(int){

    //计算逻辑

    }

    public Outer4$$anonfun$3(Outer4 outer){

    //...

    }

    }

    从上面的例子来看,最大的不同是外部对象引用的不同,在某些情况下一个匿名内部类可能仅仅是'匿名类',通过测试验证,发现仅在以下情况下内部类会添加对外部类的引用:

    内部类访问了外部类的属性

    内部类访问了外部类的方法

    还有一个问题,如果在函数A内部定义了函数B,函数B访问了函数A的局部变量,则函数B的匿名内部类会添加函数A的匿名内部类的引用吗?

    class Outer4{

    val a1=-1

    val fa=()=>{

    val local=a1

    val fb=()=>{

    println(local)

    }

    val fc=()=>{

    println(a1)

    }

    }

    }

    答案是否定的。

    在以上代码中,fb不会持有外部对象即fa的引用,fb对local引用被当作局部变量处理,

    这和上面java例子中Inner3对used变量的访问一致。

    fc会持有外部对象即fa的引用,这是因为fc访问了a1,相当于fa.outer.a1.

    总结

    scala中内部类的机制与java基本一致。

    scala借助匿名内部类实现函数对象,匿名内部类只有访问外部对象的方法或字段时才会持有外部对象的引用。

    2这一点想必是出于对函数或是闭包的支持,如果一个函数对象没有引用上下文的变量或函数,就持上下文的引用,也就无法形成闭包。因此从这个角度说,java匿名内部类或其他内部类,不是真正意义上的闭包。

    版本说明

    轮子|版本

    -|-

    java|1.8

    scala|2.11.12

    spark|2.2.0

    参考文档

    闭包

    https://github.com/ColZer/DigAndBuried/blob/master/spark/function-closure-cleaner.md

    b739ec46bb5c46d9c0aa4ce35ba1ea56.png

    关于找一找教程网

    本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。

    本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。

    [闭包与内部类]http://www.zyiz.net/tech/detail-136011.html

    展开全文
  • 下面说一说内部类(Inner Class)静态内部类(Static Nested Class)的区别:1) 非静态内部类有一个很大的优点:可以自由使用外部类的所有变量方法 。2) 静态内部类的作用:只是为了降低包的深度,方便类的...

          在Java代码的实现过程中,我们经常会使用内部类,内部类的使用也是非常多的,现在罗列一下当前的内部类的知识。

    下面说一说内部类(Inner Class)和静态内部类(Static Nested Class)的区别:
    1) 非静态内部类有一个很大的优点:可以自由使用外部类的所有变量和方法 。
    2) 静态内部类的作用:只是为了降低包的深度,方便类的使用,静态内部类适用于包含类当中,但又不依赖与外在的类,不用使用外在类的非静态属性和方法,只是为了方便管理类结构而定义。在创建静态内部类的时候,不需要外部类对象的引用。

    根据Oracle官方的说法:
    Nested classes are divided into two categories: static and non-static. Nested classes that are declared static are called static nested classes. Non-static nested classes are called inner classes.
    从字面上看,一个被称为静态嵌套类,一个被称为内部类。
    从字面的角度解释是这样的:
    什么是嵌套?嵌套就是我跟你没关系,自己可以完全独立存在,但是我就想借你的壳用一下,来隐藏一下我自己。
    因此,静态内部类的设计天生就是为建造者模式的设计开了一道门。

    (1)创建实例
       OutClass.InnerClass obj = outClassInstance.new InnerClass(); //注意是外部类实例.new,内部类
       AAA.StaticInner in = new AAA.StaticInner();//注意是外部类本身,静态内部类

    (2)内部类中的this
        内部类中的this与其他类一样是指的本身。创建内部类对象时,它会与创造它的外围对象有了某种联系,于是能访问外围类的所有成员,不需任何特殊条件,可理 解为内部类链接到外部类。 用外部类创建内部类对象时,此内部类对象会秘密的捕获一个指向外部类的引用,于是,可以通过这个引用来访问外围类的成员。

    (3)静态内部类
        关键字static中提到Static可以修饰成员变量、方法、代码块,其他它还可以修饰内部类,使用static修饰的内部类我们称之为静态内部类,不过我们更喜欢称之为嵌套内部类。静态内部类与非静态内部类之间存在一个最大的区别,我们知道非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围内,但是静态内部类却没有。没有这个引用就意味着:
    1、 它的创建是不需要依赖于外围类的。
    2、 它不能使用任何外围类的非static成员变量和方法。

    实现的代码如下:

    public class OutClassType {

    private int age;
    private int year;

    public static void test(){
    System.out.println("OutClassType data.");
    }

    public class InnerNormalClass{
    private int a = 1;
    private int b = 2;

    public InnerNormalClass(){
    System.out.println("init the inner class");
    // 普通内部类可以通过this关键字无限访问外部类的成员变量
    System.out.println("direct read OutClassType age:"+OutClassType.this.age);

    test();
    }

    public int getA(){
    System.out.println("print A.");
    return a;
    }

    public int getB(){
    System.out.println("print B.");
    return b;
    }
    }


    public static class InnnerStaticClass{
    private int c = 15;
    private int d = 16;
    public int getC(){
    System.out.println("print C.");
    return c;
    }

    public int getD(){
    return d;
    }

    public static void testStaticMethod(){
    System.out.println("this is static inner class method.");
    }
    }

    public void printInnnerStaticClassData(InnnerStaticClass innnerStaticClass){
    System.out.println("print c:"+innnerStaticClass.c+",print d:"+innnerStaticClass.d);
    }

    public void printInnerNonStaticClassData(InnerNormalClass normalClass){
    System.out.println("print a:"+normalClass.a+",print b:"+normalClass.b);
    }



    public int getAge() {
    return age;
    }


    public void setAge(int age) {
    this.age = age;
    }


    public int getYear() {
    return year;
    }


    public void setYear(int year) {
    this.year = year;
    }
    }

    测试代码如下所示:

    private static void testInnerClass(){
    OutClassType outClassType = new OutClassType();
    // 非静态的内部类的初始化只能使用outClassType.new的方式生成
    OutClassType.InnerNormalClass innerNormalClass = outClassType.new InnerNormalClass();
    // 使用内部类的对象访问内部类成员变量
    System.out.println("print the inner method:"+innerNormalClass.getA());

    // 静态内部类的初始化和和非静态内部类的初始化不一样,因为不管是静态变量还是静态内部类都是外部类直接所有
    OutClassType.InnnerStaticClass innnerStaticClass = new OutClassType.InnnerStaticClass();
    System.out.println("print the static class non static method:"+innnerStaticClass.getC());
    // 直接调用静态内部类的静态方法
    OutClassType.InnnerStaticClass.testStaticMethod();

    // 外部类的方法中也可以访问静态内部类的私有属性
    outClassType.printInnnerStaticClassData(innnerStaticClass);

    // 外部类的方法中也可以访问非静态内部类的私有属性
    outClassType.printInnerNonStaticClassData(innerNormalClass);

    }

    测试结果如下所示:

    init the inner class
    direct read OutClassType age:0
    OutClassType data.
    print A.
    print the inner method:1
    print C.
    print the static class non static method:15
    this is static inner class method.
    print c:15,print d:16
    print a:1,print b:2


    展开全文
  • 内部存储器外部存储器的区别

    千次阅读 2017-02-23 09:42:00
    内部存储器外部存储器的区别: 所有的安卓设备都有外部存储内部存储,这两个名称来源安卓的早期设备,那个时候的设备内部存储确实是固定的,而外部存储确实是可以像U盘一样移动的。但是在后来的设备中,很多...

    内部存储器与外部存储器的区别:

    所有的安卓设备都有外部存储和内部存储,这两个名称来源于安卓的早期设备,那个时候的设备内部存储确实是固定的,而外部存储确实是可以像U盘一样移动的。但是在后来的设备中,很多中高端机器都将自己的机身存储扩展到了8G以上,他们将存储在概念上分成了”内部internal” 和”外部external” 两部分,但其实都在手机内部。所以不管安卓手机是否有可移动的sdcard,他们总是有外部存储和内部存储。最关键的是,我们都是通过相同的api来访问可移动的sdcard或者手机自带的存储(外部存储)。

     


    外部存储虽然概念上有点复杂,但也很好区分,你把手机连接电脑,能被电脑识别的部分就一定是外部存储。

    内部存储器:

    • Android系统能够直接把文件存在设备的内部存储内。
    • 默认情况下,保存在内部存储内的文件是应用程序私有的,其他应用程序(或用户)是无法访问的。
    • 当用户卸载此应用程序时,内部存储的数据会一并清除。
    • Shared Preferences和SQLite数据库都是存储在内部存储空间上的。内部存储一般用Context来获取和操作。
    • 内部存储一般保存在“/data/data”目录下

    外部存储器:

      • 使用sdcard存储的数据,不限制只有本应用访问,任何可以有访问Sdcard权限的应用均可以访问,而Sdcard相对于设备的内部存储空间而言,会大很多,所以一般比较大的数据,均会存放在外部存储中。
      • 要向外部存储器写入数据,你必须在清单文件中申请WRITE_EXTERNAL_STORAGE权限
      • 外部存储中的文件是可以被用户或者其他应用程序修改的,有两种类型的文件(或者目录):
        • .公共文件Public files:文件是可以被自由访问,且文件的数据对其他应用或者用户来说都是由意义的,当应用被卸载之后,其卸载前创建的文件仍然保留。比如camera应用,生成的照片大家都能访问,而且camera不在了,照片仍然在。
        • 私有文件Private files:其实由于是外部存储的原因即是是这种类型的文件也能被其他程序访问,只不过一个应用私有的文件对其他应用其实是没有访问价值的(恶意程序除外)。外部存储上,应用私有文件的价值在于卸载之后,这些文件也会被删除。类似于内部存储。
      • 外部存储一般保存在“/mnt/sdcard/Android/data/”下。

    转载于:https://www.cnblogs.com/loaderman/p/6432013.html

    展开全文
  • 内部类可以引用定义在它嵌套外部类中数据方法,所以不需要将外部类对象引用传递给内部类构造方法,因此,内部类可以拿程序简单简洁。 声明用可见性修饰符声明内部类,遵从应用一般类成员可见性规则...

    内部类有如下特征:

    1. 内部类被编译成名为OuterClassName$InnerClassName.class的类。
    2. 内部类可以引用定义在它嵌套的外部类中的数据和方法,所以不需要将外部类对象的引用传递给内部类的构造方法,因此,内部类可以拿程序简单和简洁。
    3. 声明用可见性修饰符声明内部类,遵从应用于一般类成员的可见性规则。
    4. 可以将内部类声明为static。一个static内部类可以使用外部类的名字访问。一个static类是不能访问外部类的非静态成员的。
    5. 内部类的对象经常在外部类中创建。但是也可以从另一个类中创建一个内部类的对象。如果该内部是非静态的,就必须先创建一个外部类的实例,然后用下面的语法创建一个内部类的对象:
      Java代码
      1. OuterClass.InnerClass innerObject = OutObject.new Innerclass()  
       .如果内部类是静态的,那么使用下面的语法为它创建一个对象:
      Java代码
      1. OuterClass.InnerClass innerObject = new OutObject.Innerclass()   

    匿名内部类是一种特殊的内部类,所以有很多方面都应把它当作内部类对待。除此之外,它还不以下特征。

    1. 匿名内部类必须是扩展父类或实现接口的。但是它不能有明确的extends或implements语句。
    2. 匿名内部类必须实现父类或接口中所有的抽象方法。
    3. 匿名内部类总是使用父类的无参数构造方法来创建实例。如果匿名内部类实现了接口,构造方法就是Object().
    4. 匿名内部类编译为名为OuterClassName$n.class的类。如,如果外部类Test有两个匿名类,那么它们就编译成Test$1.class和Test$2.class。

    总结:在Activity内部定义的一个AsyncTask,它属于一个内部类,该类本身和外面的Activity是有引用关系的,如果Activity要销毁的时候,AsyncTask还仍然在运行,这会导致Activity没有办法完全释放,从而引发内存泄漏。
    展开全文
  • SQL数据库中模式、外模式概念模式的区别和概念 外模式 外模式又称子模式或用户模式,对应用户级。它是某个或某几个用户所看到的数据库的数据视图,是某一应用有关的数据的逻辑表示。外模式是从模式导出的一...
  • 连接并非等同等值连接,因为还有非等值连接情况 ^_^那么正确结论应该是:连接 =(等值连接+非等值连接):CREATE TABLE PERSONS(ID NUMBER(10) PRIMARY KEY ,LASTNAME VARCHAR2(20),FIRSTNAME VARCHAR2(20)...
  • 并介绍了static静态内部类的关系、静态内部类匿名内部类的区别 一、static关键字 static关键子可以修饰方法、成员变量、类,分别对应: 静态方法:静态方法不依赖任何对象就可以进行访问,对于静态方法来说...
  • 非静态内部类能够访问外部类静态非静态成员 静态内部类不依赖外部类实例,直接实例化内部类对象;非静态内部类通过外部类对象实例生成内部类对象 【Java面试题答案】整理推...
  • Java 静态内部类 内部类区别

    千次阅读 2018-05-30 10:52:37
    静态内部类作用:只是为了降低包深度,方便类使用,静态内部类适用包含类当中,但又不依赖外在类,不用使用外在类非静态属性方法,只是为了方便管理类结构而定义。在创建静态内部类时候,不需要...
  • 片内外设片外外设的区别: 片、外设是两个概念,片指做成芯片的集成电路内部,简称片,片外同理显而易见;外设是外部设备的简称,是指集成电路芯片外部的设备。集成电路芯片外部设备的连接一般需要专门的...
  • func new(Type) *Type ... new 相同是,其第一个实参为类型,而非值。不同是,make 返回类型 与其参数相同,而非指向它指针。其具体结果取决具体类型: slice:参数size指定了它长度,该
  • jspservlet的区别与联系 jspservlet的区别和联系: JSP的本质就是Servlet,JVM只能识别java的类,不能识别JSP的代码,Web容器将JSP的代码编译成JVM能够识别的java类 jsp表现页面显示,servlet是逻辑控制. ...
  • ECMA-262 把原生对象(native object)定义为“独立宿主环境 ECMAScript 实现提供对象”,宿主无关,在javascript(远景浏览器)、nodejs(node平台)、jscript(ie浏览器)、typescript(微软平台)等等中...
  • 8088/8086含4个16位数据寄存器,又可分为8个8位寄存器,即:数据寄存器特有习惯用法:AX:累加器,所有I/O指令都通过AX接口传送信息,中间运算结果也多放AX中;BX:基址寄存器,在间接寻址中用于存放基地址;...
  • 展开全部联系:线性...区别:一、指代不同1、线性空间:解析几何里引入向量概念后,使许多问题处理变得更为简洁清晰,在此基础上进一步抽象化,形成了域相联系向量空间概念。2、欧氏空间:是一个特别...
  • findgrep用法和区别 findgrep区别 find:相当windows中搜索,用来搜索文件 grep:用来搜索文本,搜索文件内部中文字内容 find用法 语法: 格式: find [path] [-options] [操作expression] ...
  • 数据库 基本表视图关系与区别

    千次阅读 2018-02-28 14:06:46
    数据库 基本表视图关系与区别 视图又叫虚表,就是事实上并不存在表,它是由多或一个基本表或视图导出表。 基本表是实实在在存在表,它被用来储存数据库数据。 数据库三层模型,由上到下为外模型,...
  • jspservlet的区别和联系: jsp经编译后就变成了Servlet. (JSP的本质就是Servlet,JVM只能识别java的类,不能识别JSP的代码,Web容器将JSP的代码编译成JVM能够识别的java类) jsp更擅长表现页面显示,servlet更擅长...
  • SessionCookie的区别与联系 一. 概念理解 你可能有留意到当你浏览网页时,会有一些推送消息,大多数是你最近留意过的同类东西,比如你想买桌子,上淘宝搜了一下,结果连着几天会有各种各样的桌子的链接。这是因为 ...
  • HBase Hive 的区别,我们简单的梳理一下 Hive HBase 的应用场景: Hive 适合用来对一段时间内的数据进行分析查询,例如,用来计算趋势或者网站的日志。Hive 不应该用来进行实时的查询(Hive 的设计目的,也...
  • 在Vue的内部指令中,v-showv-if的区别 v-if 根据表达式的值true或false在DOM中生成或者移除一个元素(或多个元素)。有点类似JavaScript中的if条件判断。在Vue中除了v-if也有v-else-ifv-else之类; v-show 除了v...
  • 静态内部类非静态内部类区别

    千次阅读 2016-04-21 17:23:34
    静态内部类可以创建静态成员,而非静态内部类不可以,原因:内部类相当外部类一个属性,非静态内部类中如果可以使用静态成员,但是非静态内部类是相当非静态成员,是在类实例化时候才可以使用,所以在...
  • Postman中ParamsBody参数的区别

    千次阅读 2020-04-06 12:44:54
    这里写自定义目录标题欢迎使用Markdown编辑器新改变功能快捷键合理创建标题,有助目录生成如何改变文本样式插入链接图片如何插入一段漂亮代码片生成一个适合你列表创建一个表格设定内容居中、居左、...
  • synchronized 表示只有一个线程可以获取作用对象的锁,执行代码,阻塞其他线程。 volatile 表示变量在 CPU 的寄存器中是不确定的,...synchronized 可以保证线程间的有序性(猜测是无法保证线程内的有序性,即线程...
  • 说进程线程的区别 在理解进程线程概念之前首选要对并发有一定的感性认识,如果服务器同一时间只能服务一个客户端,其他客户端都再那里傻等的话,可见其性能的低下估计会被客户骂出翔来,因此并发编程...
  • 原标题:浅谈HbaseHive的区别以及分别适用的场景(附大数据资料)HbaseHive都是大数据处理的重要工具,但两者在大数据架构中处于不同位置,Hbase主要应用实时数据查询问题,Hive则主要解决数据处理计算方面...
  • 内部类外部类联系:内部类可以访问外部类所有方法属性,如果内部类外部类有相同成员方法成员属性,内部类成员方法调用要优先外部类即内部类优先级比较高(只限于类内部,在主方法,内部类对象不...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,919
精华内容 1,167
关键字:

于内和与内的区别