程序设计基础·Java学习笔记·面向对象(下)

Java程序设计基础之面向对象(下)

(补充了上的一些遗漏的知识,同时加入了自己的笔记的ヾ(•ω•`)o)

(至于为什么分P,啊大概是为了自己查笔记方便(?)应该是(〃` 3′〃))

(但是u1s1,学完了面向对象后反而更懵逼,下一步先刷算法吧,然后Java的学习也跟上,今年争取考完二级证书(o-ωq)).oO 困)

目录

一、面向对象

(一)快捷键

(二)继承

(三)封装

(四)多态

(五)Object类

(六)关键字

(七)操作符

(八)抽象类

(九)接口

(十)内部类

 

 

一、面向对象

  (一)快捷键

  1.Eclipse:

   (1)setter and getter  右键 + Source

  2.Idea:

   (1)setter and getter  Alt + Insert

 

 

  (二)继承

  1.概念:继承是面向对象语言的重要机制。借助继承,可以扩展原有的代码,应用到其他程序中,而不必重新编写这些代码。在java语言中,继承是通过扩展原有的类,声明新类来实现的。扩展声明的新类称为子类,原有的类称为超类(父类)。继承机制规定,子类可以拥有超类的所有属性和方法,也可以扩展定义自己特有的属性,增加新方法和重新定义超类的方法。(来自百度百科)

  2.在Java中,继承是一种主要思想。通过父子类的继承、抽象类的继承、接口的继承……可以通过继承来完成调用。

  3.继承的方法:

   (1)父子类:在面向对象(上)中,已经描述了继承的方法,通过关键字extends完成父子类的继承;

   (2)接口:接口是特殊的抽象类,我们能够通过抽象类来调用方法,通过此方法调用后,只需要重写接口的内容就可以调用;

  

 

  (三)封装

  1.Java的封装,就是把一些非公开的块进行封装,不让使用者/调用者进行查看,常见的形式是通过修饰词的使用,如private来进行封装;

  2.包装类(Wrapper)

   (1)针对八种基本定义相应的引用类型——包装类(封装类)

 

基本数据类型 包装类
boolean Boolean
byte Byte
short Short
int Integer
long Long
char Character
float Float
double Double

   (2)装箱与拆箱

      a.基本数据类型包装成包装类:装箱

//通过包装类的构造器实现
int i = 500;
Integer t = new Integer(i);
//通过字符串参数构造包装类对象
Float f = new Float("4.56");
Long l = new Long("abcd");

      b.获得包装类对象中包装的基本类型变量:拆箱

//调用包装类的 .xxxValue();方法
Integer i = new Integer(112);
int i0 = i.intValue();

boolean b = new Boolean(false).booleanValue();

      c.自动装箱

//等同于上文中的Integer i = new Integer(112);
Integer il = 112;

      d.自动拆箱

//自动拆箱Integer il = 112;
int i2 = i1;

//等同于boolean b = new Boolean(false).booleanValue();
boolean b = new Boolean(false);

      e.将字符串转换成基本数据类型

//通过包装类的构造器实现
int i = new Integer("123");
//通过包装类的parseXxx(String s)静态方法
int i = Integer.parseInt("123");
float f = Float.parseFloat("0.123");
boolean b = Boolean.parseBoolean("false");

     f.将基本数据类型转换成字符串

//以上文中的i f b做示例
String istr = String.valueOf(i);
String fstr = String.valueOf(f);
String bstr = String.valueOf(ture);

 

 

  (四)多态

  1.多态性,是面向对象中最重要的概念,在Java中有两种体现:

   (1)方法的重载与重写(Overload and Override);

   (2)对象的多态性:可以直接应用在抽象类和接口上;

  2.方法的重写:在子类中可以根据需要对从父类中继承来的方法进行改造,也称方法的重置、覆盖。在程序执行时,子类的方法将覆盖父类的方法。

    注意事项 :

    △ 重写方法必须和被重写方法具有相同的方法名称、参数列表和返回值类型;

    重写方法不能使用比被重写方法更严格的访问权限;

    重写和被重写的方法须同时为static的,或同时为非static的子类方法抛出的异常不能大于父类被重写方法的异常

  3.子类可看做是特殊的父类,所以父类类型的引用可以指向子类的对象:即,向上转型(upcasting);

  4.一个引用类型变量如果声明为父类的类型,但实际引用的是子类对象,那么该变量就不能再访问子类中添加的属性和方法

Student m = new Student();
m.school = “pku”;  //合法,Student类有school成员变量
Person e = new Student();
e.school = “pku”;  //非法,Person类没有school成员变量。  属性是在编译时确定的,编译时e为Person类型,没有school成员变量,因而编译错误。

   5.虚拟方法调用(Virtual Method Invocation)

