1

Java学习笔记(十)

 1 year ago
source link: https://blog.51cto.com/u_16213911/7089065
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

第7章 面向对象(下)

7.1 静态的

1、static:静态的

2、什么是静态的?

和对象无关的,不会因为对象的不同而不同,即所有对象都一样的。

换句话说,和对象无关。

动态的,根据对象的不同而不同,和对象有关,由对象动态决定。

3、static这个关键字用在哪里?

(1)成员变量前面:静态变量

(2)成员方法前面:静态方法

(3)代码块前面:静态代码块

(4)内部类class前面(后面和内部类一起讲):静态内部类

(5)在import语句里面:静态导入

7.1.1 静态变量

4、静态变量

(1)静态变量的定义:是指有static修饰的成员变量

(2)静态变量的特点:

A:静态变量的值是所有对象共享的。

B:虽然可以,但不建议通过“对象.静态变量”的形式进行访问,

建议通过“类名.静态变量”的形式进行访问。

C:如果静态变量的可见性范围被限制了,提供get/set时,它的get/set也是静态的。

在set方法中,静态变量和局部变量(形参)重名了,使用“类名.静态变量”进行区分。

D:静态变量的值是存储在“方法区”中。

//Company公司
public class Employee {
    public static String company;//静态变量
    public String name;//实例变量
    private static String corporation;

    public static String getCorporation() {
        return corporation;
    }

    public static void setCorporation(String corporation) {
        Employee.corporation = corporation;
        //不能使用this.
    }
}
public class TestStaticVariable {
    public static void main(String[] args) {
        Employee e1 = new Employee();
        Employee e2 = new Employee();
        e1.company = "执影";

        System.out.println(e1.company);
        System.out.println(e2.company);
//        System.out.println(Employee.company);

        e2.company = "zhiying";

        System.out.println(e1.company);
        System.out.println(e2.company);

        System.out.println("-----------------");
        //静态变量推荐使用“类名.静态变量”的形式进行访问。
        Employee.company = "执影人";
        System.out.println(Employee.company);
    }
}

7.1.2 静态方法

5、静态方法

(1)静态方法的定义:是指有static修饰的方法。

(2)静态方法的特点:

A:静态方法中不允许直接使用本类的非静态成员

B:静态方法中也不允许直接使用this,super等关键字

C:静态方法的调用虽然可以用“对象.静态方法”的形式进行访问,

但是我们更推荐“类名.静态方法”的形式进行访问。

D:父类的静态方法可以被子类访问,但是不能被子类重写

public class Student {
    private static String school;
    private String name;
    public static String getSchool(){
        return school;
    }
    
    public static void method(){
        System.out.println(this.name);//错误,静态方法中不允许出现this
        System.out.println(name);//错误,静态方法中不允许直接访问非静态的实例变量name
        System.out.println(super.hashCode());//错误,静态方法也不允许出现super
    }
}
public class TestStudent {
    public static void main(String[] args) {
        System.out.println(Math.random());

        Student stu = new Student();
        System.out.println(stu.getSchool());
        //编译器也会处理成Student.getSchool()
        System.out.println(Student.getSchool());
    }
}
Java学习笔记(十)_静态变量
public class Father {
    public static void method(){
        System.out.println("Father.method");
    }
}
/*
@Override:是一个注解。
作用:和编译器说,它标记的方法是子类重写父类的方法。请“严格”按照重写的要求进行格式检查。
如果违反重写的要求,就编译报错。

如果一个方法遵守重写的要求,加或不加@Override都可以。
如果一个方法没有遵守重写的要求,不加@Override有可能编译器不提示你错误,导致和你的意图不一致。

 建议:凡是重写的方法,不管你写的对不对,都加@Override。

 */
public class Son extends Father {

    //自己以为我重写成功了,但是其实是不对的
   /* public static void method(){
        System.out.println("Son.method");
    }*/
}
public class TestSon {
    public static void main(String[] args) {
        Father f = new Son();
        f.method();//完全等价于Father.method

        Father.method();
        Son.method();
    }
}
Java学习笔记(十)_System_02

7.1.3 静态代码块

6、静态代码块

(1)静态代码块的作用:为类的静态变量初始化

(2)静态代码块的执行特点

A:一个类的静态代码块只会执行一次

B:它是在类加载类初始化时执行,先于类对象的创建

(3)语法结构

