坚定不移学Java-Day06

 整理自 韩顺平零基础30天学Java

【零基础 快速学Java】韩顺平 零基础30天学会Java_哔哩哔哩_bilibili

变量作用域

  1. Java编程中,主要的变量就是属性(成员变量)和局部变量。
  2. 局部变量一般是指在成员方法中定义的变量。
  3. 全局变量:也就是属性,作用域为整个类体;
    局部变量:也就是除了属性之外的其他变量,作用域为定义它的代码块。
  4. 全局变量可以不赋值,直接使用,因为有默认值;
    局部变量必须赋值后,才能使用,因为没有默认值。

注意

  1. 属性和局部变量可以重名,访问时遵循就近原则。
  2. 在同一个作用域中(如同一个成员方法),两个局部变量不能重名。
  3. 属性生命周期较长,伴随着对象的创建而创建,伴随着对象的销毁而销毁。
    局部变量的生命周期较短,伴随着它的代码块的执行而创建,伴随者代码块的结束而销毁,即在依次方法调用过程中。
  4. 作用域不同
    全局变量:可以被本类使用,或其他类使用(通过对象调用);
    局部变量:只能在本类中对应的方法中使用。
  5. 修饰符不同
    全局变量/属性可以加修饰符;
    局部变量不可以加修饰符。

构造方法 / 构造器

[修饰符] 方法名(形参列表){

        方法体;

}

类的一种特殊方法,完成对新对象的初始化

  1. 构造器的修饰符可以默认。
  2. 构造器没有返回值。
  3. 方法名 和 类 名字必须一样。
  4. 参数列表 和 成员方法 一样的规则。
  5. 构造器的调用由系统完成。
public class Constructor {
    public static void main(String[] args){
        //new一个对象时,直接通过构造器指定名字和年龄
        Person p1 = new Person("smith", 80);
        System.out.println("name=" + p1.name + "age=" + p1.age);
    }
}
class Person {
    String name;
    int age;
    //构造器  名称和类名一致
    public Person(String pName, int pAge){
        name = pName;
        age = pAge;
    }
}

细节

  1. 一个类可以定义多个不同的构造器,即构造器重载。
  2. 构造器是完成对象的初始化,并不是创建对象。
  3. 在创建对象时,系统自动地调用该类的构造方法。
  4. 如果程序员没有定义构造方法,系统会自动给类生成一个默认无参构造方法(也叫默认构造方法)。比如Person(){},使用javap指令 反编译看看。
  5. 一旦定义了自己的构造器,默认的构造器就覆盖了,就不能再使用默认的无参构造器。
    Dog dog = new Dog(); //使用的是默认的无参构造器
    Dog(){} //显示定义完无参构造器,上述代码又可以使用了。

对象创建的流程分析(面试题)p245

  1. 加载Person类信息(Person.class),只会加载一次。
  2. 在堆中分配空间(地址)。
  3. 完成对象初始化。
    1. 默认初始化。
    2. 显式初始化。
    3. 构造器初始化。
  4. 把对象在堆中的地址返回给p。(p是对象名,也可以理解为对象的引用)

this关键字

构造器的输入参数名不是非常号,如果能将pName改为name就好了,BUT变量的作用域原则,会导致name的值就是null,所以引入this关键字。

Java虚拟机会给每个对象分配this,代表当前对象。

p.s:hashCode()不是地址,会针对不同对象返回不同的整数,可以用来区分。

注意

  1. this关键字可以用来访问本类的属性、方法、构造器。
  2. this用于区分当前类的属性和局部变量。
  3. 访问成员方法的语法:this.方法名(参数列表);
  4. 访问构造器的语法:this(参数列表); 注意只能在构造器中调用另一个构造器(必须放在第一条)
  5. this不能在类定义的外部使用,只能在类定义的方法中使用。
public class TestPerson{
    public static void main(String[] args){
        Person p1 = new Person("mary",30);
        Person p2 = new Person("lucy",30);
        System.out.println(p1.compareTo(p2));
    }
}
class Person{
    String name;
    int age;
    //构造器
    public Person(String name, int age){
        this.name = name;
        this.age = age;
    }
    public boolean compareTo(Person p){
        return this.name.equals(p.name) && this.age == p.age;
    }
}

习题

package chapter01;

public class D6 {
    public static void main(String[] args) {
//        类A01,方法max,求某个double数组的最大值并返回
//        double[] arr1 = {1.0,2.0,3.0,4.0,5.0,6.0};
        double[] arr1 = {};
        A01 a01 = new A01();
        Double res = a01.max(arr1);
        if (res != null){
            System.out.println("最大值是" + a01.max(arr1));
        }else{
            System.out.println("arr输入有误!");
        }
    }
}
class A01{
    public Double max(double arr[]){ //Double是一个包装类
//        保证arr至少有一个元素  健壮性
        if (arr != null && arr.length > 0){ //arr是引用类型可以为空,但null.length会报错
            double m = 0.0;
            for (int i = 0; i < arr.length; i++){
                if (arr[i] > m)
                    m = arr[i];
            }
            return m;
        }else{
            return null;
        }
    }
}

返回为null,不能直接返回给基本数据类型double,所以要改成Double类。

public class Test {
    int count = 9;
    public void count1() {
        count = 10;
        System.out.println("count1=" + count);  //10
    }
    public void count2() {
        System.out.println("count1=" + count++);
    }
    
    public static void main(String args[]) {
        new Test().count1(); //匿名对象,只能调用一次

        Test t1 = new Test();
        t1.count2();  //9
        t1.count2();  //10
    }
}

构造器复用

class Employee{
    String name;
    char gender;
    int age;
    String job;
    double sal;
    public Employee(String job, double sal){
        this.job = job;
        this.sal = sal;
    }
    public Employee(String name, char gender, int age){
        this.name = name;
        this.gender = gender;
        this.age = age;
    }
    public Employee(String job, double sal, String name, char gender, int age){
        this(name, gender, age);
        this.job = job;
        this.sal = sal;
    }
}

Random r = new Random();

int n = r.nextInt(3);  //返回0-2的随机数

idea快捷键

  1. ctrl + alt + 向下光标 = 复制一行
  2. ctrl + d = 删除一行
  3. alt + / = 注释
  4. ctrl + alt + l = 格式化代码
  5. alt + r = 快速运行
  6. fn + alt + insert = 快速生成构造器
  7. ctrl + h = 查看类的继承关系
  8. 光标在方法上 + ctrl + b = 定位到方法  或直接 ctrl + 单击
  9. .var = 自动分配变量名。e.g.new Scanner(System.in).var
  10. fori:for循环模板快捷键

类似:创建不同文件夹来保存类文件。

作用

  1. 区分相同名字的类。
  2. 当类很多时,可以很好地管理类。
  3. 控制访问范围。

基本语法

package com.duoruimi  //关键字 包名

 命名

规则

只能包含数字、字母、下划线、小圆点,但不能用数字开头,不能是关键字或保留字。

规范

小写字母+小圆点。

com.公司名.项目名.业务模块名

常用

  • java.lang.*:lang包是基本包,默认引入,不需要再引入。
  • java.util.*:util包,系统提供的工具包,工具类,使用Scanner。
  • java.net.*:网络包,网络开发。
  • java.awt.*:是做java的界面开发,GUI。

细节

import java.util.Scanner;   //只引入java.util包下的Scanner类
import java.util.*;    //引入包下的所有类

Arrays.sort():自动排序

访问修饰符

  1. public:对外公开。
  2. protected:对子类和同一个包中的类公开。
  3. 默认级别:向同一个包的类公开。
  4. privateL只有类本身可以访问,对外不公开。

注意事项

  1. 修饰符可以用来修饰类中的属性、成员方法以及类。
  2. 只有默认的和public才能修饰类,并且遵循上述访问权限的特点。
  3. 成员方法的访问规则和属性完全一致。

面向对象编程三大特征

封装、继承和多态。

封装

把抽象出的数据(属性)和对数据的操作(方法)封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作(方法),才能对数据进行操作。

好处

  1. 隐藏实现细节。
  2. 可以对数据进行验证,保证安全合理。

实现步骤

  1. 对属性私有化。【不能直接修改属性】
  2. 提供一个公共的set方法,用于对属性判断并赋值。
  3. 提供一个公共的get方法,用于获取属性的值。
  4. 封装和构造器结合。
package chapter01;

public class D6 {
    public static void main(String[] args) {
    Person person = new Person();
    person.setName("jack");
    person.setAge(30);
    person.setSalary(300000);
    System.out.println(person.info);
}
class Person {
    public String name;
    private int age;
    private double salary;

    //构造器,使封装的防护机制失效;可以将set方法写在构造器中,这样仍然可以验证数据
    public Person(){
    }
    public Person(String name, int age, double salary) {
        //this.name = name;
        //this.age = age;
        //this.salary = salary;
        setName(name);
        setAge(age);
        setSalary(salary);
    }

    public void setName(String name){
        if(name.length() >=2 && name.length() <=6) {
            this.name = name;
        }else {
            System.out.println("名字的长度不对,需要2-6个字符,默认名字")
            this.name = "某某";
        }
    }
    public String getName(){
        return name;
    }
    public void setAge(String age){
        if (age >= 1 && age <= 120){
            this.age = age;
        }else{
            System.out.println("你设置的年龄不对,需要在1-120,默认为18");
            this.age = 18;
        }
    }
    public int getAge(){
        return age;
    }
    public void setSalary(double salary){
        this.salary = salary;
    }
    public double getSalary){
        //可以增加对用户的权限验证
        return salary;
    }

    public String info(){
        return "信息为 name" + name + "age=" + age + "salary=" + salary;
    }
}

继承

继承可以解决代码复用。当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过extends来声明继承父类即可。

基本语法

class 子类 extends 父类{

}

  1. 子类自动拥有父类定义的属性和方法。
  2. 父类又叫超类、基类。
  3. 子类又叫派生类。

好处

  1. 代码的复用性大大提高。
  2. 代码的可扩展性和维护性提高了。

细节

  1. 子类继承了所有的属性和方法,但是私有属性不能在子类直接访问,要通过父类提供公共的方法去访问。
  2. 子类必须调用父类的构造器,完成父类的初始化。(默认调用父类的无参构造器)
  3. 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用super去指定使用父类的哪个构造器(如:super(参数列表))完成对父类的初始化工作,否则编译不会通过。
  4. super必须放在构造器第一行。
  5. super()和this()都只能放在构造器第一行,因此这两个方法不能共存在一个构造器中。
  6. java所有类都是Object类的子类,Object是所有类的基类。
  7. 父类构造器的调用不限于直接父类,将一直往上追溯到Object类(顶级父类)。
  8. 子类最多只能继承一个父类(指直接继承),即java中是单继承机制。
    如何让A继承B和C?    A继承B,B继承C。
  9. 不能滥用继承,子类和父类之间必须满足 is-a 的逻辑关系。

继承按照查找关系返回信息

  1. 如果子类有这个属性,并且可以访问,则返回信息。
  2. 如果子类没有,就看父类有没有。
  3. 以此类推,直到Object。
  4. 都没有,报错。

super关键字

super代表父类的引用,用于访问父类的属性、方法、构造器。

语法
  1. 访问父类的属性,但不能访问父类的private属性。
    super.属性名;
  2. 访问父类的方法,不能访问父类的private方法。
    super.方法名(参数列表);
  3. 访问父类的构造器。
    super(参数列表);  只能放在构造器的第一句,只能出现一句。
便利和细节
  1. 调用父类的构造器的好处(分工明确,父类属性由父类初始化,子类的属性由子类初始化)。
  2. 当子类中有和父类中的成员(属性和方法)重名时,为了访问父类的成员,必须通过super。如果没有重名,使用super、this、直接访问是一样的效果。
    super直接找父类,this和直接访问,从自身开始往上找。
  3. super的访问不限于直接父类,如果爷爷类和本类中有同名的成员,也可以使用super去访问爷爷类的成员;如果多个基类中都有同名的成员,使用super访问遵循就近原则。
super和this的比较
区别点thissuper
访问属性访问本类中的属性,如果本类没有此属性,则从父类中继续查找从父类开始查找属性
调用方法访问本类中的方法,如果本类没有此方法则从父类继续查找从父类开始查找方法
调用构造器调用本类构造器,必须放在构造器首行调用父类构造器,必须放在子类构造器的首行
特殊表示当前对象子类中访问父类对象

方法重写/覆盖(override)

子类有一个方法,和父类的某个方法的名称、返回类型、参数一样,就说子类的这个方法覆盖了父类的方法。

满足条件
  1. 子类的方法的参数、方法名称,要和父类方法的参数、方法名称完全一致。
  2. 子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类。
    比如,父类返回类型是Object,子类返回类型是String。
  3. 子类方法不能缩小父类方法的访问权限。
    public > protected > 默认 >private。
重写与重载的比较
名称发生范围方法名参数列表返回类型修饰符
重载(overload)本类必须一样类型、个数、顺序至少有一个不同无要求无要求
重写(override)父子类必须一样必须相同子类返回类型和父类返回类型一致,或是其子类子类方法不能缩小父类方法的访问范围

  • 23
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值