简介

Java语言开发环境的搭建

Java虚拟机——JVM

  • JVM(java Virtual Machine) : Java虚拟机, 是运行所有Java程序的假想计算机, 是Java程序的运行环境, 是Java最具吸引力的特性之一, 我们编写的Java代码, 都运在JVM之上

  • 跨平台:任何软件的运行, 都必须要运行在操作系统之上, 而我们用Java编写的软件可以在任何的操作系统上, 这个特性称为Java语言的跨平台性, 该特性是由JVM实现的, 我们编写的程序运行在JVM上, 而JVM运行在操作系统上

    java-cross_platform

  • 如图, java的虚拟机本身不具备跨平台功能的, 每个操作系统下都由不同版本的虚拟机

JRE 和 JDK

  • JRE(Java Runtime Environmen) : 是Java程序的运行时环境, 包含JVM和运行时所需要的核心类库

  • JDKJava Development Kit): 是Java程序开发工具包, 包含JRE和开发人员使用的工具

  • 关系

    java-relation

概念

注释

// 单行注释
/*
多行注释
*/

关键字

  • 有特殊含义、被保留的、不能随意使用的字符

常量

在程序运行的过程中不会改变的量

  1. 字符串常量, " "双引号引起来的部分, 例如"abd"、 "Hello"、“123”
  2. 整数常量, 例如: 100, 200, 0, -250
  3. 浮点数常量, 例如:2.5, -3.14
  4. 字符串常量, 例如: 'A', ’b‘, '9', '中'
    • Java中的一个char类型标识一个utf-16编码的代码单元, 也就是两个字节, 因此, 不像C语言中文无法代表一个字符
    • char真实的含义是描述了UTF-16编码中的一个代码单元, 而不是一个字符
  5. 布尔常量, true, false
  6. 空常量, null, 代表没有任何数据

数据类型

基本数据类型

  • 整数型: byte short int long
  • 浮点型: float double
    • 浮点型可能只是一个近似值, 并非精确值, 例如1/3是无法精确表示的
  • 字符型: char
  • 布尔型: boolean

引用数据类型

  • 字符串、数组、类、接口、Lambda

流程控制

这部分和C/C++几乎一样, 我直接跳掉了

方法

定义

  • 参数:进入方法的数据(可以没有)
  • 返回值: 方法执行后的数据结果(可以没有)
  • 修饰符: 例如public static
  • 返回类型:对应返回值的类型
  • 方法名称:方法名字, 规则与变量意义, 建议符合驼峰命名法
  • 参数类型:对应参数的类型
  • 方法体:方法需要做的事情, 若干代码
  • return: (可以没有)
    • 将返回值返还调用处
    • 终止当前方法
修饰符 返回类型 方法名称(参数类型 参数名称, ....) {
方法体
return 返回值;
}

调用流程

java-function-call

重载

  • 名字相同, 但参数列表不同的方法
  • 用于对类似功能的方法的名称进行复用, 也就是记住一个名称就可以使用类似的功, 例如println()就进行了多种类型的重载, 使得我们只需要记住println()就可以了。

以数字相加为例

 public static int sum(int a, int b) {
return a + b;
}

public static int sum(int a, int b, int c) {
return a + b + c;
}

public static int sum(int a, int b, int c, int d) {
return a + b + c + d;
}

注意事项

  • 不能方法嵌套定义

  • 方法定义顺序无所谓

  • void方法可以写return, 也可以不写

  • 重载

    • 参数个数不同

    • 参数类型不同

    • 参数的多类型顺序不同

      下面例子是允许的

      public static int sum(double a, int b) {
      return (int)(a + b);
      }

      public static int sum(int a, double b) {
      return (int)(a + b);
      }

数组

任何数据类型都可以存放在数组中

动态初始化

int[] array = new int[300];
double[] array = new double[10];
String[] array = new String[10]
  • 初始化默认值:
    • 整数类型, 0
    • 浮点类型, 0.0
    • 字符类型, \u0000
    • 布尔类型, false
    • 引用类型, null

