有人可以在Java中解释这个含义
public class Test{
// instance variables go here...
protected static Test mtest;
// methods go here
}
我试图掌握mtest所代表的内容。我知道在Java中创建一个对象的实例我必须使用new关键字,但是这里没有使用它。
在同一课程中,我可以采取以下行动:
mtest.someMethod();
这让我相信这类似于在C ++中使用this指针,例如
this->aMemberFunction();
有人可以解释一下受保护的静态测试mtest的含义吗?
这不是问题的重复:"为什么要避免在Java中使用受保护的静态"
答案 0 :(得分:1)
正如你所说,它类似于C ++中的指针。但是,由于您没有初始化它,调用方法或访问它的字段将导致NullPointerException
被抛出。
编译器允许您编写mtest.someMethod();
,因为编译器信任您在程序运行时最终会初始化mtest
。如果你不这样做,就像我刚才说的那样,你会得到NullPointerException
。
要避免此NullPointerException
,您需要使用mtest
关键字创建新对象并将其分配到new
:
mtest = new Test();
答案 1 :(得分:0)
正如您已经猜到的那样,这是对定义class Test
的实例的引用。典型的用例是单例模式,其中您只有一个类的实例,并且可以防止私有构造函数创建其他实例。
public class Test {
private static final Test mtest = new Test();
private Test() { ... }
public static void method() { /* do something using mtest */ }
}
答案 2 :(得分:0)
由于您声明了一个类,因此您可以在其中使用此类的类型。
或者换句话说,您可以将任何测试或它的子实例(IS-A规则,任何扩展测试的类)分配到mtest
字段:
public class Test{
//default constructor already present when we don't specify our own
protected static Test mtest = new Test();
}
如果您没有为此字段指定任何内容,则它将为null
public class Test{
protected static Test mtest; // null
}
因此,自从我们解决了关于字段类型的问题后,我们来谈谈静态和受保护的修饰符。
静态意味着字段在jvm加载的类之后正确初始化,因为静态
field属于class本身,我们可以使用它的类名Test.mtest
当我们定义静态方法时,同样的规则在这里,我们以相同的方式使用它Test.doSomething()
换句话说,类就像特殊类型的对象我们能够调用方法或指定它的字段但是
也可以像蓝图一样使用它来创建实例。 (像js中的原型)
但是从静态的角度来看,我们无法使用静态内容中的实例方法
没有创建任何一个实例,我们只有类,因为实例方法呈现this
。它被传递给每个实例方法,但它隐藏在开发人员和静态this
中不存在。
protected意味着您希望从扩展的不同包中进行分类测试能够访问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
调用value(function)
为了创建新实例,我们需要传递新创建实例的对象
将在新实例本身找不到它们时搜索方法
fooCat = Cat.new(Cat, "foo");
barCat = Cat.new(Cat, "bar");
首先,在对象fooCat中,我们尝试按键printName
查找函数并执行它。
为什么我们需要将foocat传递给foocat printName
函数?这只是一个地方
名称“foo”存在的是fooCat对象!
第二步当fooCat没有在键值对中找到该键(printName)时fooCat看到它的原型
(我们之前通过语言setPrototype()
特殊功能在构造函数中分配的行为)
fooCat在Cat中查找函数并将其传递给它自己。
在该函数中,来自传递的引用函数试图通过键name
获取字符串值并将其传递给print方法。
在fooCat对象中,按键name
将存储值“foo”和“foo”。
fooCat.printName(fooCat);
<强> STATIC 强>
尝试从fooCat实例执行averageCatLifeInYears()方法 我们不需要传递fooCat来运行 像前面的例子一样,或者甚至更多我们能够从Cat类调用它 本身没有任何Cat类实例!
Cat.averageCatLifeInYears() // no value passed to method
或者,fooCat尝试按名称查找方法,然后在Cat类中找到它
那个方法STATIC我们不需要任何实例
传递给它,我们从中检索唯一的信息,如上例所示:
fooCat.averageCatLifeInYears(); // no value passed, this method is static
在我们向世界出现这种语言后,许多开发人员开始抱怨 关于语言详细程度,我们决定添加一些语法糖和隐藏 哑巴将自己传递给每个函数作为第一个参数。 在传递了被称为方法的对象的帮助下介绍全新的::运算符 作为该方法的第一个参数。 通过这种方式,我们将它隐藏在场景背后,但即使我们看不到它,它仍然保留在它的位置。
fooCat = Cat::new(Cat, "foo");
fooCat = Cat::new(/*this hides here*/ "foo");
因为我们隐藏了详细程度,现在方法看起来一样,但是在printnName()方法中存在 这两种方法有不同的上下文,在java中,averageLatLifeInYears()将标记为STATIC
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()
并尝试从我们得到名称调用需要参数(THIS)的方法
我们在运行时遇到错误,或者在java等更智能的语言中出现COMPILE错误。