【修饰符】 class 类名{

   static{

       静态代码块

public class Demo {
    static {
        System.out.println("静态代码块");
    }

    public Demo(){
        System.out.println("Demo无参构造");
    }
}
public class TestDemo {
    public static void main(String[] args) {
        Demo d1 = new Demo();
        Demo d2 = new Demo();
    }
}

7.1.4 类初始化

7、类初始化

(1)类初始化:为类的静态变量赋值的过程

(2)类初始化相关代码

A:静态变量声明时,直接=值

B:静态代码块

(3)如果我们编写了类初始化相关代码,那么编译器会给我们

把这些代码按照编写顺序组装到一个<clinit>()的类初始化方法中。

cl:class

init:initialize

(4)一定是先完成类初始化,再进行实例初始化(创建对象),

并且一定是先完成父类初始化,再完成子类初始化。

public class SubDemo extends Demo {
    static {
        System.out.println("子类SubDemo的静态代码块");
    }
}
public class TestDemo {
    public static void main(String[] args) {
        /*Demo d1 = new Demo();
        Demo d2 = new Demo();
*/
        SubDemo s1 = new SubDemo();
        SubDemo s2 = new SubDemo();
    }
}

7.1.5 静态导入

8、静态导入

(1)静态导入的定义:在import语句里面出现static,就是静态导入

(2)作用:在当前的.java文件中,使用另一个类的静态成员时,可以直接在代码中使用静态成员名,而不用“类名.静态成员名。

import static java.lang.Math.*;

public class TestStaticImport {
    public static void main(String[] args) {
        /*System.out.println(Math.PI);
        System.out.println(Math.random());
        System.out.println(Math.sqrt(9));*/

        System.out.println(PI);
        System.out.println(random());
        System.out.println(sqrt(9));
    }
}

7.2 抽象类和抽象方法

1、什么是抽象类?

在class前面加abstract修饰的都是抽象类。

【其他修饰符】 abstract class 类名{

2、为什么要用抽象类?

(1)不希望你创建这个类的对象,希望你创建它子类的对象(少一点)

(2)当我们在声明某个父类时,其中某些方法不得不声明,但是又无法给出具体的实现,

即无法编写方法体代码,这个方法体代码通常由子类来实现,各个子类的实现不同,

这个时候需要把这样的方法声明为抽象方法,

Java中包含抽象方法的类必须是抽象类(更多的情况)。

3、抽象类的特点

(1)抽象类不能直接new对象,只能new它子类的对象

(2)抽象类中可以包含抽象方法,也可以不包含抽象方法。

但是反过来,包含抽象方法的类,必须是抽象类。

(3)抽象类是用来被继承的,子类继承抽象类时,必须重写抽象类的所有抽象方法,

否则子类也得是抽象类。

4、抽象类和非抽象类有什么区别?

抽象类不能直接new对象,非抽象类可以直接new对象,

抽象类中可以包含抽象方法,非抽象类中不可以包含抽象方法。

5、抽象类中有构造器吗?

它的构造器存在的意义是被子类调用的。

public abstract class Person {
    private String name;
    private int age;

    public Person(){
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class Student extends Person {
    //....
}
public class Teacher extends Person {
    //.....
}
public class TestPerson {
    public static void main(String[] args) {
        //做学生信息管理系统
        //在整个系统中,要么存在的是学生对象,要么存在的是教师对象
        //希望整个程序中不能直接new Person的对象。
        Person[] arr = new Person[3];
//        arr[0] = new Person();//报错,因为抽象类不允许直接new对象
        arr[1] = new Student();
        arr[2] = new Teacher();
    }
}
//包含抽象方法的类必须是抽象类
public abstract class Graphic {
    /*public double area(){
        return 0.0;
    }*/

    //抽象方法,没有方法体,有abstract修饰
    public abstract double area();
}
public  class Circle extends Graphic {
    private double radius;

    public Circle() {
    }

    public Circle(double radius) {
        this.radius = radius;
    }

    public double getRadius() {
        return radius;
    }

    public void setRadius(double radius) {
        this.radius = radius;
    }

    @Override
    public String toString() {
        return "Circle{" +
                "radius=" + radius +
                '}';
    }

	//不重写报错
    @Override
    public double area() {
        return Math.PI * radius * radius;
    }
}
public class Rectangle extends Graphic{
    private double length;
    private double width;
    public Rectangle(){
    }

    public Rectangle(double length, double width) {
        this.length = length;
        this.width = width;
    }

    public double getLength() {
        return length;
    }

    public void setLength(double length) {
        this.length = length;
    }

    public double getWidth() {
        return width;
    }

    public void setWidth(double width) {
        this.width = width;
    }

    @Override
    public String toString() {
        return "Rectangle{" +
                "length=" + length +
                ", width=" + width +
                '}';
    }
    //不重写报错
	@Override
    public double area(){
        return length * width;
    }
}
public class TestGraphic {
    public static void main(String[] args) {
        Graphic[] arr = new Graphic[2];
        arr[0] = new Circle(2.5);
        arr[1] = new Rectangle(5,3);
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i].area());
            /*
            arr[i]的编译时是Graphic类型,先要去Graphic类中匹配area()方法,
            此时Graphic类中没有area()方法,编译报错。
            为了编译通过,必须在Graphic类中,增加area()方法
             */
        }
    }
}

7.3 注解

7.3.1 基本注解

1、什么是注解?

在代码中,使用@开头的都是注解。

2、注解有什么用呢?

注解也是一种注释,这种注释是代码级别的注释,

它是让另一段代码来读取这个注解,并做出相应的xx操作。

例如:@Override注解。

当编译器(编译器也是一段程序)读取到某个方法上面加了@Override,

就会执行一段代码,这段代码是一段校验该方法是否满足重写要求的判断代码,

如果满足,那么编译通过,

如果不满足,编译器会报错,提醒你违反了重写的要求。

3、3个最最基本的系统注解(JDK1.8之前就有的)

(1)@Override注解

它只能加在重写的方法上面。

(2)@Deprecated注解

它可以用在方法、类、构造器等等上面。

作用:让编译器提醒程序员,如果你使用了这个方法、类、构造器等,编译器会弹出警告,

提醒你这个方法、类、构造器等已经过时了,可能存在设计的缺陷,或者其他问题,

不再推荐你继续使用。

为什么已过时的代码不修复或删掉呢?

修复:修复的成本太高,重新设计一个

   开发原则:面向修改关闭,面向扩展开发

删掉:因为这些方法、类、构造器等在旧的项目中还在使用。

       注销银行卡。

       不会删除你之前的所有的银行记录啥,

       而是标记为这个卡不能用。

       这个操作称为逻辑删除,不是物理删除。

(3)@SuppressWarnings

import java.util.Date;

public class TestDeprecated {
    @SuppressWarnings("all")
    public static void main(String[] args) {
        Date today = new Date(2022-1900,8-1,20);
        //使用这个构造器时Date(int year, int month, int date)
        //编译器会弹出警告,说,这个方法已过时
        System.out.println(today);
        //Wed Sep 20 00:00:00 CST 3922
    }
}

7.3.2 文档注释

1、Java中有3种注释

(1)单行注释 //

(2)多行注释 /*    */

(3)文档注释/**    */

文档注释有严格的格式要求。

/**
 * 文档注释演示类
 * @author Irene
 * @version JDK1.8
 * @see java.lang.Object
 */
public class TestDoc {
    /**
     * 这是一个主方法,Java程序的入口
     * @param args String[] 它是命令行参数,可以通过java命令传入参数值。格式:java 主类名 参数值1 参数值2 ...
     */
    public static void main(String[] args) {
        //...
    }

    /**
     * 这是一个求两个整数最大值的方法
     * @param a int 第一个整数
     * @param b int 第二个整数
     * @return int 当a大于b时,返回a的值,否则返回b的值
     */
    public static int max(int a, int b){
        return a > b ? a : b;
    }

    /**
     * 这是求两个整数的商。
     * @param a int 被除数
     * @param b int 除数
     * @return int 商,a/b的结果,只有整数部分
     * @exception ArithmeticException 当b为0时可能发生算术异常
     */
    public static int divide(int a, int b){
        return a/b;
    }
}
Java学习笔记(十)_静态变量_03

7.3.3 JUnit

说明:标准的单元测试编写方式,在实际项目中再讲。

今天,讲单元测试的JUnit的小工具只是把它当成一个代替main方法运行的小工具而已。

使用步骤:

(1)在当前模块中要引入JUnit的库

因为JUnit不是JRE核心类库的一部分,它是第三方的一个工具。

引入的方式很简单:

第一步:先写一个方法

第二步:在方法上面加一个@Test

第三步:@Test会报错,鼠标放到@Test上面,IDEA会提示我们需要引入JUnit的库(一堆class文件)

第四步:单击Add 'JUnit4' to classpath

第五步:下载,默认是下载到C盘用户目录下的.m2的仓库中

   (至于后期项目中如何依赖和下载,咱们学习Maven时再学习)

(2)凡是要独立运行的测试方法上面都可以加@Test

使用要求:

(1)自己写的类名,同一个包的所有类,包括当前类,不能命名为Test类。

(2)要使用@Test标记测试方法,

这个测试方法必须是public,void,(),非静态的

(3)@Test标记的测试方法所在类必须只有唯一的无参构造,并且也是public的。

import org.junit.Test;

public class TestJUnit {
    @Test
    public void test01(){
        System.out.println("hello");
    }

    @Test
    public void test02(){
        System.out.println("world");
    }
}
Java学习笔记(十)_静态变量_04

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK