面向对象
class
instance
extends
implements
field
constructor 可以是多个 默认是无参数的构造 无返回值类型 跟类名相同
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person(String name) {
this(name, 18); // 调用另一个构造方法Person(String, int)
}
public Person() {
this("Unnamed"); // 调用另一个构造方法Person(String)
}
}
重载overload
重载定义: 方法名相同,但是各自参数不同是重载
重载的方法: 重载方法返回值类型应该相同
继承 extends 有s
单继承 多实现
private 只能本类
protected 可以子类和
super关键字表示父类(超类)。子类引用父类的字段时,可以用super.fieldName
其实super对于属性来说用处不大 可以用this表示甚至可以直接写父类的属性
特殊情况如下
class Person {
protected String name;
protected int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
class Student extends Person {
protected int score;
public Student(String name, int age, int score) {
这个时候会编译报错 因为继承的话编译器会自动给构造函数加上那个无参数的super() 但是父类里没有无参数的构造方法 所以需要些成suoer(name, age)
this.score = score;
}
}
向上转型 Person p = new Student(); 安全的
向下转型 使用instanceof 判断下在转型
Person p = new Student();
if (p instanceof Student) {
// 只有判断成功才会向下转型:
Student s = (Student) p; // 一定会成功
}
JAVA14的写法
Object obj = "hello";
if (obj instanceof String s) {
// 可以直接使用变量s:
System.out.println(s.toUpperCase());
}
多态
定义: 针对于某个类型的方法的调用,其真正调用的方法是属于父类的还是属于子类的我们只有在运行的时候才能知道。把控制权力交出去了
特性: 运行期才能动态决定调用的子类方法 对某个类型调用某个方法 执行实际方法可能是某个子类的重写方法
用到了重写 @Override 相当于个注释 给编译器看的 没有实际执行用处
// 例子 运用了重写 向上转型 多态的写法
public class Main {
public static void main(String[] args) {
// 给一个有普通收入、工资收入和享受国务院特殊津贴的小伙伴算税:
//定义了一个对象数组 利用了向上转型
Income[] incomes = new Income[] {
new Income(3000), // 普通收入
new Salary(7500),
new StateCouncilSpecialAllowance(15000)
};
System.out.println(totalTax(incomes));
}
public static double totalTax(Income... incomes) {
double total = 0;
for (Income income: incomes) {
total = total + income.getTax();
}
return total;
}
}
// 这是一个收入的父类 里边有一个算税的方法
class Income {
protected double income;
public Income(double income) {
this.income = income;
}
public double getTax() {
return income * 0.1; // 税率10%
}
}
// 工资的收入 算税方法重写了
class Salary extends Income {
public Salary(double income) {
super(income);
}
@Override
public double getTax() {
if (income <= 5000) {
return 0;
}
return (income - 5000) * 0.2;
}
}
// 国务院特别津贴 没有税的算法
class StateCouncilSpecialAllowance extends Income {
public StateCouncilSpecialAllowance(double income) {
super(income);
}
@Override
public double getTax() {
return 0;
}
}
重写object
Object类内置了三个方法
public String toString()
public boolean equals(Object o)
public int hashCode()
重写的时候可以通过super调用父类方法
final 在变量前加上表示常量 final是一种访问权限的修饰符
在类上加上表示不能被继承
在方法上加上 表示不能被重写
在字段上表示初始化后不能被修改
可以在构造方法中初始化final字段:
class Person {
public final String name;
public Person(String name) {
this.name = name;
}
}
抽象类 抽象方法
如果一个方法只是用来被继承之后重写的话 那他本身应该不用写任何逻辑 这个时候就可以用abstract 来表示abstract void run();,
这样的话就不用写方法体了,但是子类必须重写不重写就报错了 而且
此时这个方法是抽象方法了 类就必须加上abstract
抽象方法就是定义规范的 就这一点上跟接口有着共同的作用点
面向对象编程
尽量引用高层类型,避免引用实际子类型的方式,称之为面向抽象编程
本质:
上层代码只定义规范(例如:abstract class Person);不需要子类就可以实现业务逻辑(正常编译);具体的业务逻辑由不同的子类实现,调用者并不关心。
接口 这个有新的收获 JDK >= 1.8之后有default方法
如上抽象类是定义规范的,但是抽象类中还可以有字段 和 一些普通的方法
如果我们只是用来定义规范 没有字段的话 提供了一个新的工具是Interface接口
请注意 Interface是可以有静态字段的 public static final int MALE = 1; 只能是public static final 来修饰的字段
这个接口可以多实现 抽象类是单继承的
关键字: Tnterface implements
接口里能写方法吗?
能. 就是特殊的方法
前边用default修饰
abstract class | interface | |
---|---|---|
继承 | 只能extends一个class | 可以implements多个interface |
字段 | 可以定义实例字段 | 不能定义实例字段(但是可以有静态字段) |
抽象方法 | 可以定义抽象方法 | 可以定义抽象方法 |
非抽象方法 | 可以定义非抽象方法 | 可以定义default方法 |
静态字段和静态方法
什么是静态 静态是初始化时就会在内存中分配一块儿空间 这个空间是共享的
static 是一种访问位置的修饰符
静态字段
接口里可以写静态字段
静态字段可以通过class. 访问
静态方法
无论是静态字段还是静态方法 调用都是通过 类名. 调用 如果写成了实例来调用编辑器也会给转成类名来调用 因为是静态的
静态方法属于class不属于实例 所以无法访问this变量 也无法访问实例字段 只能访问静态字段
静态方法一般用于工具类 写一些通用的辅助方法
package import
package
一般用域名来命名 编译后的.class文件也需要按照包结构存放
import
在写import的时候,可以使用*,表示把这个包下面的所有class都导入进来(但不包括子包的class):
例如
import java.lang.* 自动导入的是java.lang包,但类似java.lang.reflect这些包仍需要手动导入
如果有两个class名称相同,例如,mr.jun.Arrays和java.util.Arrays,那么只能import其中一个,另一个必须写完整类名
一个.java文件只能包含一个public类,但可以包含多个非public类。如果有public类,文件名必须和public类的名字相同
final
用final修饰class可以阻止被继承
用final修饰method可以阻止被子类覆写
用final修饰field可以阻止被重新赋值
用final修饰局部变量可以阻止被重新赋值
package abc;
public class Hello {
protected void hi(final int t) {
t = 1; // error!
}
}
classpath 和 jar
classpath 是什么 是JVM用到的环境变量
设置classpath有两种 :1.在你的电脑里设置环境变量(不推荐) 2,java -classpath 或者java -cp 不加这个参数的话 默认是当前目录
注意: 不用把rt.jar 放到classpath中 这是jvm自己的包肯定能找到的
jar 是什么 本质是个zip包 再就是一个提供classpath的位置 找一个zip包里边的.class这种方式更优秀
如果jar包里引入了其他的jar包怎么扫描呢 这时候jar包里需要些一个文件META-INF/MAINIFEST.MF
这里边会指定主函数 和 class-path来扫描到jar包里的.class 但是手动打zip包 来规划这些类很麻烦 maven会自己打jar包的
模块 java9开始 jdk引入了模块 需要实践
什么是模块
如果a.jar运行必须依赖b.jar才能运行 那我们应该给a.jar 加上说明 让程序编译和运行的时候能够自动定位到b.jar 这种自带依赖关系额class容器就是模块
JAVA9 将rt.jar 分拆成了几十个模块 可以在$JAVA_HOME/jmods目录下找到
java base.jmod
可以抱抱成jre!! 免安装跑hava程序 真是神奇