原文地址http://blog.csdn.net/TalorSwfit20111208/article/details/77434950

由于无法联系上您,在此分享您的文章,希望谅解!

Appium PageObject 直接沿用了Selenium的PageObject设计模式,

PageObject主要优点如下:

一、将UI元素与逻辑分离方便后期维护

二、减少代码冗余

三、增强代码可读性

来看个例子

没有使用PO设计模式的代码如下:

  1. @Test
  2. public void twoPlusTwoOperation() {
  3. /* 获取控件*/
  4. MobileElement buttonTwo = (MobileElement)(driver.findElement(By.id("net.ludeke.calculator:id/digit2")));
  5. MobileElement buttonPlus = (MobileElement)(driver.findElement(By.id("net.ludeke.calculator:id/plus")));
  6. MobileElement buttonEquals = (MobileElement)(driver.findElement(By.id("net.ludeke.calculator:id/equal")));
  7. MobileElement resultField = (MobileElement)(driver.findElement(By.xpath("//android.widget.EditText[1]")));
  8. /* 计算2+2*/
  9. buttonTwo.click();
  10. buttonPlus.click();
  11. buttonTwo.click();
  12. buttonEquals.click();
  13. /* 检查在给定的时间内是否显示要查找的控件 */
  14. new WebDriverWait(driver, 30).until(ExpectedConditions.textToBePresentInElement(resultField, EXPECTED_RESULT_FOUR));
  15. }

使用了PO设计模式的代码如下

  1. @Test
  2. public void twoPlusTwoOperation() {
  3. app.calculatorScreen().addTwoAndTwo();
  4. assertTrue(app.calculatorScreen().isResultCorrect("4"));
  5. }

我们注意到的第一个最直接的变化是测试方法的长度。使用PageObject模式编写的测试方法几乎总是比原始的方法短(对于较长的测试而言更短)。如果你继续阅读,你会注意到,这不仅是因为我们在addTwoAndTwo方法中包装了所有的按钮。
可读性怎么样?再次通过这两种方法,问问自己在哪种情况下更容易理解发生了什么。另外,请注意我们如何在第二种方法中真的不需要注释,因为指定与Page Object具有的交互的方法具有重要的名称。
通过将低级操作包含在专用方法中,我们现在有了不直接引用任何WebDriver API的测试方法。在编写第一个PageObject测试方法时,请使用缺少引用低级API的导入语句作为根据模式进行处理的指标。
这种方法给了我们另一个不容忽视的优点:通过隐藏单一实用程序方法的技术复杂性,PageObject模式使得用户交互的流程变得明显。对于更长,更复杂的测试,以及我们编写测试的整个方式的转换,这特别有用。一旦实现了应用程序屏幕的基本交互,编写测试方法基本上只是通过调用正确名称所指的方法来复制用例。这就是为什么你应该努力为他们选择最好的名字。

PageObject控件定位

pageobject控件定位是使用注解方式来定位的,如下

# WebElement/列表 WebElement 字段可以这样定位:

使用@FindBy注解

  1. import org.openqa.selenium.support.FindBy;
  2. import org.openqa.selenium.WebElement;
  3. @FindBy(someStrategy)//用来定位浏览器或者webview UI
  4. //也可以用来定位native 应用,当没有定义其他定位策略时
  5. WebElement someElement;@FindBy(someStrategy) //用来定位浏览器或者webview UI
  6. //也可以用来定位native 应用,当没有定义其他定位策略时
  7. List<WebElement> someElements;//定位包含相同控件属性的控件

使用@AndroidFindBy来定位

  1. import io.appium.java_client.android.AndroidElement;
  2. import org.openqa.selenium.remote.RemoteWebElement;
  3. import io.appium.java_client.pagefactory.*;
  4. @AndroidFindBy(someStrategy) //用Android UI Automator来定位Android UI
  5. AndroidElement someElement;
  6. @AndroidFindBy(someStrategy) //用Android UI Automator来定位Android UI
  7. List<AndroidElement> someElements;

多种组合查找策略

  1. import org.openqa.selenium.remote.RemoteWebElement;
  2. import io.appium.java_client.pagefactory.*;
  3. import org.openqa.selenium.support.FindBy;
  4. import org.openqa.selenium.support.FindByAll;
  5. import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE;
  6. @HowToUseLocators(androidAutomation = ALL_POSSIBLE, iOSAutomation = ALL_POSSIBLE)
  7. @FindAll{@FindBy(someStrategy1), @FindBy(someStrategy2)})
  8. @AndroidFindBy(someStrategy1) @AndroidFindBy(someStrategy2)
  9. @iOSFindBy(someStrategy1) @iOSFindBy(someStrategy2)
  10. RemoteWebElement someElement;
  11. @HowToUseLocators(androidAutomation = ALL_POSSIBLE, iOSAutomation = ALL_POSSIBLE)
  12. @FindAll({@FindBy(someStrategy1), @FindBy(someStrategy2)})
  13. @AndroidFindBy(someStrategy1) @AndroidFindBy(someStrategy2)
  14. @iOSFindBy(someStrategy1) @iOSFindBy(someStrategy2)
  15. List<RemoteWebElement> someElements;

## 也可以用下面这种方式: 

  1. import org.openqa.selenium.remote.RemoteWebElement;
  2. import io.appium.java_client.pagefactory.*;
  3. import org.openqa.selenium.support.FindBy;
  4. import org.openqa.selenium.support.FindByAll;
  5. import static io.appium.java_client.pagefactory.LocatorGroupStrategy.CHAIN;
  6. import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE;
  7. @HowToUseLocators(androidAutomation = CHAIN, iOSAutomation = ALL_POSSIBLE)
  8. @FindAll{@FindBy(someStrategy1), @FindBy(someStrategy2)})
  9. @AndroidFindBy(someStrategy1) @AndroidFindBy(someStrategy2)
  10. @iOSFindBy(someStrategy1) @iOSFindBy(someStrategy2)
  11. RemoteWebElement someElement;
  12. @HowToUseLocators(androidAutomation = CHAIN, iOSAutomation = ALL_POSSIBLE)
  13. @FindAll({@FindBy(someStrategy1), @FindBy(someStrategy2)})
  14. @AndroidFindBy(someStrategy1) @AndroidFindBy(someStrategy2)
  15. @iOSFindBy(someStrategy1) @iOSFindBy(someStrategy2)
  16. List<RemoteWebElement> someElements;

或者

  1. import org.openqa.selenium.remote.RemoteWebElement;
  2. import io.appium.java_client.pagefactory.*;
  3. import org.openqa.selenium.support.FindBy;
  4. import org.openqa.selenium.support.FindByAll;
  5. import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE;
  6. @HowToUseLocators(iOSAutomation = ALL_POSSIBLE)
  7. @FindAll{@FindBy(someStrategy1), @FindBy(someStrategy2)})
  8. @AndroidFindBy(someStrategy1) @AndroidFindBy(someStrategy2) //this is the chain
  9. //by default
  10. @iOSFindBy(someStrategy1) @iOSFindBy(someStrategy2)
  11. RemoteWebElement someElement;
  12. @HowToUseLocators(iOSAutomation = ALL_POSSIBLE)
  13. @FindAll({@FindBy(someStrategy1), @FindBy(someStrategy2)})
  14. @AndroidFindBy(someStrategy1) @AndroidFindBy(someStrategy2) //this is the chain
  15. //by default
  16. @iOSFindBy(someStrategy1) @iOSFindBy(someStrategy2)
  17. List<RemoteWebElement> someElements;

应用PO查找

# Appium Java client使用了AppiumFieldDecorator来融合了Selenium PageFactory