静态初始化

int[] array = new int[] {1, 2, 3};
String[] array = new String[] {"Hello", "World"};

省略格式

int[] arrayA = {10, 20, 30};

异常

数组越界异常(ArrayIndexOutOfBoundsException)
public class HelloWorld {
public static void main(String[] args) {
String[] array = new String[] {"Hello", "World"};
System.out.println(array[2]);
}
}

运行结果

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2
at cn.itcast.day01.demo01.HelloWorld.main(HelloWorld.java:6)
空指针异常(NullPointerException)

数组必须new初始化才能使用, 如果只是赋值了一个null, 将发生空指针异常:

public class HelloWorld {
public static void main(String[] args) {
String[] array = null;
System.out.println(array[0]);
}
}

运行结果

Exception in thread "main" java.lang.NullPointerException
at cn.itcast.day01.demo01.HelloWorld.main(HelloWorld.java:6)

数组长度

  • 获得: array.length

  • 数组一旦创建, 程序运行期间, 长度不可改变

    java-array-length

内存

栈(Stack)

  • 存放方法中的局部变量, 超出作用域立即从栈内存中消失

堆(Heap)

  • 凡是new出来的东西, 都在堆当中
  • 堆内存里面的东西都有一个地址值:16进制
  • 堆内的数据都有默认值

方法区(Method Area)

存放.class相关信息, 包含方法的信息

本地方法栈(Native Method Stack)

与操作系统相关

寄存器(Register)

与CPU相关

面向对象的思想

  • 面向过程, 每一步都亲力亲为
  • 面向对象, 找一个已有功能帮助实现

举例:

public class HelloWorld {
public static void main(String[] args) {
int[] array = {10, 20, 30, 40};

// 打印格式: [10, 20, 30, 40]

// 面向过程
System.out.print("[");
for (int i = 0; i < array.length; i++) {
if (i == array.length - 1) {
System.out.println(array[i] + "]");
} else {
System.out.print(array[i] + ", ");
}
}

// 面向对象
System.out.println(Arrays.toString(array));
}
}

类和对象

  • :一组相关属性行为的集合, 可以看成是一类事物的模板, 使用事物的属性特征和行为特征来描述该类事物。

现实中, 描述一类事物:

  • 属性: 就是该事物的状态信息,- 行为: 就是该事物能够做什么

举例: 小猫。

  • 属性: 名字、体重、年龄、颜色
  • 行为: 走、跑、叫

对象

  • 对象: 一类事物的具体体现, 对象是类的一个实例, 必然具备该类事物的属性和行为

举例: 一只小猫

关系

  • 类是一类事物的描述, 是抽象的
  • 对象是一类事务的实例, 是具体的
  • 类是对象的模板, 对象是类的实体

创建和使用

感觉和C++有相通之处

导包, 如果在同一个包内可以不写

import 包名称.类名称

Student student = new Student();

成员变量没有进行赋值, 呢么将会有一个默认值, 规则和数组一样

内存结构

一个

java-class-storage

两个

java-class-storage-2

局部变量和成员变量

  • 局部变量: 随着方法进栈而诞生, 随着方法出栈而消失
  • 成员变量:随着对象创建而诞生, 随着对象被垃圾回收而消失

面向对象的三大特性

封装

  • 方法就是一种封装
  • 关键字private 私有化也是一种封装
  • 把一些细节信息隐藏, 对外界不可见

继承

  • 继承是多态的前提
  • 继承类似师徒关系:师傅会多少都无偿传授给徒弟
  • 继承主要解决的问题是:共性抽取, 举个栗子(滑稽保命), 在一个公司里有很多的员工, 员工属性:姓名, 性别。职称等就是他们的共性, 但根据职称的不同, 每个人的计算工资的方法不一样, 因此可以对员工这个共性进行抽取, 然后对员工类进行继承, 分别实现各自的计算工资的方法。
  • 通俗讲就是可以免去Ctrl + C/V的麻烦
  • 被继承的类可以叫做父类基类超类
  • 继承的类可以叫做子类派生类
  • 继承的关键字是extends
