Java学习-Day02-类与继承

知识要点-面向对象

三大特征:封装,继承和多态

1.定义类语法

[修饰符] class 类名{
  零到多个构造器定义..
  零到多个成员变量..
  零到多个方法..
}
  • 修饰符可以是public,final,abstract或者完全省略,类名满足驼峰命名法
  • static修饰的成员不能访问没有static修饰的成员

2.定义成员变量
[修饰符] 类型 成员变量名 [ = 默认值]

  • 修饰符可以省略,也可以是public,protected,private,static,final
  • 其中public,protected,private只能出现其一,可以与static,final组合使用

3.定义方法

[修饰符] 方法返回值类型 方法名[形参列表]{
  //由零条到多条可执行性语句组成的方法体
}
  • 修饰符可以省略,也可以是public,protected,private,static,final,abstract
  • 其中public,protected,private只能出现其一,abstract与final只能出现其一,可以与static组合使用
  • 无返回值,类型用void

4.static关键字

  • static修饰的成员表明它属于这个类本身,而不属于该类的单个实例

5.定义构造器

[修饰符] 构造器名(形参列表){
  //由零到多条可执行性语句组成的构造器执行体
}
  • 修饰符可以省略,也可以是public,protected,private其中之一

6.this关键字

  • Java允许对象的一个成员直接调用另一个成员,可以省略this前缀(js不行)
  • static修饰的方法不能使用this引用,this无法指向合适的对象
  • 方法内若有局部变量和成员变量同名,则必须使用this关键字
  • 如果需要在静态方法中访问另一个普通方法,则只能重新创建一个对象
public class StaticAccessNonStatic{
  public void info(){
    System.out.println("简单info方法");
  }
  public static void main(String[] args){
    //main()是静态方法,info()非静态
    //下面语句会报错
    info();
    //可以修改为
    new StaticAccessNonStatic().info();
  }
}

7.方法

  • Java中方法不能独立存在,要么属于类,要么属于对象
  • 永远不能被独立执行,执行方法必须使用类或者对象作为调用者

8.形参

  • 执行方法传入参数,参数为基本数据类型时,传入参数的变量被复制一遍,在方法内的变化并不会使外部的变量也发生变化
public class PrimtiveTransferTest{
  public static void swap(int a,int b){
    int temp = a;
    a = b;
    b = temp;
  }
  public static void main(String[] args){
    int a = 1;
    int b = 2;
    //传入a和b并不会使a和b值发生改变,传入后值被复制
    swap(a,b);
  }
}
  • 参数为引用类型时,传入参数被复制的仅仅是引用的变量,在方法内的变化会影响到引用的值(即堆内存中的值)也发生变化
class DataWrap{
  int a;
  int b;
}
public class ReferenceTransferTest{
  public static void swap(DataWrap dw){
    int temp = dw.a;
    dw.a = dw.b;
    dw.b = temp;
  }
  public static void main(String[] args){
    DataWrap dw = new DataWrap();
    dw.a = 1;
    dw.b = 2;
    //调用swap方法后,dw对象成员变量值会随之改变
    swap(dw);
  }
}
  • 形参可以定义数量不确定形参,在最后一个形参类型后增加三点'...'
    public static void test(int a,String... books){}

8.方法重载:同一个类中包含两个或以上方法名相同,形参不同(js没有,因为有可变参数,可以用算法实现)

  • 不能用返回值类型作为方法重载判断方法,因为直接调用方法时,java无法判断使用哪种返回值类型

9.作用域


Java学习-Day02-类与继承_第1张图片
变量种类
  • Java作用域类似于JavaScript,但是Java存在代码块局部变量,即在代码块中定义的变量在外部无法访问(类似ES6中let)

10.成员变量初始化和内存中运行机制

class Person{
  static int eyeNum;
  String name;
}
//创建第一个Person对象
//第一次使用Person类,系统在第一次使用时加载这个类并进行初始化,为类变量eyeNum分配内存空间,指定默认初始值0
Person p1;
//Person类初始化完成后,系统在堆内存中分配一块内存区,创建一个实例对象,同时分配实例变量的内存空间,赋予初始值
//实例对象也包含类变量内存,并把对象赋给p1
p1 = new Person();
//创建第二个Person对象,不需要初始化Person类
Person p2 = new Person();

11.封装(Encapsulation)

  • 使用访问控制符:private,protected,public


    访问控制级别
  • private (当前类访问权限):如果类里的一个成员(成员变量,方法,构造器)使用private修饰,则这个成员只能在当前类的内部被访问。
    适合于修饰成员变量
  • default(包访问权限):如果类里的一个成员不使用任何修饰符,则它有包访问权限,可以被相同包下的其他类访问
  • protected(子类访问权限):如果类里的一个成员使用protected修饰,则这个成员既可以被同一个包中的其他类访问,也可以被不同包中的子类访问
    使用protected来修饰一个方法,通常是希望其子类来重写这个方法
    -public(公共访问权限):使用public修饰,则这个成员或外部类可以被所有类访问,不管访问类与被访问类是否在同一个包中,是否具有父子继承关系


    Java学习-Day02-类与继承_第2张图片
    访问级别控制表
  • 如果java源文件中定义的所有类都没有使用public修饰,则这个java源文件的文件名可以是一切合法的文件名,但是如果一个java源文件里定义了一个public修饰的类,则这个源文件的文件名必须与public修饰的类的类名相同
//良好封装的Person类
public class Person{
  //private修饰成员变量
  private String name;
  private int age;
  //提供方法操作name成员变量
  public void setName(String name){
    if(name.length() > 6 || name.length() < 2){
      System.out.println("不符合要求");
      return;
     }else{
       this.name = name; 
    }
  }
  public String getName(){
    return this.name;
  }
  public void setAge(int age){
    this.age = age;
  }
  public int getAge(){
    return this.age;
  }
}

12.访问控制符基本规则

  • 类里绝大部分成员变量都应该使用private修饰,只有一些static修饰的,类似全局变量的成员变量,才可能考虑使用public修饰。除此之外,有些方法只用于辅助实现该类的其他方法,这些方法称为工具方法,工具方法也应该使用private修饰
  • 如果某个类主要用作其他类的父类,该类里包含的大部分方法可能仅希望被其子类重写,而不想被外界直接调用,则应该使用protected修饰这些方法
  • 希望暴露出来给其他类自由调用的方法应该使用public修饰。因此,类的构造器通过使用public修饰,从未允许在其他地方创建该类的实例。因为外部类通常都希望被其他类自由使用,所以大部分外部类都使用public修饰

13.package,import和import static

  • 把一个类放在指定的包结构下,则在Java源程序的第一个非注释行放置package packageName;
    意味着该源文件里所有类都属于这个包
  • javac -d . HelloWorld.java编译时,'-d'会自动建立对应的文件结构来放置class文件
  • 父级包中的类调用子级包中的类时,必须有完整包路径加类名
  • import语句出现在package之后,class定义之前,可以有多个import
  • import lee.sub.*表示导入sub包下的所有类,不包括子包lee.sub.pic
  • Java默认为所有源文件导入java.lang包下所有类,因此使用StringSystem都无需导入,但例如Arrays类,位于java.util包下
  • 有重复类位于两个包时,应该使用全名,避免import
  • import static导入静态成员变量,静态成员方法import static package.subpackage.ClassName.fieldName | methodName

14.Java常用包


Java学习-Day02-类与继承_第3张图片
常用包

15.构造器(创建对象时执行初始化)

  • 同一个类允许有多个构造器,根据形参不同,即构造器重载

16.类的继承

  • 通过extends继承class children extends parents
  • Java是单继承,Java类只有一个直接父类
  • 未指定直接父类时,默认扩展java.lang.Object类,即java.lang.Object是所有类的父类

17.类的方法重写(方法覆盖)

  • 子类包含父类同名方法
  • “两同两小一大”原则,方法名形参列表相同,子类方法返回值类型应比父类更小或相等,子类方法抛出的异常类应比父类更小或相等,子类方法的访问权限应比父类更大或相等
  • 覆盖方法与被覆盖方法必须是同一种类,即类方法或实例方法

18.重载与重写

  • 重载发生在同一个类多个同名方法之间,重写发生在子类和父类同名方法之间

19.super限定

  • super.method();调用被重写的父类方法
  • super不能出现在static修饰的方法中
  • super可以访问到父类中因为同名被隐藏的实例变量
  • super可以调用父类构造器中的初始化代码

20.继承树:创建Class B对象,系统先执行java.lang.Object类的构造器,再执行Class A的构造器,然后才执行Class B的构造器

Java学习-Day02-类与继承_第4张图片
继承树

21.多态:引用变量编译时类型和运行时类型,编译时类型与运行时类型不一样,就可能出现多态

class BaseClass{
  public int book = 6;
  public void base(){
    System.out.println("BaseClass");
  }
}
class SubClass extends BaseClass{
  public String book = "多态";
  public void sub(){
    System.out.println("sub方法");
  }
  public void base(){
    System.out.println("SubClass");;
  }
  public static void main(String[] args){
    //下面编译时类型和运行时类型一致,不存在多态
    BaseClass bc = new BaseClass();
    bc.book == 6;//true
    SubClass sc = new SubClass();
    sc,book == "多态";//true
    //下面编译时类型为BaseClass,运行时类型为SubClass,存在多态
    BaseClass ploymophicBc = new SubClass();
    ploymophicBc.book == 6;//true,表明访问的是父类的实例变量
    //ploymophicBc.sub()报错,编译时出现错误
  }
}
  • 子类是一种特殊的父类,Java允许把子类对象直接赋给一个父类引用变量,无需任何类型转换,称为向上转型,由系统自动完成
  • 当把一个子类对象赋给一个父类引用变量时,运行时调用该引用变量的方法时,其方法行为总是表现出子类的行为特征,而不是父类的行为特征。出现相同类型的变量,调用同一个方法时呈现出多种不同的行为特征,这就是多态
  • 对象的实例变量是不具备多态性的,引用变量在编译阶段只能调用其编译时所具有的方法

22.引用变量的强制类型转换

  • 引用变量在编写时只能调用它编译时的类型的方法,而不能调用它运行时类型的方法,如果需要让这个引用变量调用它运行时类型的方法,则必须把它强制类型转化成运行时类型,借助于类型转换运算符
  • (type)variable这种用法可以将variable变量转换成一个type类型的变量,也可以将一个引用类型变量转换成其子类类型,需注意:
    基本类型之间的转换只能在数值类型之间进行
    引用类型之间的转换只能在具有继承关系的两个类型之间进行,父类实例转换成子类类型,则必须这个对象编译时是父类类型,运行时是子类类型
  • instanceof判断是否可以转换

23.instanceof

  • [引用类型变量] instanceof [类]用于判断前面的对象是否是后面的类或者其子类,实现类的实例
  • instanceof前面操作数的编译时类型要么与后面的类相同,要么与后面的类具有父子继承关系

24.继承使用原则

  • 尽量隐藏父类的内部数据,尽量把父类的所有成员变量都设置成private访问类型,不要让子类直接访问父类的成员变量
  • 不要让子类可以随意访问,修改父类的方法。父类中的辅助工具方法应该用private修饰
  • 尽量不要再父类构造器中调用将要被子类重写的方法

25.初始化块

[修饰符]{
  //代码
}
  • Java类里可出现的第四种成员,可存在多个,在构造器运行之前运行
  • 修饰符只能是static,静态初始化块,只在类初始化的时候执行


    Java学习-Day02-类与继承_第5张图片
    提取初始化块

你可能感兴趣的:(Java学习-Day02-类与继承)