程序员java学习Android知识

JAVA学习记录day3

2017-06-20  本文已影响0人  Geg_Wuz

今天的主要内容是构造方法,static用法,继承,多态,抽象类,接口。由于从今天开始JAVA的学习基本上都是面向对象的内容,虽然这些内容底层的实现是由C++写的编译器实现的,在用法上与C语言已经大相径庭,故不再比较二者的差异。开始阐释JAVA的知识点为主。

构造方法

所谓构造方法,就是在创建对象时自动执行的方法,主要用于对成员变量的初始化,当然也可以用于对运行环境的初始化,如加载驱动等。

class Demo_constructor {
    public static void main(String[] args) {
        Person p = new Person();
        System.out.println(p.name+"..."+p.age);     //张三...18
        }
}
class Person{
         String name;
         int age;
         public Person(){
              name = "张三";
              age = 18;
         }
}

代码中通过空参构造方法Person(),对类中的name和age赋值为张三和18,在主方法中new一个Person对象的时候没有传递参数,系统自动执行空参构造方法,对象中的name和age便有了初值张三和18;

class Demo_constructor {
    public static void main(String[] args) {
        Person p = new Person("张三",18);
        System.out.println(p.name+"..."+p.age);     //张三...18
    }
}
class Person{
    String name;
    int age;
    public Person(String name,int age){
        this.name = name;
        this.age = age;
    }
}

当局部变量名与成员变量名的相同时,局部变量会隐藏成员变量,但在开发中常要求见名知意,对于这种情况,可以用this.来引用成员变量,与局部变量区分开来。


static

static是静态的意思,在类中定义static成员变量和static成员方法,这些方法是存放在内存的方法区中,在创建对象的时候,不需对这些变量和方法分配空间,可以达到资源共享的作用。

class Demo_static {
    public static void main(String[] args) {
        Person p = new Person();
        p.name = "张三";              
        p.country ="中国";                
        p.speak();                      //张三...中国

        Person p2 = new Person();
        p2.speak();                     //null...中国
        p2.country = "America";
        p.speak();                      //张三...America
    }
}
class Person{
    String name;
    static String country;      //在c语言的解释中就是将country声明周期延长,实现共享,节省空间资源
    public void speak(){
        System.out.println(name+"..."+country);
    }
}

从代码中可以看到,创建对象p之后,将p的name和country修改为张三和中国,然后创建对象p2,虽然没有对p2的属性进行修改,但由于country是static变量,所以,p2的country也为中国,而非静态变量的name为null。然后p2将其变量country修改为America,p的变量country也变为了America。

class ArrayTool {
    private ArrayTool(){};
    //若类只有静态方法,要设置私有构造方法,防止创建对象,浪费内存
    public static int getMax(int[] arr){
        int max = arr[0];
        for (int i = 1;i < arr.length ;i++ ){
            if (arr[i] > max){
                max = arr[i];
            }
        }
        return max;
    }
}

上面定义的类中含有static方法,在主函数中可以不创建该类的对象而直接调用方法

class Array_Test {
    public static void main(String[] args) {
        int[] arr = {11,22,33,44,55};
        int max = ArrayTool.getMax(arr);
        }
}

下面的内存分配图可以帮助我们更好的理解static的机制,了解static各个特点的原理


类中静态变量与静态方法内存分配

继承

有时候类与类之间有很多相同的成员变量和方法,倘若全部都要重写,代码的复用性太低,不利于开发。怎么通过类与类之间的联系,减少代码量?继承由此诞生。
JAVA的继承通过extends实现,实现继承的类成为子类,被继承的类成为父类。子类继承了父类,相同的成员变量和方法不需重写便可使用,大大提高了代码的复用性。

class Demo_extends {
    //让类与类之间产生关系,提高代码的复用性,维护性,也是多态的前提
    public static void main(String[] args) {
        Cat c = new Cat();
        c.color = "白";
        c.legs = 4;

        System.out.println(c.color+"..."+c.legs);
    }
}

class Animal{
    String color;
    int legs;
    
    public void sleep(){
        System.out.println("sleep");
    }
}

class Cat extends Animal{
}

通过extends关键字,Cat类继承了Animal类,即使Cat中的代码块为空,仍然可以使用Animal中的成员变量和方法。

class Demo_extends3 {
    public static void main(String[] args) {
        Son s = new Son();          //这是父类构造,这是子类构造
    }                               //在构造子类时会动访问父类构造
}
class Father{
    int num1;
    int num2;
    public Father(){
        System.out.println("这是父类构造");
    }
}
class Son extends Father{
    public Son(){                           //所有的子类构造方法会默认访问父类的无参构造方法
        //super();                          //这是一条语句,没写会自动加上,用来访问父类
        System.out.println("这是子类构造");
    }
}

这种机制在父类对象没有空参构造的时候会出现错误,因为系统默认的super();语句是访问父类的空参构造方法,在这种情况下,要在子类的构造方法中进行处理,即用super语句访问父类的有参构造方法。

class Demo_extends4 {//关于父类没有无参构造的解决方法
    public static void main(String[] args) {
        Son s = new Son(1);
        System.out.println("-----------------");
        Son s2 = new Son();
    }
}
class Father{
    int num;
    public Father(int num){
        System.out.println("父类有参构造");
    }
}
class Son extends Father{
    public Son(){
        super(1);
        System.out.println("子类无参构造");
    }

    public Son(int num){
        super(num);
        System.out.println("子类有参构造");
    }
}

