小白学习Java第七天

课前小练习

public class Demo1 {
    public static void main(String[] args) {
       	Person p1= new Person();
  	Person p2= new Person();
	p1.compare(p2);
    }
}

class Person{
    private  String  name ;
    private  int age;

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

   //封装方法,比较年龄是否相同
    public  boolean  compare(Person p){
        return  this.age == p.age;
    }

 

一. 静态

(一)静态概述

  1. 静态就是 static , 主要用来修饰java的变量和方法的关键字。
  2. 没有静态与有静态的场景对比:
    a : 没有静态
    如果某个类型的所有对象,都具有一个相同的属性值,那么这个属性值就没有必要在所有对象中,都存储一份。还有坏处:浪费内存空间;维护难度大,一旦需要修改,就得修改所有的对象
    b: 有静态
    如果某个类型的所有对象,都具有一个相同的属性值,那么就在这个属性的定义上,加一个static静态关键字。让该变量存储在方法区字节码的静态区中,避免了所有对象都存储相同数据的问题,节省了内存空间,将来维护容易(只需要修改一次)
    在这里插入图片描述

(二) 静态的内存理解

  1. 没有静态内存图:

在这里插入图片描述

  1. 有静态的内存图:

在这里插入图片描述

(三) 静态变量的特点

  1. 静态变量属于类, 不属于对象
  2. 加载时机:
    随着类的加载而加载
    静态变量随着类的加载进方法区,就直接在静态区给开辟了存储静态变量的内存空间
  3. 静态变量优先于对象而存在
  4. 静态变量被所有该类对象所共享
  5. 调用方式:
    类名调用(常用) 或者 创建对象调用

(四) 静态访问的注意事项

1、静态方法:在方法声明上,加上了static关键字的方法,就是静态方法
2、静态方法不能访问非静态的变量
原因:
静态方法可以在没有创建对象的时候调用,而非静态的变量只有在对象创建之后才存在。如果静态方法可以访问非静态的变量,那么就相当于在对象创建之前,就访问了对象创建之后的数据。明显不合理。
3、静态方法不能访问非静态的方法
原因:
静态方法可以在没有创建对象的时候调用;非静态的方法可以访问非静态的变量。如果静态方法可以访问非静态的方法,就相当于静态方法间接的访问了非静态的变量,和第2点矛盾。
4、静态方法中不能存在this关键字
原因:
this关键字表示本类当前对象。静态方法可以在对象创建之前调用。如果静态方法可以访问this关键 字,相当于在创建对象之前,就使用了对象本身,矛盾

(五) 静态成员变量和非静态成员变量的区别

  1. 概念上,所属不同:
    非静态变量属于对象
    静态变量属于类,类变量
  2. 内存空间不同,存储位置不同
    非静态变量属于对象,所以存储在堆内存中
    静态变量属于类,存储在方法区的静态区中
  3. 内存时间不同,生命周期不同
    非静态变量属于对象,所以生命周期和对象相同,随着对象的创建而存在,随着对象的消失而消失
    静态变量属于类,所以生命周期和类相同,随着类的加载而存在,随着类的消失(内存管理)而消失
  4. 访问方式不同
    非静态变量只能使用对象名访问
    静态变量既可以使用对象访问,也可以通过类名访问:
    类名.静态变量名 或者 对象名.静态变量
    类名.静态方法名()
import javax.naming.Name;

public class Demo2 {