举例
// Parent.class
public class ParentClass {
// ...
}

// Child.class
public class ChildClass extends ParentClass {
// ...
}
特点
  • Java是单继承, 即只能有一个父类

    // class one
    public class ClassOne {
    //
    }

    // class two
    public class ClassTwo {

    }

    // class three 这样定义是错误的!
    public class ClassThree extends ClassOne, ClassTwo {
    //
    }
  • Java可以多级继承

    // Parent.class
    public class ParentClass {
    // ...
    }

    // Child.class
    public class ChildClass extends ParentClass {
    // ...
    }

    // Grandson class
    public class GrandsonClass extends ChildClass{
    // ...
    }
  • 父类可以拥有多个子类

成员变量
  • 如果在继承关系中成员变量, 则创建子类对象是, 访问有两种方式
    • 直接通过子类对象访问成员变量
    • 间接通过成员方法访问成员变量
成员方法
  • 就近原则, 谁调用执行谁的成员方法, 没有则向上寻找
重载(Overload)
  • 父子类名称相同, 参数列表也相同
重写/覆盖(Override)
  • 父子类名称相同, 参数列表不同

  • 关键字@Override:可选, 起检测作用, 只要书写正确无也可覆盖

  • 返回值:子类方法返回值必须小于等于父类方法的返回值范围, 例如ObjectString的父类, 则父类为String则子类不可以是Object, 父类为Object则子类可以是String

  • 权限: 子类方法权限必须大于等于父类方法的权限修饰符

    • public > protected > (default) > private
    • defalut: 表示什么都不写, 留空
  • 举例

    // Parent.class
    public class ParentClass {
    public Object method() {
    // ...
    }
    }

    // Child.class
    public class ChildClass extends ParentClass {

    @Override
    public Object method() {
    // ...
    }
    }

多态

  • 重写, 继承, 重载都是多态的一种表现形式

this 关键字

当方法的局部变量和类成员变量重名, 根据就近原则, 优先使用局部变量

如果需要访问本类当中的成员变量, 需要使用格式;

this, 成员变量

例子:

java-this1

java-this2

”通过谁调用的方法, 谁就是this“: 用打印地址值来验证

static 关键字

  • 感觉跟C++一样, 只写一些自己不懂的

静态代码块

特点:

  1. 当第一次用到本类, 静态代码块执行唯一的一次
  2. 且比构造方法先执行!

用途:常用于对静态成员的赋值

public class 类名称 {
static {
// 静态代码块的内容
}
}

super 关键字

构造方法中

  • super(): 访问父类中的无参构造函数
  • super(paras...): 访问父类的有参构造函数

非构造方法

  • super.xxx: 访问父类中的成员变量
  • super.yyy(paras..): 访问父类中的成员函数yyy

this vs super

java-super_vs_this

标准类(Java Bean)

一个标准类中通常有

  • 所有成员变量用private修饰
  • 每一个成员变量都有一对Getter/Setter方法
  • 一个无参构造
  • 一个全参构造

匿名对象

  • 只有右边的对象, 没有左边的名字和赋值运算符
  • 只能使用一次, 下次使用需重新创建
  • 也可以作为方法的参数和返回值
// 正常
Person one = new Person();
one.name = "Lantern"

// 匿名对象
new Person().name = "Lantern2";

// 作为参数
methodParam(new Scanner(System.in));

public static Scanner methodReturnAndParam(Scanner sc) {
return new Scanner(Systen.in);
}

对象数组

Person array = new Person[3];
// 初始化为null
Person one = new Person("Lantern", 18);
// 将one中的地址值赋值给数组的0号元素
array[0] = one;

抽象

  • 如果父类中的方法不确定如何进行某个方法体实现, 那么这应该是一个抽象方法

    • 狗吃骨头猫吃鱼, 但动物吃什么没法具体描述, 那么就是一个抽象方法
    • 正方形三角形可计算面积, 但是图形怎么计算面积没法具体描述, 那么就是一个抽象方法

定义