//正常的方法调用
Person p = new Person();
p.getInfo();
Student s = new Student();
s.getInfo();

//虚拟方法调用(多态情况下)
Person e = new Student();
e.getInfo();
//调用Student类的getInfo()方法

  # 编译时类型和运行时类型编译时e为Person类型,而方法的调用是在运行时确定的,所以调用的是Student类的getInfo()方法。——动态绑定

  # 当调用成员变量时,因为成员变量不具备多态性,所以引用时,我们只考虑引用变量所属类中是否有我们的属性;

  # 而当调用成员方法时,我们在编译时,要查看引用变量所属的类中是否有所调用的方法,所有需要我们的父子类中都存在方法体,但是当我们运行时,只考虑调用的实际对象所属的类中的重写方法;

  6.多态小结

  (1)成员方法:

    编译时:要查看引用变量所属的类中是否有所调用的方法。

    运行时:调用实际对象所属的类中的重写方法。

  (2)成员变量:不具备多态性,只看引用变量所属的类。

 

 

  (五)Object类

  1.Object类是所有Java类的根父类;

  2.Object类的主要方法:

   (1)public Object()                # 构造方法

   (2)public boolean equals(Object obj)       # 对象比较

   (3)public int hashCode()             # 取得Hash码

   (4)public String toString()            # 取得地址

  3.对象类型转换(Casting)

   (1)基本类型数据转换:小的数据类型可以自动转换成大的数据类型;

      强制类型转换:大的数据类型转换到小的数据类型则需要进行强转,表示方法为:long a = (long) b;  float x = (float) y;

   (2)Java对象的强制类型转化(造型)

      在下图的代码中,Person类中是没有方法体getschool的,所以此时我们需要调用方法时,需要将Person e强转为Student,此时就可以调用方法getschool;

public class Test{
public void method(Person e) {
    //设Person类中没有getschool()方法
    // System.out.pritnln(e.getschool());
    //非法,编译时错误
if(e instanceof Student){
Student me = (Student)e;
    //将e强制转换为Student类型
System.out.pritnln(me.getschool());
  }
}
public static void main(Stirng args[]){
Test t = new Test();
Student m = new Student();
t.method(m);
  }
}

 

 

  (六)关键字

  1.this 关键字

   (1)使用this关键字:在一个实例方法或一个构造器中,关键字this是对当前对象的引用。所谓当前对象,指的是其方法或构造器正在被调用的对象,也就是正在调用的方法或构造器所在的对象。可以通过this在一个实例方法或构造器中引用当前对象的任何成员。

   (2)最经常使用this关键字的情况,是在对象的一个字段被方法或构造器的参数屏蔽时,需要调用这个被屏蔽的字段的这种情况。

   (3)对构造器使用this:在一个构造器中,还可以使用this关键字来调用同一个类中的另外的构造器,这种做法称为“显式构造器调用”。

//this在方法内部使用,即这个方法所属对象的印象
//this在构造器内部使用,表示该构造器正在初始化的对象
//  @this表示当前对象,可以调用类的属性、方法和构造器

public class Person {

    //构造体中this的调用
    public Person(){}                        //

    public Person(int age){                  //
        this.age = age;
    }
    public Person(String name){              //
        this();                    //此句则表示进行了①的调用
        this.name = name;
    }

