
从0-1认识Java
简介
Java是面向对象编程。
Java语言基础包括数据类型和运算符、控制结构、数组、类和对象、异常处理、枚举和注解等;面向对象包括封装性、继承性、多态性、接口与抽象类、泛型与集合、多线程与并发编程等;
- Java技术体系所包含的内容

- Java语言发展状况

开发环境配置
下载JDK
下载地址 :www.oracle.com/technetwork/java/javase/downloads
- Java术语

设置JDK
- 安装jdk
- 设置环境变量
- 测试:
javac -version
- JDK目录树

IDE使用
IntelliJ IDEA
基本语法
一个简单的Java应用程序
public class FirstSample{public static void main(String[] args) {System.out.println("We will not use 'Hello, World!'");}}
注释
// 单行注释/** 多行注释*//*** 文档注释*/
Java基础知识
变量
// 变量初始化int vacationDays = 12;// 常量final double CM_PER_INCH = 2.54;
运算符
// 加减乘除+、-、*、/、+=// 取模,自增、自减%、i++、i--// 位运算符&、|、^、~// 逻辑运算符&&、||、!
数学函数
// 平方根、幂运算double y = Math.sqrt(x);double y = Math.pow(x,a);// 三角函数Math.sinMath.cosMath.tan// 常量Math.PIMath.E
数值类型之间的转换

强制类型转换
double x = 9.997;int nx = (int) x;
运算符优先级

类型
数据类型
enum Size { SMALL, MEDIUM, LARGE, EXTRA_LARGE };
注:若整型和浮点型精度不能满足要求,BigInteger类实现了任意精度的整数运算,BigDecimal类实现了任意精度的浮点数运算。
字符串
// 定义、初始化String greeting = "Hello";// 子串String s = greeting.substring(0, 3)// 拼接:+号连接2个字符串String expletive = "Expletive";String PG13 = "deleted";String message = expletive + PG13;// 拼接:+号连接字符串与非字符串的值,后者被转化成为字符串int age = 13;String rating = "PC" + age;// 将多个字符串用一个定界符分隔:静态join()方法String all = String.join("/","S","M","L","XL");
String类对象为不可变字符串,没有提供用于修改字符串的方法,优点是:编译器可让字符串共享。
// 检测字符串是否相等s.equals(t)"Hello".equals(greeting)
API文档 https://docs.oracle.com/javase/8/docs/api/
控制流程
条件语句
Demo:

if (yourSales >= 2 * target){performance = "Excellent";bonus = 1000;}else if (yourSales >= 1.5 * target){performance = "Fine";bonus = 500;}else if (yourSales >= target){performance = "Satisfactory";bonus = 100;}else{System.out.println("You're fired");}
循环
- while循环
格式:
// 先检测循环条件while (condition) statement// 至少执行一次,再检测循环条件do statement while (condition);
Demo:

while(balance < goal){balance += payment;double interest = balance * interestRate / 100;balance += interest;years++;}
- for循环
格式:
// for循环for(initialization; boolean_expression; update) statement// foreachfor (variable : collection) statement
Demo:

for (int i = 1; i <= 10; i++)System.out.println(i);
Demo:遍历数组
String[] names = new String[10];for (int i = 0; i < 10; i++) names[i]="";
异常
- Java程序运行期间可能出现的错误:
- 文件包含了错误信息
- 网络连接出现问题
- 无效的数组下标
- 使用没有被赋值的对象引用
- ……
- 如果出现错误而使某些操作没有完成,程序应该:
- 返回到一种安全状态,并能够让用户执行一些其他的命令
- 或允许用户保存所有操作的结果,并以妥善的方式终止程序
异常处理的任务:将控制权从错误产生的地方转移给能够处理这种情况的错误处理器
- Java中的异常层次结构