    public static void main(String[] args) {
       /* Student s1 = new Student();
        s1.name= "小明";
        s1.age = 20;
        s1.country = "中国";

        Student s2 = new Student();
        s1.name= "小丽";
        s1.age = 18;
        s1.country = "中国";*/

        Student s1 = new Student();
        s1.name= "小明";
        s1.age = 20;
        System.out.println(s1.country);

        Student s2 = new Student();
        s1.name= "小丽";
        s1.age = 18;
        System.out.println(s2.country);

        System.out.println(Student.country); //推荐方式

//        s1.method();
//        Student.method(); //推荐方法

        System.out.println(Student.num);
    }
}

/*
* static:
*    静态的意思,是一个成员修饰符,修饰成员变量或方法。
*   没有静态前:
*      学生类型的所有对象都有一个相同的属性值,即国家的属性值:中国。
*      在堆中存储每个对象时,每块空间中有一个“中国”,占用内存空间,维护成本也高,一旦值发生改变,每块空间中的“中国”都要修改。
*   使用静态修饰符:
*      学生类中的country被static修饰符后,存储在方法区,student.class文件中的静态区域中
*      该属性值会被student类型的所有对象所共享,在内存中只存储一份,节约了内存空间,并降低了维护成本。
*
* 修饰变量:
*   1.随着类的加载而存储,随着类的消失而消失,生命周期长。
*   2.叫做类变量、静态变量,通过类名可以直接访问(推荐方式)。
*   3.优先于对象存储在内存中,通过对象名.静态变量名也可以访问(不推荐的方式)
*   4.可以被所有对象所共享
*  注意: 必须是某类型的所有对象的共享资源数据时,可以用static修饰
*
* 修饰方法(静态方法或类方法):
*   1.可以使用类名或对象名去调用,类名调用是推荐方式
*   2.静态方法只能直接访问静态成员,不可以直接访问非静态成员
*     想要访问非静态成员,必须在静态方法中创建对象,通过对象去访问。
*   3.在静态方法中,不能出现this或super关键字。
*
* 注意:
*    1.非静态方法中既可以访问静态成员也可以访问非静态成员
*    2.该类中没有需要维护的数据时(即没有属性),方法都可以是静态的,即通过类名去访问,常见用于是工具类。
*
*  数组:
*    1.遍历   2,获取最值  3.反转  4、排序...
*  步骤:  1.构造方法私有化   2.方法静态
* */
class  Student{
    String name;
    int  age;
    static String country = "中国";
    static int num;

    public static  void  method(){
        Student s = new Student();
        System.out.println(s.name);
        System.out.println(country);
        s.show();
//        System.out.println(this);
    }

    public   void  show(){
        System.out.println(country);
        method();

    }
}
public class ArrayTools {
    //1.构造方法私有化
    private  ArrayTools(){}
    //2.方法都是静态的
    /*
    * 获取数组中最大元素
    * */
    public  static  int   getMax(int[] arr){
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (max < arr[i])
                max = arr[i];
        }
        return max;
    }
    /*
     * 获取数组中最小元素
     * */
    public  static  int   getMin(int[] arr){
        int min = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (min > arr[i])
                min = arr[i];
        }
        return min;
    }

    /*
     * 反转数组中元素
     * */
    public  static  void  reverse(int[] arr){
        for (int i = 0; i < arr.length/2; i++){
            int temp = arr[i];
            arr[i] = arr[arr.length-1-i];
            arr[arr.length-1-i] = temp;
        }
    }

}
import java.util.Arrays;

public class Demo3 {
    public static void main(String[] args) {
//        int[] arr = {3,1,4,8,5};
//        ArrayTools.getMax(arr);
//        Arrays.sort(arr);

//        System.out.println(args);//[Ljava.lang.String;@1540e19d
//        System.out.println(args.length); //0
//
//        System.out.println(args[0]);

        String[] arr = {"a","b","c"};
        Demo.main(arr);
    }
}


class  Demo{
    public static void main(String[] args) {
        System.out.println("执行了");
        System.out.println(args.length+"...");
    }
}

二. 继承

(一) 继承的概述

  1. 继承概述: 继承是面向对象三大特征之一,让类与类产生子父类的关系.可以使得子类具有父类的属性和方法,还可以在子类中重新定义,以及追加属性和方法一种体现方式

  2. 继承的实现:
    使用关键字extends,表示: 扩展、增加、继承

  3. 格式:

    class 子类 extends 父类 { }
     父类:被继承的类,超类、基类
     子类:用于继承的类,派生类
     举例:
      	class Dog extends Animal { }
    
public class Demo4 {
    public static void main(String[] args) {
        Student1 s = new Student1();
        s.name = "小刚";
        //s.age = 18;
        s.setAge(18);
        System.out.println(s.getAge());
        s.sId = 10001;
        s.eat();
        s.study();
    }
}

class  Person1{
    String name;
    private  int age;

    public  Person1(){}
    void  eat(){
        System.out.println("eat");
    }

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

    public int getAge() {
        return age;
    }
}

class Student1 extends Person1{
    int  sId;

    void  study(){
        System.out.println("study java"+name+"..."+getAge());
    }


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

    public int getAge() {
        return age;
    }*/
}

(二) 继承的好处

  1. 继承的好处:
    (1) 提高了代码的复用性(多个类相同的成员可以放到同一个类中)
    (2) 提高了代码的维护性(如果方法的代码需要修改,修改一处即可)
    (3) 为多态提供了前提

  2. 继承中弊端:
    继承让类与类之间产生了关系,类的耦合性增强了,当父类发生变化时子类实现也不得不跟着变化,削弱了子类的独立性

  3. 应用场景:
    使用继承,需要考虑类与类之间是否存在is…a的关系,不能盲目使用继承
    is…a 的关系:谁是谁的一种
    例如:老师和学生都是人的一种,那人就是父类,学生和老师就是子类