对于在创建的时候,是否会创建父类对象,因为要调用父类构造方法,需要一个实例对象。网上的答案鱼龙混杂,有说要的,有说不要的。但从我查阅的资料看,在创建子类对象的时候不会创建父类对象。

多态

编译和运行的时候产生不同的形态成为多态。

class Demo_Polymorthic {
    public static void main(String[] args) {
        Father f = new Son();
        System.out.println(f.num);          //10
        f.print();                          //Son
        f.speak();                          //fat
    }
}
class Demo_Polymorthic {
    public static void main(String[] args) {
        Father f = new Son();
        System.out.println(f.num);          //10
        f.print();                          //Son
        f.speak();                          //fat
    }
}
class Father{
    int num = 10;
    public void print(){
        System.out.println("Father");
    }

    public static void speak(){
        System.out.println("fat");
    }
}
class Son extends Father  {
    int num = 5;
    public void print(){
        System.out.println("Son");
    }

    public static void speak(){
        System.out.println("so");
    }
}
class Demo_Polymorthic3 {
    public static void main(String[] args) {
        make(new Dog());
        make(new Cat());
    }
    public static void make(Animal a){      //多态常应用于父类作参数,子类方法重写的应用场景
        a.eat();
    }
}
class Animal{
    void eat(){
        System.out.println("动物吃饭");
    }
}
class Cat extends Animal{
    void eat (){
        System.out.println("猫吃鱼");
    }
    void catchmouse(){
        System.out.println("捉老鼠");
    }
}
class Demo_Polymorthic2 {
    public static void main(String[] args) {
        Person p = new SuperMan();
        System.out.println(p.name);             //man
        p.谈生意();                                //谈几个亿的生意
        //p.fly();                              //p实际上就是子类向上提升

        SuperMan sm = (SuperMan) p;             //向下转型
        sm.fly();
    }
}
class Person{
    String name="man";

    public void 谈生意(){
        System.out.println("谈生意");
    }
}
class SuperMan extends Person{
    String name = "sup";

    public void 谈生意(){
        System.out.println("谈几个亿的生意");
    }

    public void fly(){
        System.out.println("去救人");
    }
}

在上面的代码中,父类引用p 指向子类对象superman,所以在正常引用下,superman就伪装成普通人person,调用成员变量,当然是用伪装的名字man,而当调用成员方法使,实际上就是superman在“”谈生意“,而不是普通的person,故表现其真实的行为,即superman重写的谈生意()这一方法,调用结果是“谈几个亿的大生意”。当要用到superman特有的方法fly()时,必须向下转型成superman,无法再伪装了。


多态内存图解

抽象类

抽象,即无法具体的,所谓抽象类,即用abstract修饰符修饰的类。
abstract 修饰的方法,没有方法体,如 abstarct eat();

class Demo_Abstract {
    public static void main(String[] args) {
        Animal a = new Cat();               //通过多态来引用抽象类,抽象类本身无法创造实例
    }
}

abstract class Animal{
    int num1;                                       //抽象类成员变量不能抽象
    final int num2 = 10;
    Animal(){
        System.out.println("抽象类的有参构造"); //抽象类也有构造方法
    }
    abstract void eat();
    public void method(){                       //抽象类可以有非抽象方法,子类继承可以不重写
        System.out.println("抽象类的非抽象方法");
    }
}

class Cat extends Animal{
    void eat(){                             //抽象类使得子类必须重写其抽象方法
        System.out.println("猫吃鱼");
    }
}

抽象类规定了子类必须重写的方法,即规定了子类都必须有的方法,且要求其根据实际重写。

接口

广义上的接口,就是向外提供或者说制定的一种规则,如usb接口,规定了生产接口的厂商应该使用的规格,线路的电压等规则。
在JAVA中接口可以说是抽象类进一步抽象,对实现接口的类制定了特定的规则。

class Demo_Interface {
    public static void main(String[] args) {
        InterA a = new Demo();
    }
}
//设计理念,抽象类是为了规定共性的东西,接口是为了实现扩展性
interface InterA{
    public static final int num = 1;    //接口没有构造方法
    public abstract void printA();      //接口的方法都是抽象方法
}
interface InterB{
    void printB();
}
interface InterC extends InterA,InterB{ //接口可以继承接口,并且是多继承
}
class Demo implements InterC {  //类可以实现多个接口
    public void printA(){;}
    public void printB(){;}
}

关于抽象类和接口的设计理念,抽象类规定了子类共同需要重写的方法,是规定了子类的共性,而接口的多实现,可以使类具有扩展性,如下面的例子

class Demo_Interface2 {
    public static void main(String[] args) {
        Cat c = new Cat();
        c.eat();

        JumpCat j = new JumpCat();
        j.eat();
        j.jump();
    }
}

abstract class Animal{
    String name;
    abstract void eat();
}

interface Jump{
    void jump();
}

class Cat extends Animal{
    public void eat(){
        System.out.println("猫吃鱼");
    }
}

class JumpCat extends Cat implements Jump{
    public void jump(){
        System.out.println("跳高");
    }
}

在抽象类Animal中定义了抽象方法eat();因为所有继承他的子类都具有这一行为,必须根据自身重写该方法。而接口Jump定义了jump();这一抽象方法,不同的类根据自己的需求,是否去实现这一接口,去扩展该类的内容。而且由于接口是多实现的,同一个类可以实现不同的接口,展现于其他类不同的行为。


以上便是今天学习的内容中的要点及最应该注意的地方,其中有什么错误的地方,特别是关于内存的分配方面,由于是自己的理解,可能与实际有偏差,希望读者指出并谅解。

上一篇下一篇

猜你喜欢

热点阅读