对象字段结构如下:

  1. import io.appium.java_client.pagefactory.*;
  2. import org.openqa.selenium.support.PageFactory;
  3. PageFactory.initElements(new AppiumFieldDecorator(searchContext
  4. /*searchContext is a WebDriver or WebElement
  5. instance */),
  6. pageObject //对象类的一个实例
  7. );
  1. import io.appium.java_client.pagefactory.*;
  2. import org.openqa.selenium.support.PageFactory;
  3. import java.util.concurrent.TimeUnit;
  4. PageFactory.initElements(new AppiumFieldDecorator(searchContext,
  5. /*searchContext is a WebDriver or WebElement
  6. instance */
  7. 15, //默认为所有查找策略的隐式等待时间
  8. TimeUnit.SECONDS),
  9. pageObject //对象类的一个实例
  10. );
  1. import io.appium.java_client.pagefactory.*;
  2. import org.openqa.selenium.support.PageFactory;
  3. import java.util.concurrent.TimeUnit;
  4. PageFactory.initElements(new AppiumFieldDecorator(searchContext,
  5. /*searchContext is a WebDriver or WebElement
  6. instance */
  7. new TimeOutDuration(15, //默认为所有查找策略的隐式等待时间
  8. TimeUnit.SECONDS)),
  9. pageObject //对象类的一个实例
  10. );

来看个经典计算器程序在PageObject中的实际应用

项目结构
安装程序的核心组件将是以下类:

  • AbstractTest:我们在其中设置测试阶段;
  • AppiumDriverBuilder:设置所需的功能并实例化驱动程序;
  • 我们调用的应用程序类访问我们的Screen对象;
  • AbstractScreen,包含您的Screen对象之间的所有共享方法;
  • Screen类包含表示用户与被测试应用程序交互的方法;
  • 测试类包含一个或多个测试,写成屏幕方法调用序列。

为了进一步澄清项目结构,您可以将这些类组织成包。在一个实用程序包中,您可以包括您的AppiumDriverBuilder类以及您创建的其他实用程序类。您也可以将AbstractScreen类和其他Screen类放在屏幕包中。项目结构如下:

AbstractTest
在项目的中心是AbstractTest类。这里我们定义我们的测试套件方法,它将在每次测试运行之前执行。这里我们做两件非常重要的事情:

  1. 负责初始化负责连接到Appium服务器的驱动程序;
  2. 实例化了App类,这将允许我们访问我们想要测试的应用程序的单个屏幕;
  1. package com.test.calculatortest;
  2. import com.test.calculatortest.Calculator;
  3. import com.test.calculatortest.util.AppiumDriverBuilder;
  4. import io.appium.java_client.AppiumDriver;
  5. import org.junit.Before;
  6. import java.net.MalformedURLException;
  7. import java.net.URL;
  8. public abstract class AbstractTest {
  9. private AppiumDriver<?> driver;
  10. protected Calculator app;
  11. /* Establish a connection to TestObject, or to a local device test is local. */
  12. @Before
  13. public void connect() throws MalformedURLException {
  14. this.driver = AppiumDriverBuilder.forAndroid()
  15. .withEndpoint(new URL("http://127.0.0.1:4723/wd/hub"))
  16. .build("com.android.calculator2", ".Calculator");
  17. //实例化应用类
  18. app = new Calculator(driver);
  19. }
  20. }

AppiumDriverBuilder
它基本上是一个支持类,负责配置和实例化的Appium驱动程序。

  1. package com.test.calculatortest.util;
  2. import io.appium.java_client.AppiumDriver;
  3. import io.appium.java_client.android.AndroidDriver;
  4. import io.appium.java_client.android.AndroidElement;
  5. import org.openqa.selenium.remote.DesiredCapabilities;
  6. import java.net.URL;
  7. public abstract class AppiumDriverBuilder<SELF, DRIVER extends AppiumDriver<?>> {
  8. public static AndroidDriverBuilder forAndroid() {
  9. return new AndroidDriverBuilder();
  10. }
  11. public static class AndroidDriverBuilder extends AppiumDriverBuilder<AndroidDriverBuilder, AndroidDriver<?>> {
  12. DesiredCapabilities capabilities = new DesiredCapabilities();
  13. @Override
  14. public AndroidDriver<?> build(String appPackage,String appActivity) {
  15. capabilities.setCapability("platformName", "Android");
  16. //使用Android模拟器
  17. capabilities.setCapability("deviceName", "testDevice");
  18. //使用Android模拟器
  19. capabilities.setCapability("platformVersion", "4.4.4");
  20. //不重新安装应用
  21. capabilities.setCapability("noReset",true);
  22. //待测包名及首次启动的页面
  23. capabilities.setCapability("appPackage", appPackage);
  24. capabilities.setCapability("appActivity", appActivity);
  25. //使用appium Unicode键盘输入法,输入完毕后重置输入法
  26. capabilities.setCapability("unicodeKeyboard", true);
  27. capabilities.setCapability("resetKeyboard", true);
  28. capabilities.setCapability("deviceReadyTimeout",30);
  29. return new AndroidDriver<AndroidElement>(endpoint, capabilities);
  30. }
  31. }
  32. protected URL endpoint;
  33. @SuppressWarnings("unchecked")
  34. public SELF withEndpoint(URL endpoint) {
  35. this.endpoint = endpoint;
  36. return (SELF) this;
  37. }
  38. public abstract DRIVER build(String appPackage,String appActivity);
  39. }

应用类
测试中的另一个中心类将是Application类(我们简单的命名为我们正在测试的应用程序的名称)。这个类的功能是提供屏幕(正如我们之前所说的,Page对象)到需要访问它们的功能的方法(屏幕类中的测试方法)。

  1. package com.test.calculatortest;
  2. import com.test.calculatortest.screen.CalculatorScreen;
  3. import io.appium.java_client.AppiumDriver;
  4. /*
  5. * 应用类,返回各个操作页面类
  6. */
  7. public class Calculator {
  8. private final AppiumDriver<?> driver;
  9. public Calculator(AppiumDriver<?> driver) {
  10. this.driver = driver;
  11. }
  12. public CalculatorScreen calculatorScreen() {
  13. return new CalculatorScreen(driver);
  14. }
  15. }

AbstractScreen类

AbstractScreen类将包含Screen对象之间共享的所有方法。这些可能是通用目的的方法,可以执行多个点(滑动,滚动)与应用程序交互所需的手势,这些手段隐藏了一些更为复杂的代码,从而增加了测试方法的可读性,同步方法等。

  1. package com.test.calculatortest.screen;
  2. import io.appium.java_client.AppiumDriver;
  3. import io.appium.java_client.MobileElement;
  4. import io.appium.java_client.pagefactory.AppiumFieldDecorator;
  5. import org.openqa.selenium.By;
  6. import org.openqa.selenium.OutputType;
  7. import org.openqa.selenium.support.PageFactory;
  8. import org.openqa.selenium.support.ui.ExpectedConditions;
  9. import org.openqa.selenium.support.ui.WebDriverWait;
  10. public abstract class AbstractScreen {
  11. protected final AppiumDriver<?> driver;
  12. public AbstractScreen(AppiumDriver<?> driver) {
  13. this.driver = driver;
  14. PageFactory.initElements(new AppiumFieldDecorator(driver), this);
  15. }
  16. public MobileElement findElementWithTimeout(By by, int timeOutInSeconds) {
  17. return (MobileElement)(new WebDriverWait(driver, timeOutInSeconds)).until(ExpectedConditions.presenceOfElementLocated(by));
  18. }
  19. protected void takeScreenShot(){
  20. driver.getScreenshotAs(OutputType.BASE64);
  21. }
  22. }

注意
PageFactory.initElements(new AppiumFieldDecorator(driver), this);这句,这可以让你使用注释来抓取UI元素,因此请勿忘记将其包含在您的设置中!

屏幕类
屏幕类代表应用程序的屏幕。在这里获取UI元素并与代表可能与用户界面交互的方法与其进行交互,例如打开菜单并选择项目,填写某些字段并按下提交按钮,向下滚动列表并选择正确的元素这样,你的测试方法将只是不同屏幕上的一系列用户交互。这将使你的测试易于维护和扩展。

  1. package com.test.calculatortest.screen;
  2. import io.appium.java_client.AppiumDriver;
  3. import io.appium.java_client.MobileElement;
  4. import io.appium.java_client.pagefactory.AndroidFindBy;
  5. import org.openqa.selenium.TimeoutException;
  6. import org.openqa.selenium.support.ui.ExpectedConditions;
  7. import org.openqa.selenium.support.ui.WebDriverWait;
  8. public class CalculatorScreen extends AbstractScreen {
  9. @AndroidFindBy(id = "com.android.calculator2:id/digit2")
  10. private MobileElement buttonTwo;
  11. @AndroidFindBy(id = "com.android.calculator2:id/plus")
  12. private MobileElement buttonPlus;
  13. @AndroidFindBy(id = "com.android.calculator2:id/equal")
  14. private MobileElement buttonEquals;
  15. @AndroidFindBy(xpath = "//android.widget.EditText[1]")
  16. private MobileElement resultField;
  17. public CalculatorScreen(AppiumDriver<?> driver) {
  18. super(driver);
  19. }
  20. public void addTwoAndTwo() {
  21. buttonTwo.click();
  22. buttonPlus.click();
  23. buttonTwo.click();
  24. buttonEquals.click();
  25. }
  26. public boolean isResultCorrect(String result) {
  27. try {
  28. /* Check if within given time the correct result appears in the designated field. */
  29. (new WebDriverWait(driver, 30)).until(ExpectedConditions.textToBePresentInElement(resultField, result));
  30. return true;
  31. } catch (TimeoutException e) {
  32. return false;
  33. }
  34. }
  35. }

除了刚刚描述的应用程序的显着“主屏幕”之外,我们还可以创建另一个表示计算器应用程序的“高级面板”的程序,这基本上是自己的屏幕。在此屏幕中引用的UI元素将是计算器的符号/函数。
你可以为应用程序的每个屏幕创建一个Screen对象,也可以决定仅对真正重要的屏幕执行此操作。这两种方法都有其优点和缺点,但请记住,可以使用太多屏幕的应用程序来处理,另一方面,在一个Screen对象中抽取太多的屏幕可能会导致混乱。
测试类
您的测试按照扩展AbstractTest的类进行分组。这允许您抓住应用程序的任何屏幕,并通过您编写的方法与其进行交互。

  1. package com.test.calculatortest;
  2. import org.junit.Test;
  3. import static org.junit.Assert.assertTrue;
  4. /*
  5. *
  6. * 逻辑操作类
  7. *
  8. */
  9. public class OperationTests extends AbstractTest {
  10. public OperationTests() {}
  11. /* 一个简单的加法运算,期望结果为正确的值 */
  12. @Test
  13. public void twoPlusTwoOperation() {
  14. app.calculatorScreen().addTwoAndTwo();
  15. assertTrue(app.calculatorScreen().isResultCorrect("4"));
  16. }
  17. }

将计算器的例子放在一边,并跳入一个现实世界的例子:

  1. public class ChatTest extends AbstractTest {
  2. @Test
  3. public void sendMessageAndCheckHistoryTest() {
  4. login(Credentials.VALID_USER_CREDENTIALS);
  5. app.mainScreen().startChatWithUser(TEST_USERNAME);
  6. app.chatScreen().sendChatMessage(TEST_MESSAGE);
  7. app.chatScreen().navigateToHistoryScreen();
  8. assertTrue(app.historyScreen().containsMessage(TEST_MESSAGE));
  9. }
  10. @Test
  11. public void sendAndDeleteMessageThenCheckHistoryTest() {
  12. ...
  13. }
  14. }

正如你所看到的,当涉及多个屏幕时,这种模式的目的变得清晰,方便起见。我们现在正在浏览我们从未见过的一系列屏幕,但是我们已经可以得到我们测试中发生了什么的一般概念。如果我们看看我们调用的屏幕方法的实现,我们将会更准确地了解发生了什么。事实上,我们可以在没有这样做的情况下收集一些信息是使用PageObject编写测试的好处之一。
如果UI发生小的变化,我们可能不需要改动我们的测试方法:改动将在我们的屏幕方法之一发生。在这种变化频繁的敏捷环境中,除了测试脚本的强大性外,还特别受欢迎。
您可以选择自己的屏幕方法的复杂程度。拥有更多,更简单的屏幕方法将导致更长,更详细的测试方法,暴露更多的交互的复杂性。按照这种方法,上述方法看起来更像这样:

  1. @Test
  2. public void sendMessageAndCheckHistoryTest() {
  3. login(Credentials.VALID_USER_CREDENTIALS);
  4. app.mainScreen().navigateToUserSelection();
  5. app.userSelectionScreen().selectUser(TEST_USERNAME);
  6. app.userProfileScreen().startChat();
  7. app.chatScreen().sendChatMessage(TEST_MESSAGE);
  8. app.chatScreen().navigateToMainScreen();
  9. app.mainScreen().navigateToHistoryScreen();
  10. assertTrue(app.historyScreen().containsMessage(TEST_MESSAGE));
  11. }

虽然这种方法显示了屏幕之间的每个过渡,但是它可能很容易成为压倒性的,如在这个例子中:

  1. public class CreateDocumentationWithSuggestionTest extends AbstractTest {
  2. @Test
  3. public void buildNewDocumentationWithSuggestions() {
  4. app.documentationScreen().navigateToSettings();
  5. app.settingsScreen().navigateToSuggestions();
  6. app.settingsScreen().activateSuggestions(SUGGESTIONS));
  7. app.settingsScreen().navigateToDocumentation();
  8. app.documentationScreen().createDocumentation();
  9. app.documentationCreationScreen().selectCultivation();
  10. app.documentationDetailsScreen().selectFields(TEST_CULTIVATION_1.getFields());
  11. app.documentationDetailsScreen().selectConsumables(TEST_CULTIVATION_1.getConsumables());
  12. app.documentationDetailsScreen().selectWorkers(TEST_CULTIVATION_1.getWorkers());
  13. app.documentationDetailsScreen().sendActivity();
  14. app.documentationScreen().createDocumentation();
  15. app.documentationCreationScreen().selectCultivation();
  16. Assert.assertTrue(app.documentationDetailsScreen().areSuggestedFieldsFilledOut(TEST_CULTIVATION_1));
  17. }
  18. ...
  19. }

您应该保持测试方法足够短,以便您能够一目了然地告诉他们做什么,而不用将所有内容都包装到单一屏幕方法中。寻找平衡是编写一个好的,可维护的测试套件的关键。
总结:
PageObject前期可能工作量有点多,但是后面都是照葫芦画瓢非常容易维护,所以使用起来性价比还是挺高的,相比直来直去的测试脚本也减少了大量的重复代码

Appium PageObject的更多相关文章

  1. appium():PageObject&PageFactory

    Appium Java client has facilities which components to Page Object design pattern and Selenium PageFa ...

  2. Appium python unittest pageobject如何实现加载多个case

    学习了Appium python项目施展的课程小伙伴都会有一个疑问,说现在所有的case都是通过一个suite进行一个方法一个方法进行添加的,但是在实际过程中我们不希望这样,我们做出来的功能是这样: ...

  3. Appium+python自动化(三十二)- 代码写死一时爽,框架重构火葬场 - PageObject+unittest(超详解)

    简介 江湖有言:”代码写死一时爽,框架重构火葬场“,更有人戏言:”代码动态一时爽,一直动态一直爽

  4. appium在不同类中使用的是同一个session

    要这么做的起因: 测试testng框架的时候,不同类之间可以按照顺序执行,不会互相干扰.但是换成了appium,在A类中启动了session,初始化或者一些数据我仍然要用之前的session,那就不行 ...

  5. 【转】Appium 优化版

    Appium 开源分享优化版 之前分享过PageObject+Python+Appium 本版本是对上次版本较大改版,主要解决了: 失败重连一次(默认一次)可配置多次 基于appium1.7.1 ui ...

  6. appium+python+unittest+HTMLRunner编写UI自动化测试集

    简介 获取AppPackage和AppActivity 定位UI控件的工具 脚本结构 PageObject分层管理 HTMLTestRunner生成测试报告 启动appium server服务 以py ...

  7. appium+python自动化50-生成定位对象模板templet(jinja2)

    前言 每次自己写pageobject定位元素对象太繁琐,格式都差不多,只是换个定位方法,这种就可以才有模板的方式,批量生成pageobject定位元素对象的模板 python里面生成模板有两个模块可以 ...

  8. appium+python自动化49-yaml管理定位元素

    前言 如何高效管理定位元素,这个是很有学问的问题,也是面试必问的[以下纯属个人观点,勿喷!]. 有的人用xml管理页面定位元素,这种逼格略高,但是小编认为学习成本大,贼麻烦. 有的人提到用excel管 ...

  9. Appium+python自动化(三十八) - Appium自动化测试框架综合实践 - 框架简介-助你冲击高薪,迎娶白富美(超详解)

    简介 好久没有更新博客了,博友们是不是有点等不及了.不好意思啊,中秋节过后太忙了,这篇是好不容易抽点零碎时间写的.从这一篇开始小伙伴或者童鞋们,就跟随宏哥的脚步,一步步的从无到有,从0到1的搭建一个完 ...