定义抽象方法:在返回值前加上abstract关键字, 然后去掉大括号, 直接分号结束

定义抽象类: 在class之前加上abstract关键字

抽象方法必须在抽象类中

使用

  • 不能直接new抽象类对象, 必须用一个子类来继承抽象父类
  • 子类必须覆盖重写抽象父类当中的所有的抽象方法

举例

// Animal.java
public abstract class Animal {
public abstract void eat();

public void normalMethod() {
// code。。。。。
}
}


// Cat.java
public class Cat extends Animal {

@Override
public void eat() {
System.out.println("Cat eat fish.");
}
}

注意

  1. 抽象类不能创建对象
  2. 抽象类可以有构造方法, 供子类创建对象时, 初始化父类成员
    1. 先执行父类构造方法
    2. 再执行子类构造方法
  3. 抽象类不一定包含抽象方法, 有抽象方法必然是抽象类
  4. 抽象类的子类, 必须覆盖重写父类中所有抽象方法, 除非子类也是抽象类

接口

  • 一种公共的规范, 只要符合标准就可以大家通用
  • 引用数据类型, 最重要的内容就是其中的抽象方法

定义

public interface 接口名称 {
// 接口内容
}

可包含内容

  1. Java7
    1. 常量
    2. 抽象方法
  2. Java8, 额外包含
    1. 默认方法
    2. 静态方法
  3. Java9, 额外包含
    1. 私有方法

抽象方法

注意事项
  1. 接口中的抽象方法修饰符必须是:public abstract
  2. 这两个关键字可以选择性的省略
  3. 方法的三要素可以随意定义
定义举例
public interface MyInterface {
public abstract void methodAbs1();
abstract void methodAbs2();
public void methodAbs3();
void methodAbs4();
// 以上全是抽象方法
}
使用
  • 接口不能直接使用, 必须要有一个实体类来实现接口

  • 实现类必须覆盖重写接口中的抽象方法, 否则必须为抽象类

  • 创建实现类的对象, 进行使用

    public class 类名 implements 接口名称 {
    // ....
    }
使用举例
public class MyInterfaceImpl implements MyInterface {
// 覆盖重写接口中的抽象方法
}

默认方法

从java8开始允许在接口中定义默认方法

  • 解决接口升级问题
定义格式
public default 返回值类型 方法名称(参数列表) {
方法体
} // public 可省略
注意事项
  • 接口的默认方法会被实现类继承
  • 接口的默认方法可以被覆盖重写

静态方法

从java8开始允许在接口中定义静态方法

定义格式
public static 返回类型 方法名称(参数列表) {
方法体
}

成员变量

  • 必须使用public static final三个关键字修饰(可省略, 默认)
  • 其实就是接口的常量, 一旦赋值不可更改
  • 必须进行赋值
  • 成员变量名建议使用大写字母, 符合命名规范
public static final 成员变量名 = 值;

注意事项

  1. 接口没有静态代码块构造方法

  2. 一个类的直接父类是唯一的, 但一个类可以实现多个接口

    public class 实现类名 implements 接口1, 接口2 {
    // 覆写所有抽象方法
    }
  3. 如果实现类所实现的多个接口当中, 存在重复接口, 只用覆写一次

  4. 如果实现类没有覆盖重写所有接口当中的所有抽象方法, 那么实现类就必须是一个抽象类

  5. 如果实现类所实现的多个接口当中, 存在重复的默认方法, 那么实现类一定要对冲突的默认方法进行覆写

  6. 一个类如果直接父类当中的方法, 和接口当中的默认方法产生了冲突, 优先用父类当中的方法

API

  • API(Application Programming Interface)

  • Java API 文档

Scanner

一个可以解析基本类型和字符串的简单文本扫描器

例如, 以下代码使得用户可以从System.in中读取一个数

import java.util.Scanner; // 1.导包
// 2.创建, System.in 代表从键盘进行输入, 空格或回车进行截断
Scanner sc = new Scanner(System.in);
// 3.使用
int i = sc.nextInt(); // 获得一个数字
String str = sc.next(); // 获得一个字符串

