1 static静态关键字
- 实例成员变量:无static修饰,属于对象(对象名.实例成员变量)
private String name;
- 实例方法:属于对象的,只能用对象触发访问(对象名.实例方法)
public void study(){
System.out.println(name + "在好好学习,天天向上~");
}
- 静态成员变量:有static修饰,归属于类,可以被共享,用类名访问(类名.静态成员变量)
public static int onlineNumber = 161;
- 静态成员方法:有static修饰,归属于类,可以被共享,用类名访问(类名.静态成员方法)
public static int getMax(int age1, int age2){
return age1 > age2 ? age1 : age2;
}
注意事项:
1、静态方法中不可以出现this关键字,this只能代表当前对象
2、实例方法可以访问静态成员,也可以访问实例成员(实例方法内部访问)
3、静态方法只能访问静态成员,不能"直接"访问实例成员(静态方法内部访问)
4、在本类中书写方法和变量,可以不加类名和对象名
2 static应用知识:工具类
- 类中都是一些静态方法,每个方法都是以完成一个共用的功能为目的
- 这个类用来给系统开发人员共同使用的
- 优点:调用方便、提高了代码复用
- 工具类无需创建对象,建议将工具类的构造器进行私有
package com.itheima.d2_static_util;
import java.util.Random;
public class ItheimUtil {
/**
注意:由于工具类无需创建对象,所以把其构造器私有化会显得很专业!
*/
private ItheimUtil(){
}
public static String createVerifyCode(int n){
// 开发一个验证码:
// 1、定义一个变量记住验证码。
String code = "";
// 2、定义一个变量记住全部验证码字符。
String data = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
// 3、定义一个循环生成几个随机索引,去得到几个字符
Random r = new Random();
for (int i = 0; i < n; i++) {
// 4、获取随机索引对应的字符。链接给code
int index = r.nextInt(data.length());
code += data.charAt(index);
}
return code;
}
}
package com.itheima.d2_static_util;
import java.util.Random;
public class Check {
public static void main(String[] args) {
// 开发一个验证码:
System.out.println(ItheimUtil.createVerifyCode(6));
}
}
3 static应用知识:代码块
- 代码块是类的5大成分之一(成员变量、构造器,方法,代码块,内部类)
- 定义在类中方法外
- 在Java类下,使用 { } 括起来的代码被称为代码块
- 静态代码块:
格式:static{}
特点:需要通过static关键字修饰,随着类的加载而加载,并且自动触发、只执行一次
使用场景:在类加载的时候做一些静态数据初始化的操作,以便后续使用
4 static应用知识:单例设计模式
4.1 饿汉单例
- 饿汉单例是在获取对象前,对象已经提前准备好了一个
- 这个对象只能是一个,所以定义静态成员变量
- 必须把构造器私有化
package com.itheima.d4_static_singleinstance;
public class SingleInstance {
public static SingleInstance instance = new SingleInstance();
private SingleInstance(){
}
}
package com.itheima.d4_static_singleinstance;
public class Test1 {
public static void main(String[] args) {
// 目标:理解饿汉单例的设计步骤。
SingleInstance s1 = SingleInstance.instance;
SingleInstance s2 = SingleInstance.instance;
System.out.println(s1 == s2);// true
}
}
4.2 懒汉单例
- 定义一个静态的成员变量负责存储一个对象
- 只加载一次,只有一份,最好私有化
package com.itheima.d4_static_singleinstance;
/**
懒汉单例
*/
public class SingleInstance2 {
/**
2、定义一个静态的成员变量负责存储一个对象。
只加载一次,只有一份。
注意:最好私有化,这样可以避免给别人挖坑!
*/
private static SingleInstance2 instance;
/**
3、提供一个方法,对外返回单例对象。
*/
public static SingleInstance2 getInstance() {
if(instance == null){
// 第一次来拿对象 :此时需要创建对象。
instance = new SingleInstance2();
}
return instance;
}
/**
1、私有化构造器
*/
private SingleInstance2(){
}
}
5 标题面向对象三大特征之二:继承
5.1 继承概述
- 关键字:extends
- 作用:当子类继承父类后,就可以直接使用父类公共的属性和方法
- 优势:可以提高代码的复用性
- 继承设计规范:
子类们相同特征(共性属性,共性方法)放在父类中定义
子类独有的的属性和行为应该定义在子类自己里面
- 继承的特点
子类可以继承父类的属性和行为,但是子类不能继承父类的构造器
Java是单继承模式:一个类只能继承一个直接父类
Java不支持多继承、但是支持多层继承
Java中所有的类都是Object类的子类
- 子类可以继承父类的私有成员,只是不能直接访问(get,set方法访问)
- 子类可以继承父类的私有方法(但是无法访问)
- 子类可以继承父类的静态成员(子类名.静态成员变量)
5.2 继承后特点
5.2.1 成员变量、成员方法的访问特点
package com.itheima.d8_extends_field_method;
public class Test {
public static void main(String[] args) {
// 目标:理解继承后成员的访问特点:就近原则。
Dog d = new Dog();
d.run(); // 子类的
d.lookDoor(); // 子类的
d.showName();
}
}
class Animal{
public String name = "动物名";
public void run(){
System.out.println("动物可以跑~~");
}
}
class Dog extends Animal{
public String name = "狗名";
public void lookDoor(){
System.out.println("狗可以看门~~");
}
public void showName(){
String name = "局部名";
System.out.println(name);
System.out.println(this.name); // 当前子类对象的name
System.out.println(super.name); // 找父类的name
super.run(); // 找父类的方法
run(); // 子类的run
}
public void run(){
System.out.println("狗跑的贼快~~~");
}
}
5.2.2 方法重写
- 重写方法都加@Override注解,代码安全,优雅
- 重写方法的名称、形参列表必须与被重写方法的名称和参数列表一致
- 私有方法不能被重写
- 静态方法不能重写
- 子类重写父类方法时,访问权限必须大于或者等于父类
- (暂时了解 :private < 缺省 < protected < public)
5.2.3 构造器
- 子类中所有的构造器默认都会先访问父类中无参的构造器,再执行自己
- 子类构造器访问父类有参构造器:通过调用父类有参数构造器来初始化继承自父类的数据
- super调用父类构造器
package com.itheima.d11_extends_constructor;
import lombok.Data;
@Data
public class People {
private String name;
private int age;
public People(){
}
public People(String name, int age) {
this.name = name;
this.age = age;
}
}
package com.itheima.d11_extends_constructor;
public class Teacher extends People{
public Teacher(){
}
public Teacher(String name, int age){
// 调用父类的有参数构造器:初始化继承自父类的数据
super(name, age);
}
}
- 其他形式的有参构造器
package com.itheima.d12_this;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private String name;
private String schoolName;
/**
如果学生不填写学校,默认这个对象的学校是黑马
*/
public Student(String name) {
// 借用本类兄弟构造器
this(name, "黑马程序员");
}
}
6 包
- 建包的语法格式:package 公司域名倒写.技术名称
- 报名建议全部英文小写,且具备意义
- 相同包下的类可以直接访问,不同包下的类必须导包(自动导包)
7 权限修饰符
- 权限修饰符:是用来控制一个成员能够被访问的范围
- 可以修饰成员变量,方法,构造器,内部类
- 权限修饰符:有四种作用范围由小到大(private -> 缺省 -> protected - > public )
- 一般要求
成员变量一般私有
方法一般公开
8 final
8.1 final的作用
- 修饰类:表明该类是最终类,不能被继承
- 修饰方法:表明该方法是最终方法,不能被重写
- 修饰变量:表示该变量第一次赋值后,不能再次被赋值(有且仅能被赋值一次)
8.2 final修饰变量的注意
- final修饰的变量是基本类型:那么变量存储的数据值不能发生改变
- final修饰的变量是引用类型:那么变量存储的地址值不能发生改变
- 但是地址指向的对象内容是可以发生变化的
// 注意:final修饰引用类型的变量,其地址值不能改变,但是指向的对象的内容可以改变的。
final Teacher t2 = new Teacher("学习,授课,吹吹水~~");
// t2 = null; // 第二次赋值了。
System.out.println(t2.getHobby());
t2.setHobby("运动");
System.out.println(t2.getHobby());
9 常量
- 常量是使用了public static final修饰的成员变量,必须有初始化值
- 在执行的过程中其值不能被改变
- 常量名的命名规范:英文单词全部大写,多个单词下划线连接起来
- 常量做信息标志和分类
10 枚举
- 枚举的作用:“是为了做信息的标志和信息的分类”
- 枚举类的第一行默认都是罗列枚举对象的名称的
- 枚举都是最终类,不可以被继承
10.1 常量用法
package com.itheima.d5_enum;
public enum Season {
// 第一行罗列枚举的实例:对象的名称。
SPRING,SUMMER,AUTUMN, WINTER;
}
package com.itheima.d5_enum;
public class Test {
public static void main(String[] args) {
// 目标:认识枚举。
Season s1 = Season.SPRING;
// SPRING
System.out.println(s1);
}
}
10.2 向枚举中添加新方法
package com.itheima.d5_enum;
import lombok.Getter;
// 枚举一般只有Getter
@Getter
public enum Color {
RED("红色", 1),
GREEN("绿色", 2),
BLANK("白色", 3),
YELLO("黄色", 4);
// 成员变量
private String name;
private int index;
// 构造方法
private Color(String name, int index) {
this.name = name;
this.index = index;
}
// 普通方法
public static String getName(int index) {
for (Color c : Color.values()) {
if (c.getIndex() == index) {
return c.name;
}
}
return null;
}
}
11 抽象类
- 在Java中abstract是抽象的意思,可以修饰类、成员方法
- 抽象的使用场景
当父类知道子类一定要完成某些行为,但是每个子类该行为的实现又不同
该父类就把该行为定义成抽象方法的形式,具体实现交给子类去完成
- 一个类如果继承了抽象类,那么这个类必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类
- 特征和注意事项:
1、类有的成员(成员变量、方法、构造器)抽象类都具备
2、一个类继承了抽象类必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类
3、不能用abstract修饰变量、代码块、构造器
4、最重要的特征:得到了抽象方法,失去了创建对象的能力(有得有失)
12 面向对象三大特征之三:多态
- 多态的常见形式:
- 多态中成员访问特点
方法调用:编译看左边,运行看右边
变量调用:编译看左边,运行也看左边。(注意)
13 接口
13.1 接口的定义与特点
- JDK8之前接口中只能是抽象方法和常量
- 接口中的成员都是public修饰的
- 接口的格式
// 1、常量:
String SHCOOL_NAME = "黑马程序员";
//public static final String SHCOOL_NAME = "黑马程序员";
// 2、抽象方法
void run();
// public abstract void run();
13.2 接口的基本使用:被实现
- 一个类可以实现一个接口,也可以实现多个接口
- 一个类实现接口,必须重写完全部接口的全部抽象方法,否则这个类需要定义成抽象类
类和类的关系:单继承
类和接口的关系:多实现
接口和接口的关系:多继承,一个接口可以同时继承多个接口
13.3 JDK8开始接口新增的方法
- 默认方法:default修饰,实现类对象调用
- 静态方法:static修饰,必须用当前接口名调用
- 私有方法:private修饰,jdk9开始才有的,只能在接口内部被调用
- 他们都会默认被public修饰
注意:JDK8新增的3种方法我们自己在开发中很少使用,通常是Java源码涉及到的,我们需要理解、识别语法、明白调用关系即可
14 内部类
14.1 内部类基本介绍
- 内部类就是定义在一个类里面的类
- 里面的类可以理解成(寄生),外部类可以理解成(宿主)
- 使用场景:当一个事物的内部,还有一个部分需要一个完整的结构进行描述时
- 基本作用:
内部类通常可以方便访问外部类的成员,包括私有的成员
内部类提供了更好的封装性,内部类本身就可以用private ,protectecd等修饰,封装性可以做更多控制
14.2 匿名内部类(重点)
- 本质上是一个没有名字的局部内部类
- 作用:方便创建子类对象,最终目的是为了简化代码编写
14.2.1 匿名内部类常见使用形式
package com.itheima.d8_innerclass_anonymous;
/**
目标:学习匿名内部类的形式和特点。
*/
public class Test {
public static void main(String[] args) {
Animal a = new Animal(){
@Override
public void run() {
System.out.println("老虎跑的块~~~");
}
};
a.run();
}
}
abstract class Animal{
public abstract void run();
}
匿名内部类通常是在开发中调用别人的方法时,别人需要我们写的时候才会定义出来使用
15 常用API
- API:Java已经写好一些方法,直接拿过来用(应用程序编程接口)
15.1 Object
15.1.1 toString方法
- 默认是返回当前对象在堆内存中的地址信息:类的全限名@内存地址
- 父类toString()方法存在的意义就是为了被子类重写,以便返回对象的内容信息
- 写在实体类中
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", sex=" + sex +
", age=" + age +
'}';
}
15.1.2 equals方法
- 默认是比较当前对象与另一个对象的地址是否相同,相同返回true,不同返回false
- 直接比较两个对象的地址是否相同完全可以用“==”替代equals
- 为了被子类重写,以便子类自己来定制比较规则(比如比较对象内容)
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Student)) return false;
Student student = (Student) o;
return getSex() == student.getSex()
&& getAge() == student.getAge()
&& Objects.equals(getName(), student.getName());
}
@Override
public int hashCode() {
return Objects.hash(getName(), getSex(), getAge());
}
15.2 Objects
- Objects是一个工具类,提供了一些方法去完成一些功能
- 使用Objects的equals方法在进行对象的比较会更安全
package com.itheima.d10_api_objects;
import java.util.Objects;
public class Test {
public static void main(String[] args) {
String s1 = null;
String s2 = new String("itheima");
// System.out.println(s1.equals(s2)); // 留下了隐患,可能出现空指针异常。
System.out.println(Objects.equals(s1, s2)); // false 更安全,结果也是对的!
/**
Objects:
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
*/
System.out.println(Objects.isNull(s1)); // true
System.out.println(s1 == null); // true
System.out.println(Objects.isNull(s2)); // false
System.out.println(s2 == null); // false
}
}
16 StringBuilder
- StringBuilder的核心作用:操作字符串的性能比String要更高(如拼接、修改等)
package com.itheima.d11_api_stringbuilder;
public class StringBuilderDemo1 {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
sb.append("a");
sb.append(1);
sb.append(false);
sb.append(3.3);
sb.append("abc");
System.out.println(sb);// abc1false3.3abc
StringBuilder sb1 = new StringBuilder();
// 支持链式编程
sb1.append("a").append("b").append("c").append("我爱你中国");
System.out.println(sb1);// abc我爱你中国
// 反转
// reverse把里面的元素逆序
sb1.reverse().append("110");
System.out.println(sb1);// 国中你爱我cba110
System.out.println(sb1.length());// 11 字符长度
// 注意:StringBuilder只是拼接字符串的手段:效率好。
// 最终的目的还是要恢复成String类型。
StringBuilder sb2 = new StringBuilder();
sb2.append("123").append("456");
// 恢复成String类型
String rs = sb2.toString();
System.out.println("rs = " + rs);// rs = 123456
}
}
其他API
- math
package com.itheima.d12_math;
public class MathDemo {
public static void main(String[] args) {
// 1.取绝对值:返回正数
System.out.println(Math.abs(10)); // 10
System.out.println(Math.abs(-10.3)); // 10.3
// 2.向上取整: 5
System.out.println(Math.ceil(4.00000001)); // 5.0
System.out.println(Math.ceil(4.0)); // 4.0
// 3.向下取整:4
System.out.println(Math.floor(4.99999999)); // 4.0
System.out.println(Math.floor(4.0)); // 4.0
// 4.求指数次方
System.out.println(Math.pow(2 , 3)); // 2^3 = 8.0
// 5.四舍五入 10
System.out.println(Math.round(4.49999)); // 4
System.out.println(Math.round(4.500001)); // 5
System.out.println(Math.random()); // 0.0 - 1.0 (包前不包后)
// 拓展: 3 - 9 之间的随机数 (0 - 6) + 3
// [0 - 6] + 3
int data = (int)(Math.random() * 6) + 3;
System.out.println(data);
}
}
- system
package com.itheima.d13_system;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.Arrays;
public class SystemDemo {
public static void main(String[] args) {
// System.exit(0); // JVM终止!
// 2、计算机认为时间有起源:返回1970-1-1 00:00:00
// 走到此刻的总的毫秒值:时间毫秒值。
long time = System.currentTimeMillis();
System.out.println(time);// 1684828821688
// 3、做数组拷贝(了解)
/**
arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length)
参数一:被拷贝的数组
参数二:从哪个索引位置开始拷贝
参数三:复制的目标数组
参数四:粘贴位置
参数五:拷贝元素的个数
*/
int[] arr1 = {10, 20, 30, 40, 50, 60, 70};
int[] arr2 = new int[6]; // [0, 0, 0, 0, 0, 0] ==> [0, 0, 40, 50, 60, 0]
System.arraycopy(arr1, 3, arr2, 2, 3);
System.out.println(Arrays.toString(arr2));
System.out.println(k1);// 换行输出
System.out.print(k1);// 不换行输出
}
}
- BigDecimal大数据类
- 浮点型运算的时候直接+ * / 可能会出现数据失真(精度问题)
- BigDecimal可以解决浮点型运算数据失真的问题
package com.itheima.d14_bigdecimal;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
public class BigDecimalDemo {
public static void main(String[] args) {
// 浮点型运算的时候直接+ * / 可能会出现数据失真(精度问题)。
System.out.println(0.09 + 0.01);// 0.09999999999999999
System.out.println(1.0 - 0.32);// 0.6799999999999999
System.out.println(1.015 * 100);// 101.49999999999999
System.out.println(1.301 / 100);// 0.013009999999999999
System.out.println("-------------------------");
double a = 0.1;
double b = 0.2;
double c = a + b;
System.out.println(c);// 0.30000000000000004
System.out.println("--------------------------");
// 包装浮点型数据成为大数据对象 BigDeciaml
BigDecimal a1 = BigDecimal.valueOf(a);
BigDecimal b1 = BigDecimal.valueOf(b);
BigDecimal c1 = a1.add(b1);
// a1.add(b1) = 0.3
System.out.println("a1.add(b1) = " + a1.add(b1));
// a1.subtract(b1) = -0.1
System.out.println("a1.subtract(b1) = " + a1.subtract(b1));
// a1.multiply(b1) = 0.02
System.out.println("a1.multiply(b1) = " + a1.multiply(b1));
// a1.divide(b1) = 0.5
System.out.println("a1.divide(b1) = " + a1.divide(b1));
// 目的:double
double rs = c1.doubleValue();
System.out.println(rs);// 0.3
// 注意事项:BigDecimal是一定要精度运算的
BigDecimal a11 = BigDecimal.valueOf(10.0);
BigDecimal b11 = BigDecimal.valueOf(3.0);
/**
参数一:除数 参数二:保留小数位数 参数三:舍入模式
*/
BigDecimal c11 = a11.divide(b11, 2, RoundingMode.HALF_UP); // 3.3333333333
System.out.println(c11);// 3.33
}
}