JAVA-第一部分-基础语法及部分API

794 阅读14分钟

IDEA快捷键

  • option+command+左键点击 跳转
  • shift+fn+F6 全局修改名字
  • command+N 新建
  • ctrl+option+i 格式化
  • shift+ctrl+R 运行
  • shift+cmooand+up/down 某行上下移动
  • tab 向后缩近 shift+tab 向前缩近
  • option+enter 处理代码报错
  • 函数上/**函数方法注释
  • ctrl+h 查看继承类

IDEA代码提速

  • .var 创建属性
  • xxx.fori 创建循环

JAVA运行

  • JVM, Jave Virtual Machine,Java虚拟机,在对应平台上翻译Java,实现跨平台
  • JRE,Java Development Environment,运行环境
  • JDK, Java Development Kit,开发工具包
  • JDK包含开发工具和JRE,JRE包含JVM和核心类库

HelloWorld

  • psvm,直接生成主函数
  • sout,打印

重载

  • overload,放个方法名一样,但是参数列表不一样
  • 只需要一个唯一的方法名称,就可以实现多个类似的但是不同的功能
  • 参数个数不同;参数类型不同;参数的多类型顺序不同
  • 与参数的名称无关;与方法的返回值类型无关

数据类型默认值

  • 整数,0
  • 浮点,0.0
  • 字符,'\u0000'
  • 布尔,false
  • 引用,null

Java内存

  • 五个部分
  1. 栈 stack,存放的都是方法中的局部变量。局部变量有作用域,一旦超出作用域,立即从栈内存当中小时。进栈为压栈,先进后出
  2. 堆 heap,凡是new出来的东西都有一个地址值,16进制。
  3. 方法区 Method Area,存储.class相关,包含方法的信息
  4. 本地方法栈 Native Method Stack,与操作系统相关
  5. 寄存器 pc Register,CPU相关 image.png

数组

  • 数组长度,在程序运行期间不可改变
  • length获取数组长度
  • 数组作为方法参数的原理,传递进去的是数组的地址值,方法通过地址值访问数组

类与对象

  • 类,对一类事物的描述,抽象的,图纸
  • 对象,是一类事物的实例,具体的,根据图纸设计的实体
  • 类是对象的模板,对象是类的实体
  • 对象包括属性和行为,属性(成员变量)指是什么,行为(成员方法)指能做什么

类的内存空间

  • 成员变量存放在堆中
  • 成员方法以指针地址的方式存在堆中,指向方法区的实际方法 11701627626257_.pic_hd.jpg

getter与setter

  • 基本数据类型boolean类型,getter方法要写成isXxx方法

this关键字

  • 指出本类当中的成员变量
  • 通过谁调用,谁就是this
  • 可以在本类的构造方法中,访问另一个构造方法,但是也必须是第一个语句

构造方法

  • 在初始值赋值后,才进行构造方法
  • public 类名称(参数类型 参数名称) {方法体}
  • 构造方法的名称必须和类名完全一样
  • 构造方法不要写返回值类型,void都不行
  • 不能return一个返回值
  • 如果没有编写任何构造方法,编译器会默认赠送一个构造方法,什么都不做
  • 一旦编写了构造方法,将不再赠送
  • 构造方法可以重载

标准的类

  • 所有成员变量都要使用private修饰
  • 为每一个成员变量编写一对getter/setter
  • 无参数的构造方法
  • 全参数的构造方法
  • 在代码面 command+N 自动生成

局部变量与成员变量

  1. 定义的位置不一样
  • 局部变量:在方法的内部
  • 成员变量:在方法的外部,直接写在类中
  1. 作用范围不一样
  • 局部变量:只有方法当中才可以使用,出了方法不行
  • 成员变量:整个类全部可以使用
  1. 默认值不一样
  • 局部变量:没有默认值,如果想要使用,必须手动赋值
  • 成员变量:如果没有赋值,会赋默认值
  1. 内存的位置不一样
  • 局部变量:栈内存
  • 成员变量:堆内存
  1. 生命周期不一样
  • 局部变量:随着方法进栈诞生,随着方法出栈小时
  • 成员变量:随着对象创建诞生,随着对象被垃圾回收消失

匿名对象

  • 只有右边的对象,没有左边的名字和赋值运算符
  • 如果确定有一个对象只需要使用唯一的一次,就可以使用匿名对象

static关键字

  • 类中用static修饰后的成员变量,不再属于对象,而是属于类,凡事本类实例化后的对象,都共享同一份
  • 类中用static修饰后的成员方法,在使用的时候,可以直接通过类名称直接调用,类似类方法
  • 静态不能直接访问静态,成员方法可以访问静态变量,静态方法不能访问非静态成员变量
  • 内存中,先有的静态内容,后有的非静态内容
  • 静态方法中,不能使用this关键字 11731627718164_.pic_hd.jpg

静态代码块

  • 当第一次使用本类时,静态代码块唯一的执行一次
  • 静态内容,总是优先于非静态
  • 用来一次性地对静态变量进行赋值
static {
    System.out.println("i am static code");
}

面向对象

  • 封装
  • 继承
  • 多态

封装

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

继承

  • 继承是多态的提前,如果没有继承,就没有多态
  • 继承主要解决共性抽取的问题
  • 父类/子类;基类、超类/派生类
  • 子类可以拥有父类的内容;子类可以拥有自己专有的内容
  • 子类就是一个父类,子类可以被当作父类看待

访问成员变量

  • 直接通过对象访问成员变量,等号左边是谁,就优先用谁,没有则向上找
  • 间接通过成员方法访问成员变量,方法属于谁优先用谁的成员变量,没有则向上找

区分父子类成员变量

  • 直接局部变量名
  • this.子类成员变量
  • super.父类成员变量
public void method() {
    String name = "zhangsan";
    System.out.println(name);
    System.out.println(this.name);
    System.out.println(super.name);
}

成员方法

  • 创建的对象是谁,就优先用谁,没有就向上找

重写

  • 覆盖,覆写
  • override,在继承关系中,方法的名称一样,参数列表也一样
  • @Override 写在方法前面,检测是否重写成功
  • 子类方法的返回值,必须小于等于父类方法的返回值范围
  • 子类方法的权限必须大于等于父类方法的权限修饰符 public > protected > (default 留空) > private

设计原则

  • 对于已经投入使用的类,不要进行修改,定义一个新的类,来重复利用其中的共性内容,并添加新内容

构造方法

  • 如果父类只有有参构造,子类必须覆盖重写
  • 子类构造方法中,会默认先调用父类构造方法,所以在实例化过程中,会先调用父类构造方法,再调用子类构造方法
  • 子类必须调用父类构造方法,不写则赠送super(),写了则用指定的super调用,并且有且只能有一个,且在子类构造方法的第一句
  • super和this两种构造调用,但是只能选一种 11741627724450_.pic_hd.jpg

继承特点

  • 单继承,一个类的直接父类只能有唯一一个
  • 多级继承,可以有多层的继承
  • 一个父类可以拥有很多个子类

抽象类

  • 如果父类的方法不能具体实现,则为抽象方法
  • 抽象方法所在类,必须是抽象类,abstract
  • 抽象类中可以有构造方法,但是只能通过子类构造方法进行调用
  • 抽象类不能直接创建对象
  • 抽象类的子类,必须重写抽象父类的抽象方法,除非子类也是抽象类

接口

  • Interface
  • 类似ios中的协议
  • 接口不能有静态方法块;不能有构造方法
  • 一个类可以同时实现多个接口,如果多个接口有同样的抽象方法,实现类中会进行统一重写覆盖;有同样的默认方法,一定要进行覆盖重写
  • 如果一个类的父类和接口类,方法冲突,优先父类方法
  • 公共的规范标准
  • 引用数据类型
  • 实现类,implements
  • 包括 常量,抽象方法,默认方法,静态方法,私有方法
// 接口中的抽象方法,修饰符必须是`public abstract`,可以选择省略
public abstract void abstractMethod();
// 默认方法可以直接被实例化的实现类对象使用,而不需要在实现类中重写,但是也可以在实现类覆盖重写默认方法,相当于父类自带一个方法
public default void defaultMethod() {
    System.out.println("默认方法");
}
// 静态方法,通过接口类直接调用
public static void staticMethod() {
    System.out.println("静态方法");
}
// 私有方法,解决接口中代码重复问题,如果要在静态方法中调用,要加static关键字
private void privateMethod() {
    System.out.println("privateMethod");
}
private static void privateStaticMethod() {
    System.out.println("privateStaticMethod");
}
  • 接口中的成员变量只能是常量,public static final,一旦赋值,不可改变;必须进行赋值;
public static final int num = 10;

多态

  • extends继承和implements实现,是多态性的前提
  • 父类引用指向子类对象,父类名称 对象名 = new 子类名称()
  • 成员方法,编译看左,运行看右。
  1. 编译时看左边有没有需要调用的内容,如果没有则报错;
  2. 运行时,在右边的空间进行查找
  3. 父类调用子类特有的方法,编译报错;因为编译时,在父类找不到子类特有方法
  • 成员变量,编译看左,运行看左
  1. 直接调用,等号左边是谁,就找谁的,没有则向上找,父类引用在子类的空间中调用了父类的成员
  2. 间接调用,方法属于谁,调用谁,没有就向上找
  3. 成员变量是没有覆盖重写的
  • 统一左边
  • 向上转型,父类引用指向子类对象,一定是安全的,从小范围转向了大范围,但是无法调用子类特有的方法
  • 向下转型,还原的动作。子类名称 对象名 = (子类名称)父类对象,目标要与右边类统一
//判断是否属于目标对象,不是则返回-1
if (animal instanceof Cat) {
    Cat cat = (Cat) animal;
    cat.catchFish();
}

if (animal instanceof Dog) {
    Dog dog = (Dog) animal;
    dog.bark();
}

API

  • Application Programming Interface, 应用程序编程接口,SDK自带的方法

一般使用步骤

  • 导包,如果当前类位于同一个包下,不需要导包;只用lava.lang包下的内容不需要导包,其他都需要
  • 创建
  • 使用

Scanner

  • 获取键盘输入
import java.util.Scanner;

//System.in 从键盘输入
Scanner scanner = new Scanner(System.in);
int num = scanner.nextInt();
System.out.println(num);
String str = scanner.next();
System.out.println(str);

random

  • 有参构造,随机性固定
  • 获取Int范围内的数字
Random random = new Random();
//正负都有可能
int res = random.nextInt();
System.out.println(res);
  • 获取0,1,2的某个数字
Random random = new Random();
int res = random.nextInt(3);
System.out.println(res);

arrayList

  • 集合的长度可以随意变化
  • 存的内容全部要是同一类型,并且只能是引用类型,不能是基本类型

存自定义对象

ArrayList<Person> persons = new ArrayList<>();
for (int i = 0; i < 10; i++) {
    //添加
    persons.add(new Person("xiaoming-" + i, 100 / (i + 1)));
}
//插入
persons.add(1,new Person("xiaozhang", 20));
//size() 获取长度
for (int i = 0; i < persons.size(); i++) {
    //get(i) 获取当前索引的内容
    System.out.println(persons.get(i).getName() + "-----" + persons.get(i).getAge());
}
//删除
String removedName = persons.remove(3).getName();
System.out.println(removedName + " - 被删掉");
for (int i = 0; i < persons.size(); i++) {
    //get(i) 获取当前索引的内容
    System.out.println(persons.get(i).getName() + "-----" + persons.get(i).getAge());
}

存基本数据类型

  • 如果要想ArrayList存储基本类型,必须使用基本类型对应的包装类
  • 自动装箱,基本数据类型->包装类型
  • 自动拆箱,包装类型->基本数据类型
基本数据类型 包装类(引用类型)
byte       Byte
short      Short
int        Integer
long       Long
float      Float
double     Double
char      Character
boolean   Boolean
ArrayList<Integer> ints = new ArrayList<>();
ints.add(100);
ints.add(200);
System.out.println(ints);
int num = ints.get(1);
System.out.println(num);

String

  • 程序中所有双引号的字符串都是String对象,创建之后都不能更改
  • 字符串不可改变,所以字符串是可以共享使用的
  • 字符串的效果相当于char[]字符数组,但底层原理是byte[]字节数组

创建方式

//空参构造函数创建
String str1 = new String();

//根据字符数组创建字符串
char[] charArr ={'h', 'w', 'm'};
String str2 = new String(charArr);
System.out.println(str2);

//根据字节数组创建字符串
byte[] byteArr = {90, 87, 85};
String str3 = new String(byteArr);
System.out.println(str3);

//直接创建
String str4 = "hello world";

字符串常量池

  • 程序当中直接写上的双引号字符串,就在字符串常量池中
  • 对于基本类型,==是进行数值比较;对于引用类型,==是进行地址值的比较
  • 直接new的字符串对象,不在常量池中 11721627697779_.pic_hd.jpg

常用方法

  • 字符串比较
String str1 = "hello";
String str2 = "hello";
String str4 = "HeLLO";
char[] chars = {'h', 'e', 'l', 'l', 'o'};
String str3 = new String(chars);

System.out.println(str1.equals(str2));
System.out.println(str1.equals(str3));
System.out.println(str3.equals("hello"));
//推荐方式
System.out.println("hello".equals(str2));
//忽略大小写
System.out.println("hello".equalsIgnoreCase(str4));
  • 获取字符串的个数,字符串长度
String str = "dwaiojdpoawjpeakw";
System.out.println(str.length());
  • 拼接字符串
//str1 str2不变
String str1 = "hello";
String str2 = "world";
String str3 = str1.concat(str2);
System.out.println(str3);
  • 获取指定索引位置的单个字符
char c = "hello".charAt(4);
System.out.println(c);
  • 查找参数字符串在本字符串中首次出现的索引位置
//找不到返回-1
String str = "dwaiojdpoawjpeakw";
int index = str.indexOf("jpea");
System.out.println(index);
  • 截取字符串
String str = "helloworld";
String subStr1 = str.substring(2);
//左闭,右开
String subStr2 = str.substring(5,9);
System.out.println(subStr1);
System.out.println(subStr2);
  • 转换字符串
String str = "helloworld";
//转换成char数组
char[] chars = str.toCharArray();
//转换成byte数组
byte[] bytes = str.getBytes();
//替换字符串
String newStr1 = str.replace(str, "javaHello");
//替换字符
String newStr2 = str.replace('o', 'm');
for (int i = 0; i < chars.length; i++) {
    System.out.println(chars[i]);
}
for (int i = 0; i < bytes.length; i++) {
    System.out.println(bytes[i]);
}
System.out.println(newStr1);
System.out.println(newStr2);
  • 字符串分割
  • split方法的参数其实是一个正则表达式,.无法切割,要用\\.进行转义
String str = "hel, low, orld";
//根据某个字符串进行切割
String[] strings1 = str.split(", ");
//限制返回的字符串数量
String[] strings2 = str.split(",", 2);
for (int i = 0; i < strings1.length; i++) {
    System.out.println(strings1[i]);
}

for (int i = 0; i < strings2.length; i++) {
    System.out.println(strings2[i]);
}

Arrarys

  • 对于排序
  1. 如果是数值,按照升序
  2. 如果是字符串,按照字母升序
  3. 如果是自定义的类型,自定义类需要有Comparable或者Comparator接口的支持
int[] ints = {10, 20, 30};
//将int[] 按照默认格式变成字符串 [10, 20, 30]
String intStr = Arrays.toString(ints);
System.out.println(intStr);

//排序
int[] ints1 = {2,3,5,7,1,2,0,10};
Arrays.sort(ints1);
System.out.println(Arrays.toString(ints1));

Math

//获取绝对值
System.out.println(Math.abs(-2.9));
//向上取整
System.out.println(Math.ceil(4.2));
//向下取整
System.out.println(Math.floor(4.9));
//四舍五入
System.out.println(Math.round(4.6));
System.out.println(Math.round(3.4));
//PI
System.out.println(Math.PI);

Final关键字

  • 修饰类,不能有任何子类
  • 修饰方法,不能被覆盖重写
  • 修饰局部变量,一次赋值,终身不变;对于基本类型,不可变指的是数据不可改变;对于引用类型,不可变指的是地址值不可改变
  • 修饰成员变量,变量不可变,但是必须手动赋值,不会给默认值;否则,必须在所有的构造方法内都进行赋值

权限修饰符

  • 访问权限 || public | protected | defalut | private | |:---:| :---:|:---:|:---:|:---:| |同一个类| Y | Y | Y | Y | |同一个包| Y | Y | Y | N | |不同包子类| Y | Y | N | N | |不同包非子类| Y | N | N | N |

内部类

  • 一个类内部包含另一个类

成员内部类

  • 内用外,随意访问
  • 外用内,要借助内部类对象
  • 内部类和外部类调用
//间接调用内部类
Body b = new Body();
b.methodBody();
//直接调用内部类
Body.Heart bh = new Body().new Heart();
bh.methodHeart();
  • 访问同名成员变量
//局部变量
System.out.println(name);
//内部类成员变量
System.out.println(this.name);
//外部类成员变量 外部类.this.成员变量
System.out.println(Body.this.name);

局部内部类(匿名内部类)

  • 定义在方法内部
  • 只有当前所属的方法才能使用它,出了这个方法就不可以
  • Body中的方法局部内部类
public void methodInner() {
    class Lungs {
        String name = "wangwu";
        public void methodLungs() {
            System.out.println("methodLungs");
            System.out.println(this.name);
        }
    }
    Lungs l = new Lungs();
    l.methodLungs();
}
  • 局部内部类,如果希望访问所在方法的局部变量,那么这个局部变量必须是有效final,即只能被赋值一次
  • 原因是,new出来的对象是在堆中,局部变量是跟着方法走的,在栈内存中,方法运行结束之后立即出栈,局部变量消失,但是new出来的对象会在堆中持续存在,直到,垃圾回收,所以要保证在局部内部类存在期间,局部变量存在,即局部变量的内容不能改变,copy进内部类一份

匿名内部类

  • 直接在方法内使用接口实现类或者抽象类实例化
  • 可以减少实现类的创建,省略了实现类或者子类
  • 接口名称 对象名 = new 接口名称() { 覆盖重写所有抽象方法 }
// new代表创建动作
// 接口名称代表匿名内部类实现哪个接口
// {...} 实现类的内容
MyInterface obj = new MyInterface() {
    @Override
    public void method() {
        System.out.println("anonymousMethod");
    }
};
obj.method();
//匿名对象
new MyInterface() {
    @Override
    public void method() {
        System.out.println("anonymousMethod");
    }
}.method();
  • 匿名内部类,在创建对象的时候,只能使用唯一一次
  • 匿名对象,只能调用唯一一次,如果希望调用多次,那就取个名字

类的权限修饰符

  • 外部类 public/default
  • 成员内部类 public/protected/default/private
  • 局部内部类 类似局部变量,什么都不写