本文是学习 Java 过程中所作的知识点总结,希望能给大家一些快速参考。
假如 JDK
解压缩后的包在 /home/cunyu/soft/jdk-11.0.7
目录,则在 /etc/profile
文件中加入如下配置:
JAVA_HOME = /home/cunyu/soft/jdk-11.0.7
PATH = $JAVA_HOME/bin:$PATH
# 编译
javac HelloWorld.java
# 运行
java HelloWorld
public class Item{
// 物品名
String name;
// 价格
int price;
public static void main(String[] args){
Item hp = new Item();
hp.name = "血瓶";
hp.price = 50;
Item shoes = new Item();
shoes.name = "草鞋";
shoes.price = 300;
Item sword = new Item();
sword.name = "长剑";
sword.price = 530;
}
}
public class Item{
// 物品名
String name;
// 价格
int price;
// 血量
float hp;
public legendary(){
System.out.println("超神");
}
public float getHp(){
return hp;
}
public void recovery(float blood){
hp += blood;
}
}
总共有 8 大基本数据类型
byte
,1 个字节,8 位short
,2 个字节, 16 位int
,4 个字节,32 位long
,8 个字节,64 位float
,4 个字节,32 位double
,8 个字节,64 位char
,2 个字节,16 位boolean
,1 位给基本数据类型变量赋值的方式叫做 字面值;
从小达到自动转,从大到小强制转;
字母、数字、_、$
;字母、$、_
,不能是 数字
;Java
中 {}
包括的部分,称为一个块;
当变量声明在 类下 时,叫做 字段,或者 属性、成员变量、Field,作用域 从声明的位置开始的整个类;
当变量声明在 方法上 时,叫做 参数,作用域为 该方法内所有代码,其他方法和类都不能访问;
当变量声明在 方法内 时,叫做 局部变量,作用域为 从声明的位置开始,直到所处于的块结束;
当声明一个用 final
修饰的变量时,说明该变量 有且只有一次赋值的机会;
+、-、×、/、%、++、--
int
)进行运算时,最终返回结果按照最长的长度计算;int
)进行运算时,最终返回结果按照 int
计算;++、--
前置时,先运算,再取值;后置时、先取值,再计算;>、>=、<、<=、==、!=
&、&&、|、||、!、^
false
时,运算符右侧则不再计算;Integer.toBinaryString()、|、&、^、~、<<、>>、>>>
>>
与 >>>
的区别
>>
会将正数所有位右移,并在最前面补 0
,会将负数所有位右移,并在最前面补 1
;>>>
会将负数的二进制的第一位的 1
也向右移动,然后在前面补 0
,从而导致负数在无符号右移后,得到一个正数;>>
移动后数的正负性不变,>>>
移动后变为正数;表达式?值1:值2
,当表达式为真时,返回值1;当表达式为假时,返回值2;switch
中可以使用 byte、short、int、char、String、enum
;break
;String
的实质还是使用正数,是通过编译后将其转化为 hash
值;// 声明一个引用
int[] arr;
// 创建一个长度为 10 的数组,且使用引用 arr 指向该数组
//分配长度为 5 的数组,但未赋值
int[] a = new int[5];
//没有赋值,那么就会使用默认值,作为int类型的数组,默认值是0
System.out.println(a[0]);
//进行赋值
a[0] = 100;
a[1] = 101;
a[2] = 103;
a[3] = 120;
a[4] = 140;
// 方式 1,分配空间同时赋值
int[] arr1 = new int[]{100,102,444,836,3236};
// 方式 2
int[] arr2 = {100,102,444,836,3236};
// 方式 3,分配空间的同时指定内容
int[] arr3 = neew int[5]{100,102,444,836,3236};
首先在未排序数组中找到最小元素,存放到排序数组的其实位置,然后再从剩余未排序的元素中寻找最小的元素,放到排序数组起始位置,以此类推直到数组所有元素排序完毕;
/**
* 选择排序
* @param source 未排序数组
*/
public void selectSort(int[] source){
// 数组长度
int size = source.lenth;
for(int i = 0; i < size; i++){
for(int j = i + 1; j < size; j++){
// 进行交换,从小到大
if(source[i] > source[j]){
// 进行交换,从大到小
// if(source[i] < source[j])
int tmp = source[i];
source[i] = source[j];
source[j] = tmp;
}
}
}
}
通过双层循环,内层循环将相邻的两个数进行比较,将最大的一个数以冒泡(两两交换)的形式传送到数组尾部,每次将一个最大值传到数组尾部,外层循环则实现依次将当前最大值传送,最终实现排序;
/**
* 冒泡排序
* @param source 未排序数组
*/
public void bubbleSort(int[] source){
// 数组长度
int size = source.length;
for(int i = 0; i < size - 1; i++){
for(int j = 0; j < size - 1 - i; j++){
if(source[j] > source[j + 1]){
int tmp = source[j];
source[j] = source[j + 1];
source[j + 1] = tmp;
}
}
}
}
数组一旦分配空间,就不再可变,当我们需要在原有数组的基础上增删改查时,则需要对数组进行复制;
/**
* @param src 源数组
* @param srcPos 源数组要复制的起始位置
* @param dest 目的数组
* @param destPos 目的数组要放置的起始位置
* @param length 复制的长度
*/
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
import java.util.Arrays;
/**
* Created with IntelliJ IDEA.
* Version : 1.0
* Author : cunyu
* Email : cunyu1024@foxmail.com
* Website : https://cunyu1943.github.io
* 公众号 : 村雨遥
* Date : 2020/5/6 上午10:58
* Project : mavenDemo
* Package : PACKAGE_NAME
* Class : MergeArr
* Desc : 合并数组
*/
public class MergeArr {
public static void main(String[] args) throws Exception {
int[] arr1 = {1, 5, 7, 9};
int[] arr2 = {0, 4, 11, 45};
int destSize = arr1.length + arr2.length;
int[] mergeArr = new int[destSize];
merge(arr1, arr2, mergeArr);
System.out.println(Arrays.toString(mergeArr));
}
/**
* 合并数组
*
* @param arr1 源数组 1
* @param arr2 源数组 2
* @param destArr 合并后的数组
*/
public static void merge(int[] arr1, int[] arr2, int[] destArr) {
// 将数组 1 合并到最终数组
System.arraycopy(arr1, 0, destArr, 0, arr1.length);
// 将数组 2 合并到最终数组
System.arraycopy(arr2, 0, destArr, arr1.length, arr2.length);
}
}
方法 | 功能 |
---|---|
copyOfRange | 数组复制 |
toString() | 转换为字符串 |
sort | 排序 |
binarySearch | 搜索 |
equals | 判断是否相同 |
fill | 填充 |
import java.util.Arrays;
/**
* Created with IntelliJ IDEA.
* Version : 1.0
* Author : cunyu
* Email : cunyu1024@foxmail.com
* Website : https://cunyu1943.github.io
* 公众号 : 村雨遥
* Date : 2020/5/6 下午1:27
* Project : mavenDemo
* Package : PACKAGE_NAME
* Class : ArraysOperation
* Desc : Arrays 常见操作
*/
public class ArraysOperation {
public static void main(String[] args) throws Exception {
int[] arr = {1, 9, 8, 49};
// 复制
int[] newArr = Arrays.copyOfRange(arr, 0, arr.length);
// 转换为字符串
System.out.println(Arrays.toString(newArr));
// 排序
Arrays.sort(newArr);
// 搜索
System.out.println(Arrays.binarySearch(newArr, 8));
// 比较是否相等
System.out.println(Arrays.equals(arr, newArr));
// 填充
Arrays.fill(arr, 10);
System.out.println(Arrays.toString(arr));
}
}
class Item{
String name;
int price;
}
public class Armor extends Item{
int ac;
public static void main(String[] args) {
Armor a1 = new Armor();
Armor a2 = new Armor();
// 布甲相关属性
a1.name = "布甲";
a1.price = 300;
a1.hjdj =15;
// 锁子甲相关属性
a2.name = "锁子甲";
a2.price = 500;
a2.hjdj =40;
}
**方法重载 ** 指方法名一样,但参数类型不一样;
通过一个类构建一个对象的过程叫做 实例化,而实例化是通过 构造方法 来实现的;构造方法名和类名一样,但是 没有返回类型,默认会提够一个无参的构造方法,this
代表当前对象;
public class Hero{
String name;
float hp;
float armor;
int moveSpeed;
Hero(String name, float hp, float armor, int moveSpeed){
this.name = name;
this.hp = hp;
this.armor = armor;
this.moveSpeed = moveSpeed;
}
}
符号 | 说明 |
---|---|
private | 私有 |
package/friendly/default | 默认, |
protected | 受保护 |
public | 公有 |
自身 | 同包子类 | 不同包子类 | 同包类 | 其他类 | |
---|---|---|---|---|---|
private | 访问 | 不能继承 | 不能继承 | 无法访问 | 无法访问 |
package/friendly/default | 访问 | 继承 | 不能继承 | 访问 | 无法访问 |
protected | 访问 | 继承 | 继承 | 访问 | 无法访问 |
public | 访问 | 继承 | 继承 | 访问 | 访问 |
private
封装;public
方便调用;protected
;package
使用较少;static
修饰时,叫做 类属性,也叫 静态属性,当一个属性被声明为类属性时,所有对象均共享一个值;
对象.类属性
:teemo.hp
;类.类属性
:Hero.hp
,推荐使用;static
修饰的方法,访问类方法,无需对象 存在就可以直接访问,若某一方法中 未调用任何对象属性,则可以设计为类方法;对象.类方法
:teemo.die()
;类.类方法
:Hero.battleWin()
,推荐使用;public class Hero{
// 声明同时初始化
public String name = "teemo";
protected float hp;
float maxHP;
// 初始化块初始化
{
maxHP = 999;
}
// 构造方法中初始化
public Hero(){
hp = 100;
}
}
public class Hero{
public String name;
protected float hp;
float maxHP;
// 声明时初始化
public static int itemCapacity = 10;
// 静态初始化块
static{
itemCapacity = 20;
}
}
静态初始化块 -> 非静态初始化块 ->构造方法
;
Singleton
模式,指在一个类在 JVM
中,只存在一个实例;public static
的 getInstance
方法获取一个对象,每次获取的都是同一个对象,属于 立即加载,无论是否用到该对象,均加载;getInstance
方法时才会创建实例,每次获取的都是同一个对象,属于 延迟加载,只有在使用该对象时才加载,同时具有 线程安全;public staic
的 getInstance
方法,**返回上一个要素中的静态属性 ** ;/**
* 饿汉式
*/
public class Earth{
// 私有构造方法,使得无法在外部通过 new 实例化
private Earth(){
}
// 定义类属性同时初始化
private static Earth instance = new Earth();
// private static 方法,用于获取对象
public static Earth getInstance(){
return instance;
}
public static void main(String[] args){
Earth earth1 = Earth.getInstance();
Earth earth2 = Earth.getInstance();
// true
System.out.println(earth1 == earth2)
}
}
/**
* 懒汉式
*/
public class Earth{
// 私有构造方法,使得无法在外部通过 new 实例化
private Earth(){
}
// 定义类属性
private static Earth instance;
// private static 方法,用于获取对象
public static Earth getInstance(){
// instance 未指向任何对象,将其实例化
if(instance == null){
instance = new Earth();
}
return instance;
}
public static void main(String[] args){
Earth earth1 = Earth.getInstance();
Earth earth2 = Earth.getInstance();
// true
System.out.println(earth1 == earth2)
}
}
public enum Heros{
TANK,
WIZARD,
ASSASSIN,
WARRIOR,
ASSIST,
RANGED,
PUSH,
FARMING
}
public class Demo{
public static void main(String[] args){
for(Heros hero : Heros.values()){
System.out.println(hero);
}
}
}
static
和 final
变量;Hero hero = new Hero();
AdHero ad = new AdHero();
hero = ad;
Hero hero = new Hero();
AdHero ad = new AdHero();
ad = (AdHero)hero;
子类可以继承父类对象方法,继承后重复提供该方法,则叫做 方法的重写,也叫覆写(override);
class Item{
String name;
int price;
public void buy(){
System.out.println("购买");
}
public void effect(){
System.out.println("物品使用后生效");
}
}
public class LifePotion extends Item{
@override
public void effect(){
System.out.println("血瓶使用后回血");
}
}
+
两侧是整形,则代表 数字相加;若其中任意一个是字符串,则代表 字符串连接;public interface Mortal{
public void die();
}
public class Hero{
public String name;
protected float hp;
public Hero(String name, float hp){
this.name = name;
}
public void kill(Mortal m){
m.die();
}
public static void main(String[] args){
Hero hero = new Hero("赵云", 1000.0f);
APHero ap = new APHero("安琪拉", 400.0f);
ADHero ad = new ADHero("后羿", 450.0f);
ADAPHero adap = new ADAPHero("嫦娥", 600.0f);
hero.kill(ad);
hero.kill(ap);
hero.kill(adap);
}
}
public class ADHero extends Hero implements Mortal{
@override
public void die(){
System.out.println("AD 被击杀");
}
}
public class APHero extends Hero implements Mortal{
@override
public void die(){
System.out.println("AP 被击杀");
}
}
public class ADAPHero extends Hero implements Mortal{
@override
public void die(){
System.out.println("ADAP 被击杀");
}
}
public class Test {
public static void main(String[] args) {
Circle circle = new Circle();//本类引用指向本类对象
Shape shape = new Circle();//父类引用指向子类对象(会有隐藏和覆盖)
System.out.println(circle.name);
circle.printType();
circle.printName();
//以上都是调用Circle类的方法和引用
System.out.println(shape.name);//调用父类被隐藏的name属性
shape.printType();//调用子类printType的方法
shape.printName();//调用父类隐藏的printName方法
}
}
class Shape {
public String name = "shape";
public Shape(){
System.out.println("shape constructor");
}
public void printType() {
System.out.println("this is shape");
}
public static void printName() {
System.out.println("shape");
}
}
class Circle extends Shape {
public String name = "circle"; //父类属性被隐藏
public Circle() {
System.out.println("circle constructor");
}
//对父类实例方法的覆盖
public void printType() {
System.out.println("this is circle");
}
//对父类静态方法的隐藏
public static void printName() {
System.out.println("circle");
}
}
输入结果如下 :
shape constructor
circle constructor
circle
this is circle
circle
shape
this is circle
shape
所有类均继承自 Object
,所以所有类均有 toString()
方法,返回 当前对象的字符串表达 ;
当一个对象没有任何引用指向的时候,就满足垃圾回收的条件,当被垃圾回收时,其 finalize()
方法就会 被虚拟机 JVM
调用,此时无需开发人员主动调用;
用于判断两个对象内容是否相同;
不属于 Object
类的方法,用于判断两个对象是否相同(即判断两个引用是否指向同一对象);
用于返回一个对象的哈希值;
返回一个对象的 类对象,主要用于 反射机制;
final
修饰类时,表示当前类不允许继承;final
修饰方法时,表示该方法不允许被重写;final
修饰基本类型变量时,表示该变量只有一次赋值机会;final
修饰引用时,表示该引用只有一次指向对象的机会;abstract
修饰;而当一个类有抽象方法时,该类必须被声明为 抽象类,抽象类不能直接实例化;
public、package、protected、private、静态和非静态属性、final 和非 final 属性
,但 接口中声明的属性只能是 public、静态、final
;public abstract class Item{
public abstract void disposable();
public static void main(String[] args) throws Exception{
Item item = new Item(){
public void disposable(){
System.out.println("一次性");
}
}
}
}
默认方法自 JDK8
加入,指 接口中也可以加入具体方法(即默认方法,声明为 default
),而不仅限于抽象方法;
public abstract class Animal{
protected int legs;
protected Animal(int legs){
this.legs = legs;
}
public abstract void eat();
public void walk(int legs){
if(legs > 0){
System.out.println("用" + legs + "条腿走路")
}
}
}
class Spider extends Animal{
protected Spider(int legs){
super(legs);
}
@Override
public void eat(){
System.out.println("蜘蛛吃东西");
}
}
public interface Pet{
String name;
public void setName(String name);
public String getName();
public void play();
}
class Cat extends Animal implements Pet{
String name;
protected Cat(String name){
super(4);
this.name = name;
}
public Cat(){
this.name = "";
}
@Override
public void eat(){
System.out.println("猫在吃鱼");
}
@Override
public void setName(String name){
this.name = name;
}
@Override
public String getName(){
return this.name;
}
@Overrid
public void play(){
System.out.println("猫在玩毛线");
}
}
class Fish extends Animal implements Pet{
private String name;
protected Fish(){
super(0);
}
@Override
public void setName(String name){
this.name = name;
}
@Override
public String getName(){
return this.name;
}
@Override
public void walk(int legs){
System.out.println("鱼没有腿,只能游泳");
}
@Override
public void play(){
System.out.println("鱼在水力追蝌蚪");
}
@Override
public void eat(){
System.out.println("鱼吃草");
}
}
基本数据类型 | 封装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
=
自动把 基本类型转换为封装类 的过程叫做自动装箱;=
自动将 封装类转换为基本类型 的过程叫做自动拆箱;int
类型的最大最小值 : 最大值 :Integer.MAX_VALUE
;最小值 :Integer.MIN_VALUE
;public class TestNumber{
public static void main(String[] args) throws Exception{
byte byteNum1 = 3;
// 自动装箱
Byte byteNumClass1 = byteNum1;
// 自动拆箱
Byte byteNumClass2 = new Byte(byteNum1);
byte byteNum2 = byteNumClass2;
}
}
String
类的静态方法 valueOf
;toString
方法;+
将数字与 “”
相连;public class Demo{
public void main(String[] args) throws Exception{
int num = 200;
// 方法 1
String numString1 = String.valueOf(num);
// 方法 2
Integer numClass = new Integer(num);
String numString2 = numClass.toString();
// 方法 3
String numString3 = num + "";
}
}
parseXxx
进行装换;public class Demo{
public void main(String[] args) throws Exception{
String numString1 = "34";
int num1 = Integer.parseInt(numString1);
String numString2 = "35.34";
float num2 = Float.parseFloat(numString2);
}
}
字符 | 含义 |
---|---|
%s | 字符串 |
%d | 数字 |
%n | 换行(平台无关) |
public class TestNumber {
public static void main(String[] args) {
String name ="迦罗";
int kill = 8;
String title="超神";
String sentenceFormat ="%s 在进行了连续 %d 次击杀后,获得了 %s 的称号%n";
// printf 和 format 效果一样
//使用printf格式化输出
System.out.printf(sentenceFormat,name,kill,title);
//使用format格式化输出
System.out.format(sentenceFormat,name,kill,title);
}
}
DOS 和 Windows
中,每行结尾是 \r\n
;Linux
中,每行结尾是 \n
;Mac
中,每行结尾是 \r
;import java.util.Locale;
public class TestNumber {
public static void main(String[] args) throws Exception{
int year = 2020;
//总长度,左对齐,补0,千位分隔符,小数点位数,本地化表达
//直接打印数字
System.out.format("%d%n",year);
//总长度是8,默认右对齐
System.out.format("%8d%n",year);
//总长度是8,左对齐
System.out.format("%-8d%n",year);
//总长度是8,不够补0
System.out.format("%08d%n",year);
//千位分隔符
System.out.format("%,8d%n",year*10000);
//小数点位数
System.out.format("%.2f%n",Math.PI);
//不同国家的千位分隔符
// 法国
System.out.format(Locale.FRANCE,"%,.2f%n",Math.PI*10000);
// 美国
System.out.format(Locale.US,"%,.2f%n",Math.PI*10000);
// 英国
System.out.format(Locale.UK,"%,.2f%n",Math.PI*10000);
}
}
String
的构造方法创建;+
进行字符串拼接;public class TestString {
public static void main(String[] args) {
// 字面值创建
String garen ="盖伦";
// 构造方法创建
String teemo = new String("提莫");
// 通过字符数组创建
char[] cs = new char[]{'崔','斯','特'};
String hero = new String(cs);
// 通过 + 加号进行字符串拼接
String hero3 = garen + teemo;
}
}
String
被 final
修饰,无法被继承,而且一旦被创建就不可改变(不能增加长度、不能减少长度、不能插入字符、不能删除字符、不能修改字符);
方法 | 简介 |
---|---|
charAt(int index) | 获取某索引位置字符 |
toCharArray() | 将字符串转换为字符数组 |
subString(int start, int end) | 获取索引位置在 [start, end) 的子字符串 |
split(String str) | 根据分割符将字符串分割为字符串数组 |
trim() | 去掉首尾空格 |
toLowerCase() | 全部变成小写 |
toUpperCase() | 全部变成大写 |
indexOf | 字符或子字符串第一次出现的索引位置 |
lastIndexOf | 字符或子字符串最后一次出现的索引位置 |
contains | 字符串是否包含子字符串 |
replaceAll | 用指定字符串替换目标字符串 |
replaceFirst | 用指定字符串替换第一个目标字符串 |
startsWith | 判断字符串是否以子字符串开始 |
endsWith | 判断字符串是否以子字符串结束 |
用 ==
比较字符串是否指向同一对象,equals()
方法比较字符串内容是否一样;
注意特例 :
public class TestString {
public static void main(String[] args) {
String str1 = "the light";
String str2 = new String(str1);
// 用于判断是否是同一个字符串对象
System.out.println( str1 == str2); // false
// 用于判断是否是同一个字符串对象
System.out.println(str1.equals(str2)); // true
// 特例,当编译器遇到字符串字面值时,若发现有重复的,则会直接使用而不再重复创建
String str3 = "the light";
System.out.println( str1 == str3); // true
}
}
StringBuffer
不同于 String
,属于可变长的字符串,需要经常操作字符串时,StringBuffer
性能更高,常用方法如下:
方法 | 功能 |
---|---|
append | 追加 |
delete | 删除 |
insert | 插入 |
reverse | 反转 |
length | 内容长度 |
capacity | 总空间 |
public class TestString {
public static void main(String[] args) {
String str1 = "let there ";
// 根据str1创建一个StringBuffer对象
StringBuffer sb = new StringBuffer(str1);
//在最后追加
sb.append("be light");
System.out.println(sb);
// 删除4-10之间的字符
sb.delete(4, 10);
System.out.println(sb);
// 在4这个位置插入 there
sb.insert(4, "there ");
System.out.println(sb);
// 反转
sb.reverse();
System.out.println(sb);
// 内容长度
System.out.println(sb.length());
// 总空间
System.out.println(sb.capacity());
}
}
SimpleDateFormat
类常用方法方法 | 功能 |
---|---|
format | 日期转字符串 |
parse | 字符串转日期 |
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 日期转字符串
*/
public class TestDate {
public static void main(String[] args) throws Exception{
//y 代表年
//M 代表月
//d 代表日
//H 代表24进制的小时
//h 代表12进制的小时
//m 代表分钟
//s 代表秒
//S 代表毫秒
SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS" );
Date d= new Date();
String str = sdf.format(d);
System.out.println("当前时间通过 yyyy-MM-dd HH:mm:ss SSS 格式化后的输出: "+str);
SimpleDateFormat sdf1 =new SimpleDateFormat("yyyy-MM-dd" );
Date d1= new Date();
String str1 = sdf1.format(d1);
System.out.println("当前时间通过 yyyy-MM-dd 格式化后的输出: "+str1);
}
}
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class TestDate {
public static void main(String[] args) {
SimpleDateFormat sdf =new SimpleDateFormat("yyyy/MM/dd HH:mm:ss" );
String str = "2020/5/1 12:12:12";
try {
Date d = sdf.parse(str);
System.out.printf("字符串 %s 通过格式 yyyy/MM/dd HH:mm:ss %n转换为日期对象: %s",str,d.toString());
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}