随机推荐

  1. JAVA会将所有的错误封装成为一个对象,其根本父类为Throwable

    JAVA会将所有的错误封装成为一个对象,其根本父类为Throwable. Throwable有两个子类:Error和Exception. 一个Error对象表示一个程序错误,指的是底层的.低级的.不可 ...

  2. 采用预取(Prefetch)来加速你的网站(转)

    一.DNS预取 如果你像我一样想在网站上有一个Twitter小程序,还有网站分析,再也许一些网页字体,那么你必须要链接到一些其它域名,这意味着你将不得不引发DNS查询.我的建议通常是,不要还没有先适当 ...

  3. leetcode:Pascal&#39;s Triangle

    一.     题目 经典题目,杨辉三角,输入行数.生成杨辉三角的数组. 二.     分析 首先,我们知道有例如以下规律: 1.每一行的第一个数和最后一个数都为1 2.中间的数是上面数和上面数左边的数 ...

  4. MathType中输入不了汉字如何处理

    MathType作为一款常见的数学公式编辑器在编辑数学公式时,不仅可以输入英文字符,对中文也有很好的兼容性.但是有些用户在使用MathType编辑公式时,发现一些汉字是输入不进去的,这个时候我们就需要 ...

  5. [4] 算法之路 - 插入排序之Shell间隔与Sedgewick间隔

    题目 插入排序法由未排序的后半部前端取出一个值.插入已排序前半部的适当位置.概念简单但速度不快. 排序要加快的基本原则之中的一个: 是让后一次的排序进行时,尽量利用前一次排序后的结果,以加快排序的速度 ...

  6. 了解 IMyInterface.Stub

    Service中的IBinder 还记得我们在MyService中利用new IMyInterface.Stub()向上转型成了IBinder然后在onBind方法中返回的.那我们就看看IMyInte ...

  7. Spring学习笔记 7.1 Spring MVC起步

    7.1.1 跟踪Spring MVC的请求请求首先到达DispatcherServlet(DispatcherServlet是Spring MVC中的前端控制器):DispatcherServlet的 ...

  8. Json与数组

    今天趁着看源代码的同时,记录学习的小知识. 一.String.Split 方法有6个重载函数: 1) public string[] Split(params char[] separator)2) ...

  9. Linux中chown和chmod的区别和用法(转)

    chmod修改第一列内容,chown修改第3.4列内容: chown用法: 用来更改某个目录或文件的用户名和用户组. chown 用户名:组名 文件路径(可以是绝对路径也可以是相对路径) 例1:cho ...

  10. 【BZOJ3622】已经没有什么好害怕的了 容斥+DP

    [BZOJ3622]已经没有什么好害怕的了 Description Input Output Sample Input 4 2 5 35 15 45 40 20 10 30 Sample Output ...