深入理解Java中的面向对象

1、类和对象的概念

1>把一类事物的静态属性和动态可以执行的操作组合在一起所得到的这个概念就是类 
2>类的一个个体就是对象,对象是具体的,实实在在的事物 
3>对象是特征与技能的结合体,其中特征和技能分别对应对象的数据属性和方法属性。 
这里写图片描述

2、访问控制符的具体用法

访问控制符的用法包括两种:在类的内部与在类的外部 
1>在一个类的内部,所有的成员之间彼此之间都可以进行相互访问,访问控制符是透明的,失效的,共有的可以调用私有的,私有的可以调用共有的 
2>在一个类的外部,只有其私有成员不可以通过类对象的方式进行访问,共有成员和保护型的成员都可以通过这种方式进行访问,换言之,在一个类的外部,通过类对象名.私有成员的方式是无法访问该对象中的私有成员的 
综上:内部之间可以相互访问,外部私有成员不能进行访问 
示例程序:

package App;

public class App1
{
   public static void main(String[] args2)
   {  
      A aa = new A(2,3);
      aa.fun();
   }    
}

class A
{
    private int i;
    private int j;
    public A(){}
    public A(int i,int j){this.i = i;this.j = j;}
    public void fun()
    {
        System.out.println(this.i+"\t"+this.j);
    }
}

运行结果:

2   3
3、构造函数的概念以及相应的作用

所谓构造函数就是在构造对象的同时被对象自动调用,完成对事物的初始化,一个类只要生成一个类对象,它一定会调用构造函数,并且它永远只会调用一个. 
特点: 
1>构造函数的名字和类的名字相同 
2>构造函数没有返回值 
3>构造函数可以有形式参数,也可以没有形式参数 
4>一个类中可以有多个构造函数 
示例程序:

package App;

public class App1
{
   public static void main(String[] args2)
   {  
       A aa =  new A();
       A bb = new A(2,3);
   }    
}

class A
{
    private int i;
    private int j;
    public A(){System.out.println("自动调用方法!");}
    public A(int i,int j)
    {
         this.i = i;
         this.j = j;
         System.out.println("自动调用方法!");
    }
    public void fun()
    {
        System.out.println(this.i+"\t"+this.j);
    }
}

运行结果:

自动调用方法!
自动调用方法!
4、局部变量与类属性初始化的问题

1>在Java中,如果是个局部变量(在一个函数内部定义的变量或者函数的形式参数),必须进行初始化,否则会出错 
2>类中的属性,如果没有进行初始化,将会被自动赋值. 
示例程序:

package App;

public class App1
{
   public static void main(String[] args2)
   {  
      System.out.println(new A().i);//输出为0
      System.out.println(new A().j);//输出为0
      int i;
      System.out.println(i);
   }    
}

class A
{
    public int i;
    public int j;
    public A(){}
    public A(int i,int j)
    {
         this.i = i;
         this.j = j;
    }
}

运行结果:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
The local variable i may not have been initialized
5、函数的重载(C语言也支持)

同名的函数通过不同的形参列表做类似的或者相同的事情,就叫做函数的重载,即只要函数的功能是类似的或者相同的,统一用一个函数名来进行表示. 
形参列表的不同体现在: 
1>形式参数个数的不同 
2>形式参数数据类型的不同 
3>形式参数顺序的不同 
函数的重载要求这三个至少有一个不同 
函数返回值的不同不能作为函数重载的条件 
示例程序:

package App;

public class App1
{
   public static void main(String[] args2)
   {  
      System.out.println(String.valueOf(66.6));
      System.out.println(String.valueOf(66.6f));
      System.out.println(String.valueOf(66));
      System.out.println(String.valueOf(66L));
   }    
}

运行结果:

66.6
66.6
66
66

实例程序:

public class App1 
{
    public static void main(String[] args)
    {
        Scanner scanner = new Scanner(System.in);
        int a = scanner.nextInt();
        int b = scanner.nextInt();
        int c = scanner.nextInt();

        System.out.println(max(10,20));
        System.out.println(max(10,20,30));
    }
    public static int max(int i,int j)
    {
        return i+j;
    }
    public static int max(int i,int j,int k)
    {
        return i+j+k;
    }
}
6、this关键字的用法