抛出异常
抛出一个已经存在的异常类:
String readData(Scanner in) throws EOFException{...while (. . .) {if (!in.hasNext()) { // EOF encounteredif (n < len)throw new EOFException();}...}return s;}
捕获异常
捕获异常:
try{codemore codemore code}catch (ExceptionType e){handler for this type}
捕获多个异常:
try{code that might throw exceptions}catch (FileNotFoundException e){emergency action for missing files}catch (UnknownHostException e){emergency action for unknown hosts}catch (IOException e){emergency action for all other I/O problems}
捕获后再次抛出:改变异常类型
{access the database}catch (SQLException e){throw new ServletException ("database error: " + e.getMessage());}
断言
作用:对条件进行检测,如果结果为false,抛出AssertionError异常。断言只应该用于在测试阶段确定程序内部的错误位置。
格式:
assert条件;assert条件:表达式;
注解
- 注解类型
- 内建注解
- @Override注解:表示该方法是重写父类的某方法
- @Deprecated注解:表示已过时
- @SuppressWarnings注解:阻止编译器警告
- 元注解
- @Target注解:指定被其修饰的注解能用于修饰哪些程序元素
- @Retention注解:描述了被其修饰的注解是否被编译器丢弃或者保留在class文件中
- @Documented注解:指定被其修饰的注解将被JavaDoc工具提取成文档
- @Inherited注解:指定被其修饰的注解将具有继承性
- 自定义注解
- 定义:public @interface AnnotationTest{}
- 内建注解
- 读取注解信息
-
Demo:
public class MyAnnotation{//获取MyAnnotation类的getObjectInfo()方法的所有注解Annotation[] arr=Class.forName("MyAnnotation").getMethod("getObjectInfo"). getAnnotations();//遍历所有注解for(Annotation an:arr){System.out.println(an);}}
常用操作
数据驱动测试,每种数据源适合的场景:
1)测试数据的存放:推荐使用CSV或Excel作为数据源。
2)配置数据的存放:推荐使用Properties或YAML作为数据源。
3)跨项目共享测试数据或配置数据:推荐使用数据库作为数据源。
JUnit参数化测试
-
Demo:
pom.xml:
<dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-engine</artifactId><version>5.6.0</version></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-params</artifactId><version>5.6.0</version></dependency>
代码:
import org.junit.jupiter.params.ParameterizedTest;import org.junit.jupiter.params.provider.*;import org.openqa.selenium.chrome.ChromeDriver;import java.util.concurrent.TimeUnit;import java.util.stream.Stream;import static org.junit.jupiter.api.Assertions.assertEquals;import static org.junit.jupiter.api.Assertions.assertNotNull;public class LoginForJUnit {((ArgumentsProviderClass.class))void testCase_001(String url, String username, String password) throws InterruptedException {ChromeDriver driver = new ChromeDriver();driver.get(url);driver.findElementByCssSelector("input[type='text']").sendKeys(username);driver.findElementByCssSelector("input[type='password']").sendKeys(password);driver.findElementByClassName("el-button").click();TimeUnit.SECONDS.sleep(3);assertEquals(username, driver.findElementByCssSelector("#nav > div:nth-child(2) > span").getText());driver.quit();}static Stream<Arguments> methodSource() {return Stream.of(Arguments.of("http://localhost:9002/login", "zhangsan", "zhangsan123456"),Arguments.of("http://localhost:9002/login", "lisi", "lisi123456"));}(value = Role.class, names = {"GUEST", "USER"})void testCase_002(Role role) {assertNotNull(role);}enum Role {GUEST, USER, ADMIN}}
文件读写
Demo:使用CSV文件进行数据驱动测试
Github: xiaoliuzi20180524/selenium-webdriver https://github.com/xiaoliuzi20180524/selenium-webdriver/tree/master/chapter9/src/main/java/com/data/demo
import org.testng.annotations.DataProvider;import org.testng.annotations.Test;import java.io.BufferedReader;import java.io.FileInputStream;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;/*** @description 利用CSV文件做数据驱动测试* @author rongrong* @version 1.0* @date 2020/6/27 13:22*/public class TestCSVData {/*** 读取csv文件** @param filePath* @return返回list集合*/public List<Map<String, String>> getCSVData(String filePath) {List<Map<String, String>> list = new ArrayList<Map<String, String>>();;FileInputStream fileInputStream = null;try {fileInputStream = new FileInputStream(filePath);InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);BufferedReader br = new BufferedReader(inputStreamReader);//通过for循环遍历,将读取的每一行数据使用逗号进行分割并保存到map中for (String line = br.readLine(); line != null; line = br.readLine()) {Map<String, String> map = new HashMap<String, String>();String key = line.split(",")[0];String value = line.split(",")[1];map.put("userName", key);map.put("passWord", value);//再将map对象放到list集合中list.add(map);}br.close();} catch (Exception e) {e.printStackTrace();}return list;}@DataProviderpublic Object[][] testCSVData() {//读取csv文件数据,调用getCSVData()方法来获得测试的数据List<Map<String, String>> result = getCSVData("d:\data.csv");Object[][] files = new Object[result.size()][];//通过for循环遍历list,每一行的数据都会通过构造函数来进行初始化赋值for (int i = 0; i < result.size(); i++) {files[i] = new Object[]{result.get(i)};}return files;}@Test(dataProvider = "testCSVData")public void testCSVData(Map<String, String> param) {System.out.println(param.get("userName") + "t" + param.get("passWord"));}}
MySQL
Demo:使用数据库作为数据源
Github: xiaoliuzi20180524/selenium-webdriver https://github.com/xiaoliuzi20180524/selenium-webdriver/tree/master/chapter9/src/main/java/com/data/demo
package com.data.demo;import org.testng.annotations.Test;import java.util.Map;/*** @description 读取mysql数据库* @author rongrong* @version 1.0* @date 2020/6/27 14:22*/public class TestDbData extends DbDataHeleper {public void testmethod1(Map<?, ?> param) {System.out.println(param.get("username") + "t" + param.get("passWord") + "t" + param.get("remark"));}}
package com.data.demo;import org.testng.annotations.DataProvider;import java.sql.*;import java.util.*;/*** @description 读取mysql数据库* @author rongrong* @version 1.0* @date 2020/6/27 14:22*/public class DbDataHeleper {static Connection conn = null;public static String driverClassName = "com.mysql.jdbc.Driver";public static String url = "jdbc:mysql://127.0.0.1:3306/demo?serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true&zeroDateTimeBehavior=convertToNull";public static String username = "root";public static String password = "root";/*** 执行sql** @param jdbcUrl 数据库配置连接* @param sql sql语句* @return*/public static List<Map<String, String>> getDataList(String jdbcUrl, String sql) {List<Map<String, String>> paramList = new ArrayList<Map<String, String>>();Map<String, String> param = new HashMap<String, String>();Statement stmt = null;try {// 注册 JDBC 驱动Class.forName(driverClassName);// 打开链接conn = DriverManager.getConnection(jdbcUrl, username, password);// 执行查询stmt = conn.createStatement();ResultSet rs = null;rs = stmt.executeQuery(sql);String columns[] = {"username", "passWord", "remark"};// 展开结果集数据库while (rs.next()) {Map<String, String> map = new LinkedHashMap<String, String>();for (int i = 0; i < columns.length; i++) {String cellData = rs.getString(columns[i]);map.put(columns[i], cellData);}paramList.add(map);}// 完成后关闭rs.close();stmt.close();conn.close();} catch (SQLException se) {// 处理 JDBC 错误System.out.println("处理 JDBC 错误!");} catch (Exception e) {// 处理 Class.forName 错误System.out.println("处理 Class.forName 错误");} finally {// 关闭资源try {if (stmt != null) stmt.close();if (conn != null) conn.close();} catch (SQLException se) {se.printStackTrace();}}return paramList;}public Object[][] dbDataMethod() {String sql = "SELECT * FROM `account`;";List<Map<String, String>> result = getDataList(url, sql);Object[][] files = new Object[result.size()][];for (int i = 0; i < result.size(); i++) {files[i] = new Object[]{result.get(i)};}return files;}}
Redis
Demo1:jmeter中使用java获取Redis中的值
Demo2:缓存中间件Redis性能测试
场景:
(1)分别设置value值大小为64B、128B、256B、512B,往Redis集群和Redis单机写入500万条记录。
(2)并发分别设置80、160、320、500、1000、2000、3000、4000、5000、6000、8000对拥有500万条记录的Redis集群和Redis单机进行读取的测试。



集合

集合类存放于java.util包中,Java集合定义了两种基本的数据结构,一种是Collection,用来表示一组对象的集合;另一种则是Map,用来表示对象间的一系列映射或关联关系。Set、List和Queue等接口都是Collection的子接口。
Collection<E>是参数化接口,用来表示一组泛型对象的集合
ArrayList
ArrayList是Java中最常用的List实现类,通过数组实现,可存储一组不唯一、有序的对象。
特点:长度可变且可以存储任何类型的数据
优点:遍历元素和随机访问元素的效率较高
- ArrayList常用方法

LinkedList
LinkedList使用链表结构存储数据,适合数据的动态插入和删除,但随机访问和遍历速度较慢。可作为堆栈、队列和双向队列使用。

HashSet
可存储一组唯一、无序的对象。

HashMap
Map接口存储一组成对的键(key)——值(value)对象,提供key到value的映射,通过key来检索。Map接口中的key不要求有序,不允许重复。value同样不要求有序,但允许重复。
优点:查询指定元素效率高

线程安全问题
ArrayList、LinkedList、HashSet、HashMap都是非线程安全的,在多个线程场景中使用这些基础容器会出现线程安全问题。多线程场景可考虑使用基于非阻塞算法的JUC高并发容器类。
| 线程不安全 | 高并发容器方案 |
| ArrayList | CopyOnWriteArrayList:读多写少的场景 |
| HashSet | CopyOnWriteArraySet:核心操作基于CopyOnWriteArrayList实现 |
| TreeSet | ConcurrentSkipListSet:线程安全的有序集合 |
| HashMap | ConcurrentHashMap |
| TreeMap | ConcurrentSkipListMap |
本篇文章来源于微信公众号: 海盐架构笔记
微信扫描下方的二维码阅读本文

Comments NOTHING