    public Person(int age,String name){
        this(1);                   //进行了②的调用
//Attention!!this进行构造体的调用时,要写在方法的第一句 //this表示的是构造器中初始化的age,而后面的age表示的是形参的age this.age = age; this.name = name; } int age; String name; public void setName(String name){ //this表示的是方法中这个方法所属对象的印象,而后面的name表示的是形参的name this.name = name; } public void setName01(String name) { //this表示调用的是setName方法,而后面的name表示的是形参的name this.setName(name); } public void showInfo(){ System.out.println("姓名:" + this.name); System.out.println("年龄:" + this.age); } }

  2.super 关键字

   (1)在Java类中使用super来调用父类中的指定操作:

   (2)super可用于访问父类中定义的属性

   (3)super可用于调用父类中定义的成员方法

   (4)super可用于在子类构造方法中调用父类的构造器


    注意事项:

    △ 尤其当子父类出现同名成员时,可以用super进行区分

    △ super的追溯不仅限于直接父类

    △ super和this的用法相像,this代表本类对象的引用,super代表父类的内存空间的标识

  3.this与super的区别

序号 区别 this super
1 访问属性 访问本类中的属性,如果本类没有此属性则从父类中继续查找 访问父类中的属性
2 调用方法 访问本类中的方法 直接访问父类中的方法
3 调用构造器 调用本类构造器,必须放在构造器首行 调用父类构造器,必须放在子类构造器的首航
4 特殊 表示当前对象 (/ω\*)……… (/ω•\*)没有啦

   4.static关键字

    (1)在Java中,static可以用来修饰属性、方法、代码块、内部类;

    (2)类变量(class Variable):被static所修饰的变量就是类变量,他是静态的,如果不想变量被改变,那么就可以使用静态变量;

         类变量(类属性)由该类的所有实例共享;类变量不需要通过实例化就可以进行使用;

    (3)类方法(class Method):被static所修饰的方法就是类方法;

      没有对象的实例时,可以用 类名.方法名() 的形式访问由static标记的类方法;同时,在类方法中只能访问类的static属性;

      因为不需要实例化就能访问,所以类方法中不能有 thissuper 关键字;

    (4)代码块中,优先执行静态代码块,其次是代码块,然后才是其他方法;

  5.final关键字

    (1)在Java中,final关键字用来表示“最终”的意思;

    (2)final标记的类不能被继承;

    (3)final标记的方法不能被子类重写;

    (4)我们称final修饰的变量为常量,只能被赋值一次,名称大写;

 

 

  (七)操作符

  1.instanceof操作符

    x instanceof A:检验x是否为类A的对象,返回值为boolean型。要求x所属的类与类A必须是子类和父类的关系,否则编译错误。如果x属于类A的子类B,x instanceof A值也为true。

public class Person extends Object {…}
public class Student extends Person {…}
public class Graduate extends Person {…}

public void method1(Person e) {
if (e instanceof Person)       //处理Person类及其子类对象
if (e instanceof Student)      //处理Student类及其子类对象
if (e instanceof Graduate)     //处理Graduate类及其子类对象
}

     # 要求x所属的类与类A必须是子类和父类的关系,否则编译错误;

     # 如果x属于类A的子类B,x instanceof A值也为true;

   2. 【==】操作符 && equals操作符

   (1)【==】操作符基本类型比较:只要两个变量的值相等,即为ture;

      引用类型比较引用(是否指向同一个对象):只有指向同一个对象时,才返回ture;

      用【==】进行比较时,符号两边的数据类型必须兼容(可自动转换的基本类型除外),否则编译出错;

   (2)equals():所有类都继承了Object,也就获得了equals()方法,还可以重写;

      只能比较引用类型,其对象与【==】相同,比较是否指向同一个对象;

      特例:使用equals对File、String、Data及包装类来说,是比较类型及内容而不考虑引用的是否是同一个对象;

       原因:在这些类中重写了Object类的equals方法。  

 

 

   (八)抽象类

  1.用abstract关键字来修饰一个类时,这个类叫做抽象类;用abstract来修饰一个方法时,该方法叫做抽象方法;

  2.抽象方法:只有方法的声明,没有方法的实现;以分号结束:abstract int abstractMethod(int a);

  3.含有抽象方法的类必须被声明为抽象类

  4.抽象类不能被实例化。抽象类是用来作为父类被继承的,抽象类的子类必须重写父类的抽象方法,并提供方法体。若没有重写全部的抽象方法,仍为抽象类;

  5.不能用abstract修饰属性、私有方法、构造器、静态方法、final的方法;

 

  (九)接口(interfac)

  1.接口是特殊的抽象类;

  2.在我们进行父子类的调用时,因为Java不支持多重继承,所以我们可以通过接口进行多重的继承,只需要重写方法体即可;

  3.实现接口:class 类名 implements 接口名{  }

  4.一个类可以实现多个接口,通过“ ,”进行多个接口的串联;接口也可以继承其他接口;

  5.接口的特点:用interface来定义;

   接口中的所有成员变量都默认是由public static final修饰的;

   接口中的所有方法都默认是由public abstract修饰的;

   接口没有构造器;

   接口采用多层继承机制。

  6.实现接口的类中必须提供接口中所有方法的具体实现内容,方可实例化;否则,仍为抽象类;

   接口的主要用途就是被实现类实现(面向接口编程);

   与继承关系类似,接口与实现类之间存在多态性;

   定义Java类的语法格式:先写extends,后写implements;

 

  (十)内部类(Inner class)

  1.在类中写的类就是内部类;

  2.匿名内部类:不能定义任何静态成员、方法和类,只能创建匿名内部类的一个实例;一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类;

  3.内部类的作用:解决Java中不能多重继承的问题;通过内部类继承来继承多个类进行重写;

  4.内部类的使用方法;

 

public class Test{
    int i;
    public int z;
    private int k;
 
    //内部类 A
    class A{
        public void setTestFileds(){
            //在Test类中的成员变量,所以不能直接通过this调用,而是Test.this
            Test.this.i = 1;
            Test.this.z = 2;
            Test.this.k = 3;
            }
        }

    //调用类A
    public void setInfo(){
        new A().setTestFileds();
        }

    //输出类A
    public void showInfo(){
        System.out.println(this.i);
        System.out.println(this.z);
        System.out.println(this.k);
        }
}

 

Tags: