Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 当实例变量与类同名时_Java_Java 8 - Fatal编程技术网

Java 当实例变量与类同名时

Java 当实例变量与类同名时,java,java-8,Java,Java 8,有人能用Java解释一下这句话的意思吗 public class Test{ // instance variables go here... protected static Test mtest; // methods go here } 我试图理解mtest所代表的领域。我知道在Java中,要创建一个对象的实例,我必须使用new关键字,但是这里没有使用这个关键字 在同一类中,我可以执行以下操作: mtest.someMethod(); 这使我

有人能用Java解释一下这句话的意思吗

 public class Test{
     // instance variables go here...

     protected static Test mtest;

     // methods go here
 }
我试图理解mtest所代表的领域。我知道在Java中,要创建一个对象的实例,我必须使用new关键字,但是这里没有使用这个关键字

在同一类中,我可以执行以下操作:

   mtest.someMethod();

这使我相信这与C++中的这个指针的用法类似,例如

   this->aMemberFunction();
有人能解释一下受保护的静态测试mtest是什么意思吗


这不是一个问题的重复:“为什么要避免在java中使用受保护的静态”

,正如你所说的,C++中的指针类似。但是,由于您没有初始化它,因此调用它的方法或访问它的字段将导致抛出
NullPointerException

编译器允许您编写
mtest.someMethod()mtest
。如果不这样做,正如我刚才所说,您将得到一个
NullPointerException

要避免出现这种
NullPointerException
,您需要创建一个新对象,并使用
new
关键字将其分配给
mtest

mtest = new Test();

正如您已经猜到的,这是对定义
类测试的一个实例的引用。典型的用例是使用singleton模式,在这种模式中,您只有一个类的实例,并且可以防止私有构造函数创建额外的实例

public class Test {
    private static final Test mtest = new Test();
    private Test() { ... }
    public static void method() { /* do something using mtest */ }
}

由于您声明了一个类,所以可以在其中使用该类的类型。 或者换句话说,您可以将任何测试或其子实例(规则,扩展测试的任何类)分配给
mtest
字段:

 public class Test{

     //default constructor already present when we don't specify our own 
     protected static Test mtest = new Test();

 }
当您不为此字段分配任何内容时,它将为空

public class Test{

     protected static Test mtest; // null

 }
既然我们已经解决了关于字段类型的问题,那个么让我们来谈谈静态修饰符和受保护修饰符。 静态意味着在jvm加载类之后立即初始化该字段,因为静态 字段属于类本身,我们可以将其与类的名称一起使用,即
Test.mtest
当我们定义静态方法时,这里有相同的规则,我们以相同的方式使用它
Test.doSomething()
换句话说,类就像是一种特殊的对象,我们可以调用方法或分配它的一个字段,但 还可以像blueprint一样使用它来创建实例。(类似于js中的原型) 但是我们不能从静态内容使用实例方法,因为从静态的角度来看 没有创建任何实例,我们只有类,因为在实例中提供了
this
方法。它被传递给每个实例方法,但它对开发人员隐藏,在静态
中,这个
不存在。
受保护意味着您希望从扩展测试的不同包中进行分类,以便能够访问
mtest
字段 但测试包之外没有一个类不能看到mtest字段

静态和非静态上下文。

当我们删除所有语法时,请尝试理解 静态而非静态的低层上下文将是这样的(称为基于原型的oop,这是js、lua等语言处理oop的方式)

对于建模类和实例,我们只需要一个行为类似于Map(键值对)和函数的结构:

让我们定义类型(对象)cat,我们需要生成其中的许多 因为我们想养很多猫,所以我们需要一个存放的地方 独特性 这个地方将是单独的对象{}

Cat = {
    new = (this, name) -> {         
        newCat = {};                //create empty object {}
        newCat.name = name;         //assign to key name of this object value name
        setPrototype(newCat, this)  // assign where is newCat will search for keys (Cat object)  
                                    //when it's no able to find it in ourself 
        return newCat;              // return newly created cat
    }

// THIS passed to method, it's method like instance method in java but in java THIS is hidden
    printName = (this) -> {         
        print ("hello " .. this.name)
    },

// no THIS keyword here, same as static methods in java
    averageCatLifeInYears = () -> { 
        print(10);
    }


};
实例

工作原理: 我们有一个Cat对象,其行为类似于java中的map,为key
new
调用值(函数) 对于创建新实例,我们需要传递新创建实例所在的对象 当新实例本身找不到方法时,将搜索这些方法

fooCat = Cat.new(Cat, "foo");  
barCat = Cat.new(Cat, "bar");
首先,在对象fooCat中,我们试图通过键
printName
找到函数并执行它。 为什么我们需要将foocat传递给foocat
printName
函数?因为只有一个地方 出现的名称“foo”是fooCat对象! 第二步,当fooCat在键值对中找不到该键(printName)时,fooCat将查看其原型 (我们之前在构造函数中通过语言
setPrototype()
特殊函数指定的行为) fooCat在Cat中找到函数,并将引用传递给它自身。 在该函数中,从传递的引用函数尝试通过键
name
获取字符串值,并将其传递给打印方法。 在fooCat对象中,通过键
name
将打印存储值“foo”和“foo”

 fooCat.printName(fooCat); 
静态

正在尝试从fooCat实例执行averageCatLifeInYears()方法 我们不需要将fooCat传递给函数 就像前面的例子一样,我们甚至可以从Cat类调用它 本身没有任何Cat类实例

Cat.averageCatLifeInYears() // no value passed to method
或者,fooCat尝试按名称查找方法并在Cat类中查找它,因为 该方法是静态的,我们不需要任何实例
传递给它,我们从中检索唯一信息,如前一个示例中所示:

 fooCat.averageCatLifeInYears(); // no value passed, this method is static
在我们将这种语言推向世界后,许多开发人员开始抱怨 关于语言的冗长,我们决定添加一些语法糖和隐藏 这个哑函数将自己作为第一个参数传递给每个函数。 我们引入了全新的::操作符,借助于我们传递的对象,我们从中调用方法 作为该方法的第一个参数。 通过这种方式,我们将其隐藏在场景后面,但它仍然保留在原来的位置上,即使我们看不到它

fooCat = Cat::new(Cat, "foo");  
fooCat = Cat::new(/*this hides here*/ "foo"); 
由于我们隐藏了详细信息,所以这些方法现在看起来是一样的,但这存在于printname()方法中 这两个方法具有不同的上下文,在java中,averageCatLifeInYears()将被标记为静态

fooCat::printName(); 
Cat::averageCatLifeInYears();
那么,为什么在java中我们不能使用静态的实例上下文呢? 尝试重写我们的Cat类,以便在java中对此进行建模

Cat = {
    new = (this, name) -> {         
        newCat = {};                
        newCat.name = name;         
        setPrototype(newCat, this)  
        return newCat;              
    },


    printName = (this) -> {  // need instance where is placed name to work
        print ("hello " .. this.name)
    },

    //tryint to invoke instance context from static
    averageCatLifeInYears = () -> { 
        print(10);
        //lets try to invoke printName from this method...
        printName(?????) // WHAT WE NEED TO PLACE HERE???
    }
};
因为我们能够从Cat调用
averageCatLifeInYears()
,而无需任何参数 并试图调用metho