1.static关键词(用来修饰成员方法和成员变量)
1.1静态变量
-
被该类的所有对象共享
-
比如在Student类中static String teachername; 那么可以在ClassTest中通过类名调用,即Student.teachername = "大伟老师";
1.2静态方法
1.区分三种类别
javabean类:用于描述事物的类,如Student,Cat,要写空参构造,全参构造,getter and setter。
测试类: 带有main方法的类,如StudentTest
工具类:帮助我们做一些事情的类,要私有化构造方法(创建工具类的对象没有意义)
工具类的一个代码:
package xzx.staticdemo;
public class ArrayUtil {
private ArrayUtil(){}
public static String printArr(int[] arr){
StringBuilder sb = new StringBuilder();
sb.append('[');
for(int i=0;i<arr.length;i++){
if( i != arr.length-1){
sb.append(arr[i]+",");
}else{
sb.append(arr[i]);
}
}
sb.append(']');
String result = sb.toString();
return result;
}
public static double getAverage(double[] arr){
double sum = 0;
for(int i=0;i<arr.length;i++){
sum += arr[i];
}
return sum/arr.length;
}
}
1.3 static注意事项
- 静态方法只能访问静态变量和静态方法
- 非静态方法可以访问所有
- 静态方法中没有this关键字的
2. 继承
- public class Student extends Person{}
- 可以提高代码复用性,子类也可以在父类的基础上增加自己独特的功能
- java只支持单继承,不支持多继承,但支持多层继承(A可以继承B,B可以继承C)
- 每一个都直接或间接的继承于object类(虚拟机自动完成)
2.1 代码实现
见Idea extendsdemo
2.2 构造方法的调用
- 父类中的构造方法不会被子类继承。
- 子类中所有的构造方法默认先访问父类中的无参构造。(因为有可能用到父类中的数据,父类没有完成初始化的话,就不能使用父类的数据)
- 子类构造方法的第一行语句默认都是super(),不写也存在,且必须在第一行。
- 如果想调用父类的有参构造,必须手动写super进行调用。
public class Student extends Person{
public Student(){//空参构造
super(); //必须写在第一行
}
public Student(){ //带参构造
super(name,age); //访问父类的带参构造
}
}
2.3 this、super关键词
- 什么时候用this访问本类构造方法呢? 当需要设定默认值的时候
首先Student类中有三个成员变量,分别是age name school
如果创建对象的时候不给学校的值,默认为鲨鲨大学
则空参构造要这么写:
public Student(){
this(0,null,"鲨鲨大学");//调用本类其他构造方法,虚拟机也不会再添加super了
}
3. 多态(对象的多种形态)
3.1 应用场景
- 在学生管理系统中,一定会有多个角色,给每种角色写一个注册方法是愚蠢的,利用多态可以很好的解决这个问题(Student类和Teacher类继承于Person类,可以
Person p = new Student();)
3.2 调用规则
- 调用成员变量:编译看左边,运行也看左边
- 调用成员方法:编译看左边,运行看右边
- 理解:子类继承父类时,会将父类的成员变量也继承下来,但如果重写方法,会将父类的成员方法覆盖掉。
3.3 优势及弊端
优势:
弊端: 不能使用子类的特有功能,还要强转成真正的子类类型,并使用instanceof来防止报错。
package xzx.duotaidemo;
public class Test {
public static void main(String[] args) {
Animal a = new Dog();
a.eat();
// 多态的弊端:使用a.lookHome()会报错, 根据编译看左边,会先看父类有没有该方法,没有的话会报错
//解决方案
//把a变回子类类型就可以了
if(a instanceof Dog){
Dog d = (Dog) a;
d.lookHome();
}else if(a instanceof Cat){
Cat c = (Cat) a;
c.Attack();
}else{
System.out.println("没有这个类型");
}
//JDK14新特性,如果说a是Dog类型,就强制转换成Dog类型,转换之后的变量名为d
if(a instanceof Dog d){
d.lookHome();
}else if(a instanceof Cat c){
c.Attack();
}else{
System.out.println("没有这个类型");
}
}
}
class Animal{
public void eat(){
System.out.println("动物在吃东西");
}
}
class Dog extends Animal{
public void eat(){
System.out.println("狗在吃骨头");
}
public void lookHome(){
System.out.println("狗在看家");
}
}
class Cat extends Animal{
public void eat(){
System.out.println("哈基米在吃鱼");
}
public void Attack(){
System.out.println("哈基米在哈气");
}
}
4.封装
4.1 定义
- 封装:隐藏对象的属性和实现细节,仅对外公开接口来实现交互。
- 属性被private封装后,在类的外部想要使用,就要通过getter和setter方法
以下是四种常见的权限:
- public: 被public修饰的内容在当前项目中都可见,描述公共的,公开的内容
- default: 对于自己家族中(同一个包中)不是什么秘密,对于其他人来说就是隐私了。
- private:只在当前类的内部可见,对外部完全隐藏,同一个包的同一类才能访问。
- protected:继承访问权限。
4.2 包
- 包就是文件夹。用于管理各种不同功能的java类。
- 命名规则:公司域名反写+包的作用,全部小写。
- 使用同一个包的类时,不需要导包。
- 使用java.lang包时不需要导包,其他情况都需要。
- 如果同时使用两个包中的同名类,需要用全类名。
如 com.cqupt.xzx.student.Student stu = new com.cqupt.xzx.student.Student()
4.3 final关键字
- 如果一个方法是规则,那就可以用final来修饰。
- 字符串类就是一个final类。
- final 修饰一个基本数据类型,fianl PI = 3.141592653,
- 但是如果final修饰一个引用类型变量,不能改变的是地址值,对象内部可以改变
4.4 权限修饰符
- 实际开发一般只用public和private
- 成员变量私有,方法公开
4.5 代码块
4.5.1 局部代码块
局部代码块:用于提前结束变量的周期,用于节省内存空间(用完立马回收),随着计算机硬件的发展,现在已经不用了。
4.5.2 构造代码块
用于将构造方法中重复的代码抽取出来 写在构造代码块里面。 创建对象时会先执行构造代码块,再执行构造方法。 也渐渐被淘汰了,因为不够灵活(有些构造不想执行这个语句),可以直接写一个方法,然后用的时候调用方法就行。
4.5.3 静态代码块
- 格式:static{}
- 特点:随着类的加载而加载,自动触发,只执行一次。
- 用处:进行数据的初始化
5. 抽象类
- 父类person中work方法被子类继承,如果子类忘记重写了,就会有问题(学生和老师的work内容不一致),所以abstract类出现了。
- 抽象方法所在的类就是抽象类,但是抽象类中可以没有抽象方法。
- 抽象方法必须重写。
- 抽象类不能实例化。
- 抽象类中可以没有抽象方法
- 抽象类可以有构造方法(作用:创建子类对象时,给属性进行赋值的。)
- 抽象类的子类要不重写抽象类中所有抽象方法,要么是抽象类。
强制重写格式,要不然每个子类都自己写一个work方法,调用的时候不就炸了吗(比如有些有return或者名字来一个working)
public abstract class Person{
//抽象方法不用写方法体
public abstract void work();
}