(三) 继承的注意事项

1、私有的成员不能被继承
父类中有一些私有成员,不能在子类中直接使用
其实在子类对象中,仍然包含了父类中定义的私有成员变量
只不过在子类中,不能直接访问父类中定义的私有成员变量

2、父类中的构造方法,不能继承
原因:
父类的构造方法需要和父类的类名一致、子类的构造方法需要和子类类名一致,父 类和子类的类名不一样。因此无法继承,名称有冲突。
父类的构造方法用于给父类的成员变量赋值,子类的构造方法用于给子类的成员变 量赋值,子类的成员变量较多,使用父类的构造方法无法将子类中所有的成员变量都进 行赋值,因此不继承父类的构造方法

(四) 继承的特点

1、java支持单继承,不支持多继承,支持多层继承
单继承:一个子类只能继承一个父类
不能多继承:一个子类不能同时继承多个父类
可以多层继承:A类可以继承B类,B类可以继承C类,A类中拥有B、C类中的所有属性和方法。说明:越是顶层的类,定义的功能越是共性功能,功能和属性就越少;越是底层的类,定义的特有功能和属性就越多,就更加强大。学习一个体系的时候,先学顶层的类,共性功能学习完,学习底层特有的方法即可;使用一个类创建对象的时候,选择底层的类型,功能更多更强大。

2、原因:
如果支持多继承,那么可能一个子类继承了两个父类,两个父类中有相同的方法声明,却拥有不同的方法实现。子类继承之后,就不知道该走哪个父类的方法实现了(安全隐患)。

