面向对象
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 classinterface继承只能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程序 真是神奇