为了辨别此时此刻正在处理哪个对象,this指针变量指向当前时刻正在处理的对象,即new()出来的东西 
在构造方法中this代表的是:this指针变量指向当前时刻正在创建的对象 
构造函数中this.i = i的含义:将局部变量i的数值发送给当前时刻正在创建的对象中的i成员 
示例程序:

package App;

public class App1
{
   public static void main(String[] args2)
   {  
      A  aa = new A(2,3);
      System.out.println(aa.toString());
   }    
}

class A
{
    public int i;
    public int j;
    public A(){}
    public A(int i,int j)
    {
         this.i = i;
         this.j = j;
    }
    public String toString()
    {
        return this.i + "\t" + this.j;
    }
}

运行结果:

2   3
  • 7、利用static统计一个类到底产生出多少个类对象(实用程序)

语法涉及: 
1>如果一个成员前面加一个static,意味着这个成员不再是属于某个类对象的,而是被n个对象所共有的,即静态成员属于类本身的,由操作系统只分配一块内存空间,大家共同使用这一块内存空间,对同一个变量进行操作 
不同的类对象,其属性所占的内存空间不同,但是却公用相同的方法,方法只在代码区分配一块存储空间,大家共同使用这一块内存空间 
2>静态的属性和方法属于类本身的,可以通过类名的方式进行访问 
3>创建完类对象之后,系统首先为这个对象分配好内存空间,然后由类自动调用相应的构造函数 
实例程序:

package App;

public class App1
{
   public static void main(String[] args2)
   {  
        A aa = new A();
        A bb = new A(2,3);
        A cc = new A();
        A dd = new A();
        A ee = new A(2,3);
        A ff = new A();
        System.out.println(A.getCount());
   }    
}

class A
{
    private int i;
    private int j;
    private static int num = 0;//分配一块内存空间
    public A()
    {
        num ++;
    }
    public A(int i,int j)
    {
         this.i = i;
         this.j = j;
         num++;
    }
    public static int getCount()
    {
        return num;//类内部所有成员都可以进行相互访问
    }
}

运行结果:

6
  • 8、static单态涉及模式::要求一个类只能生成一个类对象(实用)

实例程序:静态的成员由操作系统只分配一块内存空间,大家共同使用这一块内存空间,对同一个变量进行操作 
语法:

package App;

public class App1
{
   public static void main(String[] args2)
   {  
           A aa = A.getObject();
           A bb = A.getObject();
           A cc = A.getObject();//返回的是同一个类对象
           if(aa == bb )
               System.out.println("true");
           if(aa == cc )
               System.out.println("true");
           if(bb == cc )
               System.out.println("true");    
   }    
}

class A
{
    private static A  aa = new A();
    private A(){}
    public static A getObject()
    {
          return aa;
    }
}

运行结果:

true
true
true
9、多态的概念

一个父类的引用既可以保存父类对象的地址,也可以保存子类对象的地址,即一个父类的引用它既可以指向父类对象也可以指向子类对象,它可以根据当前时刻指向的不同,自动调用不同对象的方法,这就是多态. 
示例程序:

package App;


public class App1
{
   public static A  aa ;
   public static void main(String[] args2)
   {  
         aa = new A(2,3); //指向父类对象
         aa.fun();
         aa = new B(2,3,4); //指向子类对象
         aa.fun();
   }    
}

class A
{
   public int i;
   public int j;
   public A(){}
   public A(int i,int j)
   {
       this.i=i;
       this.j=j;
   }
   public void fun()
   {
       System.out.println(this.i+"\t"+this.j);
   }
}
class B  extends A
{
    public int k;
    public B(){}
    public B(int i,int j,int k)
    {
        this.i = i;
        this.j = j;
        this.k = k;
    }
   public void fun()
   {
       System.out.println(this.i+"\t"+this.j+"\t"+this.k);
   }
}

运行结果:

2   3
2   3   4
  • 10、A类继承了B类意味着什么?

1>若A类继承了B类,则各种修饰符相应的也被继承了过来 
2>若A类继承了B类,则继承过来的成员相应的也就属于A类本身了

11、同包继承权限的问题

父类的私有成员无法被子类继承,其余的成员都可以被子类继承,即私有成员无法被子类继承 
示例程序:

package App;


public class App1
{
   public static void main(String[] args2)
   {  
        A aa = new A();
        System.out.println(aa.i);
        System.out.println(aa.j);
        //System.out.println(aa.k);父类的私有成员无法被子类继承
        aa.fun();
   }    
}

class A
{
   public int i;
   protected int j;
   private int k;
   public A(){}
   public A(int i,int j,int k)
   {
       this.i = i;
       this.j = j;
       this.k = k;
   }
   public void fun()
   {
       System.out.println("AAAA");
   }
}
class B  extends A
{
   public void fun()
   {
       System.out.println("AAAA");
   }
}

运行结果:

0
0
AAAA
12、super关键字的使用

super关键字产生的原因:子类可以继承父类除私有成员以外的所有成员,但是子类永远无法继承父类的构造方法,在子类的构造方法中通过使用super关键字来调用父类的构造方法 
super语句的三个注意事项: 
1>每个子类构造方法中的第一条语句,都是隐含的调用super()语句 
2>如果显示的写出super语句,则必须保证该语句是子类构造方法中的第一条语句,并保证父类中有相应参数的构造方法,否则会出错 
3>通过super调用父类的构造方法只放在子类的构造方法中,不能放在普通方法中,并且该语句只能放在子类构造方法中的第一条语句 
示例程序:

package App;


public class App1
{
   public static void main(String[] args2)
   {  
        B  bb = new B(1,2,3,4);
        System.out.println(bb.i+"\t"+bb.j+"\t"+bb.k+"\t"+bb.l);
   }    
}

class A
{
   public int i;
   public int j;
   public int k;
   public A(){}
   public A(int i,int j,int k)
   {
       this.i = i;
       this.j = j;
       this.k = k;
   }
}
class B  extends A
{
   public int l;
   public B(){}//隐含着调用A()
   public B(int i,int j,int k,int l)
   {
//     this.i = i;
//     this.j = j;
//     this.k = k;
       super(i,j,k);//理解为调用A(i,j,k);
       this.l = l;
   }
}

运行结果:

1   2   3   4
13、方法重写的概念

定义:方法重写指在子类中重新定义父类中已有的方法,但是方法重写仅仅是函数修饰符与函数执行体的改变而已 
要求:重写方法与被重写方法要求:同名,同参,同返回值,访问权限不能更加严格(因为多态);仅仅是函数修饰符与函数执行体的改变而已 
[若两个函数只有函数返回值不同,则编译时会出错] 
实例程序:

package App;


public class App1
{
   public static void main(String[] args2)
   {  
       A aa =  new A(1,2,3);
       System.out.println(aa.toString());
   }    
}

class A
{
   public int i;
   public int j;
   public int k;
   public A(){}
   public A(int i,int j,int k)
   {
       this.i = i;
       this.j = j;
       this.k = k;
   }
   public String toString()
   {
       return this.i+"\t"+this.j+"\t"+this.k;//重写Object类中的toString()方法
   }
}

运行结果:

1   2   3
14、多态的两个注意事项

1>通过父类的引用只能访问子类对象从父类继承过来的成员,但是不能访问子类对象所特有的成员(父类引用强制转化为子类的引用的原因) 
2>父类的引用永远不可能直接赋给子类引用,否则会出错,只有在父类的引用本身指向的就是子类对象的时候,才可以将父类引用强制转化为子类的引用(其它情况下不允许将父类的引用强制转化为子类的引用,否则运行的时候会出错)

实例程序:

package App;

import java.awt.List;
import java.util.ArrayList;
import java.util.Collections;


public class App1
{
   public static ArrayList aa;
   public static void main(String[] args2)
   {  
        aa = new ArrayList<Student>();
        aa.add(new Student("lisi",88.8));
        aa.add(new Student("zhangsan",98.8));
        aa.add(new Student("wangwu",66.6)); 
        Collections.sort(aa);
        System.out.println(aa);
   }    
}


class  Student  implements Comparable
{
    public String name;
    public double score;
    public Student(){}
    public Student(String name,double score)
    {
        this.name = name;
        this.score = score;
    }
    public int compareTo(Object obj)//父类的引用obj此时指向了子类的对象Student
    {
        Student cc = (Student)obj;//在父类的引用指向子类对象的前提下,将父类的引用强制转化为子类的引用
        /**之所以要将父类的引用强制转化为子类的引用,主要是因为父类的引用不能调用子类所特有的成员****/
        if(this.score>cc.score)
            return 1;
        else if(this.score < cc.score)
            return -1;
        else 
            return 0;       
    }
    public String toString()
    {
        return this.name + "\t" + this.score;
    }
}

运行结果:

[wangwu 66.6, lisi  88.8, zhangsan  98.8]
15、抽象类与抽象方法

抽象类是为了更好的对类加以分类,抽象类通常情况下是作为一个类族的最顶层的父类,如植物,并用最底层的类来描述现实世界中的具体的事物. 
1>没有执行体的方法叫做抽象方法,抽象方法要求末尾必须得加分号,前面必须得加abstract进行修饰 
如public abstract void fun1(); 
2>抽象方法通过子类的实现可以变成普通的方法 
3>抽象方法不存在所谓重写的问题,却存在着实现的问题 
4>含有抽象方法的类一定是抽象类,但是抽象类不一定含有抽象方法,此时也就没有什么意义了 
实例程序:

abstract class A//抽象类
{
   public int i;
   public int j;
   public int k;
   public A(){}
   public A(int i,int j,int k)
   {
       this.i = i;
       this.j = j;
       this.k = k;
   }
   public abstract void dat();//抽象方法
   public void fun()//普通方法
   {
       System.out.println(i+j+k);//方法体
   }
}
16、接口的概念

接口就是抽象方法与数值型常量的集合,接口里面只能有一些抽象方法与数值型常量,不能有普通方法,接口本质上就是一个更加严格,更加特殊的抽象类,不能在定义一个子类去继承它,即接口只能被实现,不能被继承. 
注意:接口中的方法只能被public abstract修饰符修饰,接口中的常量只能被public static final修饰符修饰.(两者可以省略) 
实例程序:

interface A
{
    int i = 5;//数值型常量<--> public static final int i = 5;
    void fun();//抽象方法<-->  public abstract void fun();
}
17、接口与抽象类的区别

1>接口可以近似的当做一个抽象类,但是却不是抽象类,更不是类,接口只能被一个类实现,但是抽象类却可以被一个类继承 
2>接口中的方法不允许有方法体,但是抽象类中的方法却允许有方法体 
3>接口可以实现多继承,但是抽象类只能实现单继承

18、final关键字

含义:最后的,最终的,表示这个事物已经很完美了. 
用途:1>用final来修饰整个类:若一个类的前面加上一个final,表示这个类已经很完美了,不能再定义一个子类去继承它,进行相应的修改,否则会出错 
用途:2>用final来修饰类中的成员,即属性与方法:在一个类中,若一个方法的前面加上一个final,表示这个方法已经很完美了,虽然该方法可以被子类继承,但是不能被子类重写,否则会出错;用final修饰过的变量叫做常变量,此时java中的final相当于c语言中的const,表示该变量必须被赋值,并且只能被赋一次值,从此以后数值不能再发生更改;因此用final来修饰类中的若干个属性表示该属性必须被赋值并且只能被赋一次值,注意默认值不算真正的赋值,但是在子类当中可以修改final修饰过的变量,这一点与final修饰过的方法不同 
注意:在一个类的普通方法内部不可以修改final修饰过的成员变量的数值

 

posted @ 2018-04-10 22:59  vegatate  阅读(187)  评论(0编辑  收藏  举报