(五) 继承中成员变量的关系

  1. 父类中定义了成员变量,子类中没有定义,那么子类可以直接使用父类中非私有成员

  2. 父类中没有定义成员变量,子类中定义了,子类可以自己调用自己的变量,父类不能调用子类特有变量
    总结: 子类可以使用自己和父类的成员变量,父类只能使用自己的成员变量

  3. 父类中定义了变量,子类中重新定义了这个变量,在子类中调用的就是子类的变量

     原因: 变量的访问就近原则
     1) 方法内部,自己定义了变量,使用方法内部变量
     2) 方法内部没有定义,找当前类中成员变量
     3) 类中成员变量也没有定义,找父类中的成员变量
     4) 父类中没有定义变量,再继续找父类的父类,直到找到最后(Object类,所有类的直接或者间接的父类,Object是一个最顶层的类,也没有找到,才报错
    
  4. 如果子父类中成员变量重复定义, 想调用父类成员变量, 可以使用关键字 super
    使用 : super.父类成员变量名;

(六) 继承中成员方法的关系

  1. 父类中私有方法不能被子类继承使用
  2. 子类中定义的和父类中继承到的方法不同, 子类可以调用自己特有方法功能, 可以调用从父类继承来的功能
  3. 当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容, 是对父类方法的功能进行了拓展和维护
  4. 重写Override注意事项:
    1. 重写需要与父类原方法, 返回值类型, 方法名 ,参数列表相同
    2. 私有方法不能被重写
    3. 子类方法访问权限不能更低(public > 默认 > 私有)
    4. 在子类重写方法上, 通常使用注解 @Override, 用来检测当前的方法, 是否是重写的方法,起到【校验】的作用

注意 : 重写的方法本身还是属于父类,只是在子类中重新实现了这个方法的内容。

(七) super关键字

  1. super :建立在继承关系中用来使用父类资源的关键字
  2. 使用场景: 子父类中的成员变量或方法重名时, 可以使用super关键字表示父类成员调用
    super只能访问父类中定义的成员变量
    语法: super.成员变量名;
    super只能访问父类中定义的成员方法
    语法: super.成员方法名(实际参数);

(八) 关键字this和super的详细解释

1、this和super:
this表示本类当前对象的引用
super表示本类当前对象父类的引用

2、图示:

在这里插入图片描述

(九) 继承中构造方法的关系

  1. 父类中构造无法被子类继承, 但是子类构造方法中可以调用父类构造; 在子父类继承关系中, 父类优先于子类进入到内存, 父类中数据优先于子类进行初始化
  2. 如果子类构造方法中, 没有手动调用任何构造(本类, 父类),系统会默认在子类构造方法第一行调用super(); 目的是为了让父类中成员优先于子类进入内存中赋值
  3. 如果子类构造方法中, 手动调用本类或者父类构造, 那么系统不会再默认调用任何构造, 一律以手动调用构造为准
  4. super() : 父类空参构造调用. 必须写在构造方法第一位置上, 直接保证父类构造优先于子类进入内存运行
public class Demo1 {
    public static void main(String[] args) {
        //出现了继承,加载类时,先加载父类,再加载子类
        Zi zi = new Zi("",10);

    }
}
/*
* 继承出现后:
*    构造方法变化:
*       构造方法的作用:主要用于给对象的属性进行初始化。
*       创建子类对象,发现父类的构造方法也执行了,意味着让父类的属性先初始化,然后子类属性在初始化。
*    在子类的构造方法的第一行有一条隐藏的  super();  语句:这个语句就是去调用父类的无参数构造方法
*    如果父类中没有无参数构造方法,那么子类构造方法的第一行必须显示写出  super(参数);  语句.
*
* 父类的构造方法执行了,那么父类的对象创建了吗?
*    没有创建。仅仅是子类中持有一个父类型引用,即super,super可以调用父类中的所有成员,变量、方法、构造方法。
*
* 子类构造方法:
*    重载构造方法调用 : this(参数);  需要在第一行
*    调用父类的构造方法: super(参数);  需要在第一行
*    this() 和 super() 是不能共存的,在一个构造方法中,如果写了this()就不能写super()  写了super(),就不能写this()。
*
* */
class Fu{
    //构造方法
    public  Fu(){
        System.out.println("父");
    }

    public  Fu(int  x){
        System.out.println("父---"+x);
    }
}

class Zi  extends  Fu{
    private  String s;
    private  int  a;
    //构造方法
    public   Zi(){
        super();
        System.out.println("子");
    }

    public   Zi(String s){
        this();
        this.s = s;
        //System.out.println("子---"+s);
    }

    public   Zi(String s,int  a){
        this(s);
        this.a = a;
        //System.out.println("子---"+s+"..."+a);
    }
}

(十) this和super使用总结

1、含义:

this关键字表示本类当前对象的引用
 	哪个对象在调用this所在的方法,this就表示哪个对象
super关键字表示本类当前对象的父类引用
 	哪个对象在调用super所在的方法,super就表示哪个对象中的父类部分的数据

2、super和this都可以访问成员变量

super只能访问父类中定义的成员变量
 	super.成员变量名
this既可以访问子类中定义的成员变量,也可以访问父类中定义的成员变量
 	this.成员变量名

3、super和this都可以访问成员方法

super只能访问父类中定义的成员方法
 	super.成员方法名()
this不仅可以访问子类中定义的成员方法,也可以访问父类中定义的成员方法
 	this.成员方法名()

4、super和this都可以访问构造方法:this语句和super语句

this():访问本类的其他构造方法
super():访问父类的构造方法
public class Demo5 {
    public static void main(String[] args) {
        Zi zi = new Zi();
        //System.out.println(zi.num);
        //zi.show();
        //zi.method();
        zi.study();
    }
}

class A{}
class B extends A{}

class Fu{
    int num = 10;

    public  void  method(){
        System.out.println("fu");
    }

    public A study(){
        System.out.println("走路");
        return null;
    }
}

class Zi extends  Fu{
    //int num = 100;

    public  void  show(){
        int num = 1000;
        System.out.println(num);
        System.out.println(this.num);
        System.out.println(super.num);
    }

    public  void  method(){
        System.out.println("zi");
    }

    @Override
    public B study(){
        System.out.println("开车");
        super.study();
        return null;
    }

}
/*
* 继承出现后:
*    类中成员的变化:
*      变量:
*           子父类中出现相同的变量,创建子类对象,访问该变量,默认访问是子类中的。
*           super:
*              超级的意思,代表父类的引用。用法与this很相似。
*              this:代表的是当前类对象的引用,可以访问当前类中的成员,也可以访问父类中的成员
*              super:代表的是父类对象的引用,只能访问父类中的成员。
*      方法:
*           子父类中出现相同的方法定义,方法体不同,创建子类对象,调用该方法,默认运行的是子类中的方法,
*           这种现象叫做方法的重写/覆盖(override)。
*          overload:重载,方法名相同,参数列表不同
*          override:重写,子类重复父类中继承的方法。
*         为什么重写?
*          继承的方法的功能不满于子类的需求。
*        重写方法需要注意?
*        1.权限修饰符要大于等于父类。
*           public  protected  默认   private
*        2.方法名和参数列表要与父类的方法相同
*        3.返回值类型可以小于等于父类的  jdk5.0版本
*       通常:修饰符 返回值类型 方法名 参数列表 与父类的相同
*       验证是否是重写方法: 在重写的方法的上边写一个注解 @Override
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值