java - java.lang.NullPointerException 正在生成
问题描述
为什么会发生以下情况,我如何在以下情况下使用它EnglishHomepage
?
我的代码(不工作):
public class EnglishHomepage {
WebDriver driver = null;
public Actions action = new Actions(driver);
By login_button = By.xpath("//*[@id=\"wrapper\"]/div[1]/header/div[2]/div[1]/div/a[15]");
//constructor of EnglishHomepage
public EnglishHomepage (WebDriver driver) {
this.driver = driver;
}
public void clickFogotPassword() {
driver.findElement(login_button ).click();
}
public void clickDropdownValue() {
action.doubleClick(driver.findElement(xpath2)).perform();
}
}
代码(工作)
public class EnglishHomepage {
WebDriver driver = null;
By login_button = By.xpath("//*[@id=\"wrapper\"]/div[1]/header/div[2]/div[1]/div/a[15]");
//constructor of EnglishHomepage
public EnglishHomepage (WebDriver driver) {
this.driver = driver;
}
public void clickFogotPassword() {
driver.findElement(login_button ).click();
}
public void clickDropdownValue() {
**Actions action = new Actions(driver);**
action.doubleClick(driver.findElement(xpath2)).perform();
}
}
我可以public Actions action = new Actions(driver);
在该clickDropdownValue
方法下使用,并且测试按预期工作正常。
然而,
当我public Actions action = new Actions(driver);
在课堂下移动时,可以看到java.lang.NullPointerException
。
例外
在 java.util.Objects.requireNonNull(Objects.java:203) 在 org.openqa.selenium.interactions.Actions.(Actions.java:65) 在 pages.EnglishHomepage.(EnglishHomepage.java:12) 在 testcases.Tc4_Market_status。在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 处单击 (Tc4_Market_status.java:27)在 java.lang.reflect.Method.invoke(Method.java:498) 在 org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:133) 在 org.testng.internal.TestInvoker.invokeMethod(TestInvoker.java:584 ) 在 org.testng.internal.MethodRunner 的 org.testng.internal.TestInvoker.invokeTestMethod(TestInvoker.java:172)。runInSequence(MethodRunner.java:46) at org.testng.internal.TestInvoker$MethodInvocationAgent.invoke(TestInvoker.java:804) at org.testng.internal.TestInvoker.invokeTestMethods(TestInvoker.java:145) at org.testng.internal .TestMethodWorker.invokeTestMethods(TestMethodWorker.java:146) 在 org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:128) 在 java.util.ArrayList.forEach(ArrayList.java:1257) 在 org.testng.TestRunner。 privateRun(TestRunner.java:770) at org.testng.TestRunner.run(TestRunner.java:591) at org.testng.SuiteRunner.runTest(SuiteRunner.java:402) at org.testng.SuiteRunner.runSequentially(SuiteRunner.java :396) at org.testng.SuiteRunner.privateRun(SuiteRunner.java:355) at org.testng.SuiteRunner.run(SuiteRunner.java:304) at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:53) at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:96) at org.testng.TestNG.runSuitesSequentially(TestNG.java:1180) at org.testng.TestNG.runSuitesLocally(TestNG.java:1102) at org.testng.TestNG.runSuites(TestNG.java:1032) 在 org.testng.TestNG.run(TestNG.java:1000) 在 org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:115) 在 org.testng .remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251) 在 org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77)AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:115) at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251) at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77)AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:115) at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251) at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77)
解决方案
如果new Actions(driver)
位于构造函数之上,则在构造函数体之前执行,即 的值driver
仍然为空。
如果new Actions(driver)
位于构造函数的下方,则在构造函数体之后执行,即 的值driver
将是传递给构造函数的值。
建议:在字段初始化器中,永远不要使用在自己的初始化器中未完全初始化的另一个字段,也永远不要使用稍后声明的字段。
正确的方法是在构造函数中初始化字段,其中值可用。
WebDriver driver; // No need to initialize to null, it's the default
public Actions action; // Don't initialize here
public EnglishHomepage (WebDriver driver) {
this.driver = driver;
this.action = new Actions(driver);
}
更新
实际上,根据 Java 语言规范第12.5节,向下移动字段声明不应该奏效。新类实例的创建,它指定了这个初始化顺序(释义):
分配内存并调用构造函数,其评估如下:
如果此构造函数以 开头
this(...)
,则调用另一个构造函数。使用这些相同的步骤递归地处理该构造函数调用。否则,调用超类构造函数,或者使用
super(...)
语句指定,或者隐式调用无参数超类构造函数。执行该类的实例初始化程序和实例变量初始化程序,将实例变量初始化程序的值分配给相应的实例变量,按照它们在源代码中以文本形式出现的从左到右的顺序。
执行此构造函数的其余部分。
可以看出,根据规范,构造函数主体(除了this(...)
and )总是最后执行,因此将字段声明向下移动到构造函数下方不应该改变字段在初始化字段时super(...)
的事实。driver
null
action
上面给出的建议是要走的路。
推荐阅读
- javascript - 我怎样才能模式匹配 ID 只确保变量编号匹配而不必硬编码所有的可能性?
- html - 有没有办法用输入字段的自定义图像背景替换默认选择文件图标?
- javascript - Javascript Sum 仅返回一次迭代
- compiler-construction - 计算一组指令的依赖图
- ios - 在 Swift 中将可访问性“accessibilityIgnoresInvertColors = true”分配给颜色 - SmartInvert [iOS]
- arrays - 为什么我的循环在 C 中的第一个参数(argv 的字符)处停止?
- python - python深度学习问题中找不到数据适配器错误
- python - 使用 Selenium 抓取 Web 词库
- python - try/except 语句在哪里出错了
- html - Bootstrap - 当父母不居中或全宽时居中孩子