练习

计算输入的两数字和
Scanner sc = new Scanner(System.in);
int i = sc.nextInt();
int j = sc.nextInt();
System.out.println(i + j);

Random

生成随机数

// 导包
import java.util.Random;
// 创建
Random r = new Random();
// 使用
int num1 = r.nextInt(); // 无参调用, 全范围
int num2 = r.nextInt(10); // 有参调用, [0, 10)

ArrayList

  • java.util.ArrayList;

  • ArrayList<E>

    • <E>称为泛型, 也就是装在集合当中的所有元素都是统一类型

    • 泛型只能是引用类型, 不能是基本类型

  • ArrayList集合的长度可以随意改变

  • 对于ArrayList集合来说, 直接打印得到的不是地址值, 而是内容

  • 如果内容为空, 得到的是空的中括号: []

// 创建了一个ArrayList聚合, 集合的名称list, 里面装的全都是String字符串类型的数据
// 备注: 从JDK 1.7+ 开始, 右侧的尖括号内可以不写, 但尖括号还是要写的
ArrayList<String> list = new ArrayList<>();

// 向集合中添加一些数据, 需要用到add方法
list.add("Lantern");
list.add("Lantern2");

System.out.println(list);

// list.add(100); // 报错!

常用方法

  • 不常用可以查询API文档
  • public boolean add(E e): 向集合当中添加元素, 参数的类型和泛型一致
    • 对于ArrayList集合来说, add添加动作一定是成功的, 所以返回值可用可不用, 但是对于其他集合来说, add动作不一定成功
  • public E get(int index):从集合当中获取元素, 参数是索引编号, 返回值就是对应位置的元素
  • public E remove(int index): 从集合当中删除元素, 参数是索引编号, 返回值就是删除掉的元素
  • public int size(): 获取集合的尺寸长度, 返回值为集合中包含的元素个数
ArrayList<String> list = new ArrayList<>();
list.add("Lantern");
list.add("Lantern1");
list.add("Lantern2");

// 从集合中获得元素, get 索引从0开始
String name = list.get(1);

// 从集合中删除元素, remove 索引值从0开始
String whoRemoved = list.remove(0);

// 获得集合的长度
int size = list.size();

// 遍历集合的元素
for (String s : list) {
System.out.println(s);
}

存储基本类型

  • 如果要存储基本类型, 必须使用基本类型对应的包装类(引用数据类型, 包装类都位于java.lang下)
基本类型包装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean
  • 从JDK 1.5+开始, 支持自动装箱, 自动拆箱

    • 自动装箱: 基本类型 –> 包装类
    • 自动拆箱:包装类–> 基本类型
  • 使用(以Integer为例)

    ArrayList<Integer> listInt = new ArrayList<>();
    listInt.add(100);

    int num = listInt.get(0);

String

  • java.lang.String
  • 程序中所有的双引号字符串全是String类的对象
  • 字符串内的内容不可改变
  • 字符串可以共享
  • 效果上相当于char[]字符数组, 但底层原理是byte[]字节数组【在JDK 1.8也就是Java 8中看到的其实是 char[]字符数组, Java 9中对其进行了优化, 使用了byte[]字节数组来节省空间(如使用字母时char需要两个字节, 而byte只需要一个字节)】

Ctrl + Alt点击String查看定义:

public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
.....

创建字符串

  • public String(): 创建一个空白字符串, 不含有任何内容
  • public String(char[] array): 根据字符数组的内容, 来创建对应的字符串
  • public String(byte[] array): 根据字节数组的内容, 来创建对应的字符串
  • String str = "xxxx":直接创建, 也是对象
String str = new String();
System.out.println(str);

char[] chars = {'L', 'a', 't'};
String str2 = new String(chars);
System.out.println(str2);

byte[] bytes = {97, 98 , 99};
String str3 = new String(bytes);
System.out.println(str3);

String string = "Hello";

字符串的常量池

程序当中直接写上双引号的字符串, 就在字符串常量池中

String str1 = "abc";
String str2 = "abc";

char[] chars = {'a', 'b', 'c'};
String str3 = new String(chars);

System.out.println(str1 == str2);
System.out.println(str1 == str3);
System.out.println(str3 == str2);

运行结果:

true
false
false
  • 对于基本类型来说, ==是【数值】比较
  • 对于引用类型来说, ==是【地址值】的比较

java-string

  • 对于""双引号直接括起来的字符串, 在常量池当中
  • 读于new出来的字符串, 不在常量池中

常用方法

字符比较
  • public boolean equals(Object obj): 参数可以是任何对象, 只有参数是一个字符串并内容相同的才会给true

    • 任何对象都可以用Object进行接受

    • 具有对称性a.equals(b)b.equlas(a)效果相同

    • 如果比较双方一个常量一个变量, 推荐把常量字符写在前面

      • 推荐: "abc".equals(str)

      • 不推荐:str.equals("abc")

      • 理由

        String str = null;
        System.out.println("abc".equals(str)); // false
        System.out.println(str.equals("abc")); // 报错:空指针异常 NullPointerException
  • public boolean equalsIgnoreCase(String str): 参数是字符串, 忽略大小写判断

使用

String str1 = "Hello";
char[] chars = {'H', 'e', 'l', 'l', 'o'};
String str2 = new String(chars);

System.out.println(str1.equals(str2));
System.out.println(str2.equals("Hello"));
System.out.println("Hello".equals(str1));

String str3 = "hello";
System.out.println(str3.equalsIgnoreCase(str2));

运行结果:

true
true
true
true
字符获取
  • public int length(): 获取字符串当中含有的字符个数, 拿到字符串长度
  • public String concat(String str): 将当前字符串和参数字符串拼接成为返回值(新的字符串)
  • public char charAt(int index): 获取指定索引位置的单个字符(从0开始)
  • public int indexOf(String str): 查找参数字符串在本字符串当中首次出现的索引位置
字符串截取
  • public String subtring(int index): 截取从参数位置一直到字符串末尾, 返回新字符串
  • public String substring(int begin, int end): 截取从begin开始, 一直到end结束, 中间的字符串。 备注: [begin, end), 包含左边, 不含右边
字符串转换
  • public char[] toCharArray(): 将当前字符串拆分成为字符数组作为返回值
  • public byte[] getBytes():获取当前字符串底层的字节数组
  • public String replace(CharSequence oldString, CharSequence newString): 将所有出现的老字符串替换为新的字符串, 返回替换之后的新字符串
字符串切割
  • public String[] split(String regex): 根据regex的规则, 将字符串切分成若干部分(由于,用于切分因此生成的字符串数组中的字符串不包含,)
  • 实际上, split方法的参数其实是正则表达式, 因此当我们string.split('.')时并不会用.进行切割, 因为.在正则中有特殊的含义, 因此我们必须写string.split('\\.'), 用\\来转义

Arrays

  • java.util.Arrays: 一个与数组相关的工具类, 里面提供了大量的静态方法, 用来实现数组的常见操作

  • public static String toString(数组):将参数数组变成字符串

  • public static void sort(数组): 按默认升序(从小到大)对数组元素进行排序

    • 如果时数值, sort默认按照默认升序(从小到大)对数组元素进行排序
    • 如果时字符串, 按字母升序排序
    • 如果时自定义类型, 则必须要有Comparrable或者Comparator接口的支持

Math

  • java.util.Math: 数学工具类, 提供了大量静态方法, 完成于数学运算相关的操作
  • public static double abs(double num): 获取绝对值
  • public static double ceil(double num): 向上取整
  • public static double floor(double num): 向下取整
  • public static long round(double num): 四舍五入
  • Math.PI:近似圆周率

Java项目结构

java-project_structure

IDEA

  • iml: 配置文件
  • src: 代码
  • External Libraries: JDK的文件
  • psvm一键生成public static void main(String[] args)
  • sout一键生成System.out.println();
  • Alt + Insert 一键生成Getter/Setter方法