java学习笔记第二章

二、面向对象 Oriented Object

以类组织代码,以对象来封装数据

 

面向过程:以方法(函数)组织数据,以线性的思维去解决;当数据量少,无问题;当数据多了,方法多了,以

     方法为核心组织代码,累人;扩展性差,不易维护(当多人协同项目时)

C语言结构体,多个变量集合在一块,方便管理;按照这个想法,横向竖向扩散/深入思考,把相近的方法也放在一起,方法反复调用变量,

              深度发散,就把方法及变量打包到一块,这种概念在C语言里没有,就起名叫做类 class 【 YY】

以类来组织代码,易于维护,易于扩展

1000个变量 + 1000个方法   ----->  50个类 

面向对象优势仅来自软件的复杂性,要是简单的话,就没有必要,用面向过程实现就可以

 

面向对象的思考方式:  以如何开汽车为例来阐述

面向过程:(事物比较简单,用线性思维去思考解决问题;跟把大象关进冰箱一样)

1.踩离合

2.挂档

3.踩油门,放离合

4.开了

面向对象:多角色,协作完成(思考这些过程要哪些对象)

对象:驾驶员、汽车

驾驶员开汽车

开车细节放在汽车下的方法, car.start(); 来实现

如何造汽车?

面向对象思维:轮胎、座椅、发动机、车架......,将上面造出的东西,组装起来,汽车造出

 

面向对象思维把握整体,面向过程实现局部细节

 

面向对象编程(OOP)的本质:以类的方式组织代码,以对象的方式组织(封装)数据

面向对象思维:OOA, OOD

对象:是具体的事物

类:是对对象的抽象,(抽象,抽出象的部分),类是对象的模板。 典型案例:数学 1-10 (1-10个人,1-10个苹果,1-10个等等)

现实的逻辑用代码来实现,静态的数据、动态的行为

 

===================================================================

JAVA语言中除基本类型之外的变量类型,都称之为引用类型;java对象是通过引用reference(地址)对其操作的

未赋值,默认初始化值

数值型:

--整型:0

--浮点型:0.0

--char型:\u0000

--boolean型:0   false

--字符串 null

属性(成员变量、静态数据);方法(动态行为),方法隶属于类

 

成员/实例变量、局部变量

局部变量必须初始化,成员/实例变量未赋值,系统采用默认值初始化

 

=======================程序执行过程的内存分析(初步分析浅,等待后期改进)====================

栈、堆、方法区

1.栈

自动分配连续的空间,后进先出

存放:局部变量

2.堆

空间不连续

存放:new出来的对象

3.方法区(在堆里划出一部分空间)

存放:类的信息(代码)、static变量、常量池(字符串常量)等

栈帧的概念 ? ?    //后期补充

JVM在内存中未找到类,会从classpath里加载类,找到class文件,JVM通过类加载器class loader来加载类,加载后,在方法区就有student信息

操作对象,就是操作它的地址,引用类型4个字节

垃圾回收机制(Garbage Collection);空间分配,new对象;对象空间释放:GC回收没有被引用的对象

 

===============================构造器===================================

构造器又称构造方法constructor

格式如下:

[修饰符] 类名 (形参列表) {

  //n条语句

}

 构造方法是一种特殊的方法:

1.通过new来调用 

2.定义时无需定义返回值;不能再构造器使用return语句

3.构造器的方法名必须和public class类名一致

4.如果没有定义构造器,编译器会在编译过程中自动构造一个无参构造器;如果已定义,则编辑器不会添加

5.初始化构造该类的对象

 1 Car.java:
 2 public class Car {
 3     int speed;
 4     public Car(){
 5         System.out.println("构造一个车");
 6     }
 7 }
 8 
 9 TestConstructor.java
10 public class TestConstructor {
11     public static void main(String[] args) {
12         Car c = new Car();        
13     }
14 }
15 
16 编译执行结果:
17 构造一个车
18 构造类Car通过new来调用,同时也初始化对象c

============================方法重载 & 构造方法的重载===============================

重载(overload):最主要是调用时不会产生歧义(编译器不知道调用哪个?)

方法的重载是指一个类中可以定义有相同的名字,但参数不同的多个方法;调用时,会根据不同的参数表选择对应的方法

两同三不同

--两同:同一个类,同一个方法名

--三不同:参数列表不同(类型、个数、顺序不同)

只有返回值不同是不能构成方法的重载:int a(String str){} / void a(String i){},当调用a(String c),会产生歧义,不知道调用哪个?

只有形参名称不同,也不能构成方法的重载:int a(int b){} / int a(int c){},调用a(int d)会产生歧义

与普通方法一样,构造方法也可以重载;重载条件跟普通方法一致

 1 public class TestOverload {
 2     public int add(int a, int b){
 3         return a+b;
 4     }
 5     public static void main(String[] args) {
 6         MyMath m = new MyMath();
 7         int result = m.add(4.2,8);
 8         System.out.println(result);
 9     }
10 }
11 
12 class  MyMath {
13     int a;
14     int b;
15     
16     public MyMath(){
17     }
18 
19     public MyMath(int a){
20         this.a = a;
21     }
22     
23     public MyMath(int b, int a){
24         this.b = b;
25         this.a = a;
26     }
27     
28     public int add(int b, double a){
29         return (int)(a+b);
30     }
31     
32     public int add(double a, int b){
33         return (int)(a+b);
34     }
35     
36     public int add(int a, int b){
37         return a+b;
38     }
39     
40     public int add(int a, int b,int c){
41         return a+b+c;
42     }
43 
44 }

====================================static静态===================================
在类中,用static声明的成员变量称为静态成员变量,或者叫做:类属性,类变量

--它为该类的公用变量,属于类,被该类的所有实例(对象)共享,在类被载入时被显式初始化

--对于该类的所有对象来说,static成员变量只有一份,被该类的所有对象共享

--可以使用“对象.类属性”来调用,不过,一般都是用“类名.类属性”

--static变量置于方法区中

用static声明的方法称为静态方法

--不需要对象,就可以调用(类名.方法名)

--在调用该方法时,不会将对象的引用传递给它,所以在static方法中不可访问非static的成员

 

静态初始化块:

如果希望加载后,对整个类进行初始化操作,可以使用static初始化块;是在类初始化时执行,不是在创建对象时执行

静态初始化块不能访问非static成员

执行顺序:上溯到Object类,先执行Object的静态初始化块,再向下执行子类的静态初始化块,直到我们的类的静态初始化块为止

 

静态的方法里不能调用非静态的内容

非静态的方法可以调用静态变量及静态方法

 

从属于类的方法,不能调用对象内容,对象里没有static

Student.java
public class Student {
     String name;
     int id;   
     
     static  int  ss;
     
     public static void printSS(){
         System.out.println(ss);
     }
     
     public void study(){
         printSS();
         System.out.println(name+"在學習");
     }
     
     public void sayHello(String sname){
         System.out.println(name+""+sname+"說:你好!");
     }

}

Test.java
public class Test {
    public static void main(String[] args) {
        Student.ss = 323;    //类变量,一般都是用“类名.类属性”
        Student.printSS();
        
        Student s1 = new Student();
    }
}

===========================================this=========================================

this用于方法里面,但不能用于static方法里;this隐式参数,jvm调用时会传this参数,方法里可以使用this

普通方法:this总是指向调用该方法的对象

构造方法:this总是指向正要初始化的对象

隐式参数:this  super

this();调用其它构造器方法,必须放在第一句

Student.java
public class Student {
     String name;
     int id;   
     
     public  Student(String name,int id){
         this(name);   //通过this调用其他构造方法,必须位于第一句! Constructor call must be the first statement in a constructor
         this.name = name;
         this.id = id;
     }
     
     public Student(String name){
         this.name = name;
     }
     public Student(){
         System.out.println("构造一个对象");
     }
     
     public void setName(String name){
         this.name = name;
     }
          
     public void study(){
         System.out.println(this.name);
         this.name=  "张三";
         System.out.println(name+"在學習");
     }
     
     public void sayHello(String sname){
         System.out.println(name+""+sname+"說:你好!");
     }
}

Test.java
public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Student s1 = new Student();
        s1.name = "李四 ";
        s1.study();
        
    }

}
执行结果:
构造一个对象
李四 
张三在學習

构造方法:this总是指向正要初始化的对象
普通方法:this总是指向调用该方法的对象
this的引用地址<--->new对象的引用地址

 

面向对象三大特征:

===================================继承======================================

OOD角度上看,类是对对象的抽象,继承是某一批类的抽象,从而实现对现实世界更好的建模         //inherited

OOP角度上看,提高代码的复用性

extends “扩展” 子类是对父类的扩展  (class  a  extends b)

子类继承父类,可以使用父类的全部属性和方法(除父类的构造器外)

java类只有单继承,利于维护(例如:只有一个直属上级,无多个)

java中的多继承,可以通过接口interface实现

如果定义一个类时,没有调用extends,则它的父类是java.lang.Object(根类)

 

方法的重写: 当从父类继承下来的方法不合适,就需要进行方法的重写;方法的重写跟方法的重载无任何关系

(阅读源代码,需要转换下思维;中文:亚洲、中国、北京、大兴区、街道 |  英文:街道、大兴区、北京、中国、亚洲;

鼠标停留到要查看的类,按住CTRL,跳到类文件里,用来查看源代码;Ctrl + T,查看源码层次)

重写的方法必须跟被重写具有相同的方法名称,参数列表和返回类型

隐式参数:  this,super    public void run (this,super) {};

this:当前对象的引用(地址)

super:指向父类对象的引用(地址),通过super访问父类的属性或值

构造方法:所有的构造方法,第一句super,调用父类的构造器,除了Object类;如果不加,编译器自动添加

 1 Bird <-- Animal <-- Object类
 2 
 3 Animal.java
 4 public class Animal {
 5     String eye;
 6     
 7     public void run(){
 8         System.out.println("跑跑!");
 9     }
10     public void eat(){
11         System.out.println("吃吃!");
12     }
13     public void sleep(){
14         System.out.println("zzzzz");
15     }
16     
17     public  Animal(){
18         super();         //通过super可以调用父类的构造器
19         System.out.println("创建一个动物!");
20     }
21     
22 }
23 
24 class Bird  extends Animal {    //extends关键字 继承
25     public void run(){
26         //this.run();
27         super.run();
28         System.out.println("我是一个小小小小鸟,飞呀飞不高");
29     }
30     
31     public void eggSheng(){
32         System.out.println("卵生");
33     }
34     
35     public Bird(){
36         super();
37         System.out.println("新建一个鸟对象");
38     }
39     
40 }
41 
42 Test.java
43 public class Test {
44 
45     public static void main(String[] args) {
46         // TODO Auto-generated method stub
47         Bird b = new Bird();
48         b.run();
49     }
50 }
51 
52 执行结果:
53 新建一个鸟对象             //构造器初始化
54 跑跑!                        //super调用父类
55 我是一个小小小小鸟,飞呀飞不高   
56             

继承 VS 组合
从代码复用角度来看,组合完全可以替代继承,组合比继承更灵活;组合,把父类放在子类里,这样子类就可以使用父类的方法和属性

从建模角度来看,继承是继承,组合是组合;

组合的样例:

 1 public class Animal2 {
 2     String eye;
 3     
 4     public void run(){
 5         System.out.println("跑跑!");
 6     }
 7     public void eat(){
 8         System.out.println("吃吃!");
 9     }
10     public void sleep(){
11         System.out.println("zzzzz");
12     }
13     
14     public  Animal2(){
15         super();
16         System.out.println("创建一个动物!");
17     }
18     
19     public static void main(String[] args) {
20         Bird2 b = new Bird2();
21         b.run();
22         b.animal2.eat();  //子类调用父类的方法
23     }
24     
25 }
26 
27 class Bird2  {
28     Animal2 animal2=new Animal2();//组合,把父类放在子类里,这样子类可以使用父类的方法及变量
29     
30     public void run(){
31         animal2.run();
32         System.out.println("我是一个小小小小鸟,飞呀飞不高");
33     }
34     
35     public void eggSheng(){
36         System.out.println("卵生");
37     }
38     
39     public Bird2(){
40         //super();
41         System.out.println("建一个鸟对象");
42     }
43 }

final 关键字
--修饰变量:常量

--修饰方法:该方法不可被子类重写,但可以重载

--修饰类:不能有子类,不能被继承;比如Math类,String类

final不能被修改

 1 public /*final*/ class Animal {    //final修饰类则说明,这个类不能被继承!
 2     
 3     public /*final*/ void run(){   //final加到方法前面,意味着该方法不能被子类重写!
 4         System.out.println("跑跑!");
 5     }
 6 
 7 }
 8 
 9 class Bird  extends Animal {
10     
11     public void run(){
12         super.run();
13         System.out.println("我是一个小小小小鸟");
14     }
15     
16 }
17 测试final
18 public class TestFinal {
19     public static void main(String[] args) {
20         final int MAX_VALUE= 200;    //常量
21         double d = Math.PI;
22     }
23 }

===================================封装/隐藏encapsulation=======================================
为什么需要封装?封装的作用和含义?

比如:电视只需要了解怎么使用,不需要了解内部信息

隐藏对象内部的复杂性,只对外公开简单的接口,便于外界调用,从而提高系统可扩展性、可维护性

哪些方法、类、属性封装?哪些开放?怎么实现?

private

default

protected

public

常用是private和public

成员变量全部私有,静态变量、常量可以公开

提供相应get/set方法来访问相关属性,这些方法通常是public,从而提供接口

 1 public class Man {
 2     private String name;
 3     private String id;
 4     private boolean man;
 5     public static int cc;
 6     public static final int MAX_SPEED = 120;
 7         
 8     public String getName(){
 9         return name;
10     }
11     public void setName(String name){
12         this.name = name;
13     }
14     public String getId() {
15         return id;
16     }
17     public void setId(String id) {
18         this.id = id;
19     }
20     public boolean isMan() {
21         return man;
22     }
23     public void setMan(boolean man) {
24         this.man = man;
25     }
26     
27 }

================================多态Polymorphism=======================
多态是为了适应需求的多种变化,使代码变得更加通用

多态的存在3个必要条件:

继承、方法的重写(方法的多态)、父类引用指向子类对象 eg:Animal a = new Cat();

多态性是OOP中的一个重要特性,主要是用来实现动态联编的,换句话来讲,就是程序的最终状态只有在执行过程中才被决定而非在编译期间,这对于大型系统来说能提高系统的灵活性和扩展性

如何实现多态?使用多态的好处?

引用变量的两种类型:

--编译时类型(父类定义宽广些,模糊点),由声明的类型决定

--运行时类型(运行时,具体是哪个子类就是哪个子类),由实际对应的对象类型决定

在调用时,有时需要强制转型: Cat a2 = (Cat)a; 或instanceof用于强制转换

 1 Animal.java
 2 public class Animal {
 3     String str;
 4     public void voice(){
 5         System.out.println("普通动物叫声!");
 6     }
 7 }
 8 
 9 class Cat extends Animal {
10     public void voice(){
11         System.out.println("喵喵喵");
12     }
13     public void catchMouse(){
14         System.out.println("抓老鼠");
15     }
16 }
17 
18 class Dog extends Animal {
19     public void voice(){
20         System.out.println("汪汪汪");
21     }
22     
23     public void seeDoor(){
24         System.out.println("看门!");
25     }
26     
27 }
28 
29 Test.java
30 public class Test {
31     
32     public static void testAnimalVoice(Animal c){
33         c.voice();
34         if(c instanceof Cat){
35             ((Cat) c).catchMouse();
36         }
37     }
38 
39     public static void main(String[] args) {
40         Animal a = new Cat();
41         Cat a2 = (Cat)a;            //强制转换,否则无法调用catchMouse方法
42         a2.catchMouse();
43         testAnimalVoice(a);
44 
45     }
46 }

Servlet:服务器端小程序,本质是一个类

 1 HttpServlet.java
 2 
 3 public class HttpServlet {
 4     public void service(){
 5         System.out.println("HttpServlet.service()");
 6         this.doGet();
 7     }
 8     
 9     public void doGet(){
10         System.out.println("HttpServlet.doGet()");
11     }
12 }
13 
14 MyServlet.java
15 
16 public class MyServlet extends HttpServlet {
17     
18     public void doGet(){
19         System.out.println("MyServlet.doGet()");
20     }
21     
22 }
23 
24 A.javapublic class A {
25     public static void main(String[] args) {
26         HttpServlet s = new MyServlet();
27         s.doGet();
28         s.service();
29     }
30 
31 }
32 运行结果:
33 MyServlet.doGet()
34 HttpServlet.service()
35 MyServlet.doGet()

=========================================抽象Abstract=======================================
抽象类,为什么需要抽象类?如何定义抽象类?

--是一种模板模式;抽象类为所有子类提供了一个通用模板,子类可以在这个模板基础上进行扩展

--通过抽象类,可以避免子类设计的随意性;通过抽象类,我们就可以做到严格限制子类的设计,使子类之间更加通用

要点:

1.有抽象方法的类,只能定义为抽象类

2.抽象类不能实例化,及不能用new来实例化抽象类;未抽象的子类可以new实例化,子类指向父类,引用父类

3.抽象类可以包含属性、方法、构造方法

4.抽象类无对象建立,只能被继承;一个抽象类可以继承另一个抽象类

5.抽象方法必须被子类实现  (父类定义规范,子类必须实现;比如父类定义run(),子类必须重写方法run)

 

抽象方法只有方法声明,无方法体

public abstract void run();   //抽象方法,只有声明,没有实现,具体实现由子类完成

子类必须定义run方法

@Override         //重写

public void run(){

  System.out.println("gogo");

}

 1 Animal.java
 2 public abstract class Animal {
 3     String str;
 4     public void breath(){
 5         System.out.println("breath");
 6     }
 7     public abstract void run(); //只有声明,无方法体
 8     public Animal(){
 9         System.out.println("chaungjainyigezhongduw");
10     }
11 }
12 
13 /*abstract*/ 
14 class Cat extends Animal {
15     //不定义,由父类提供,不规范
16     @Override
17     public void run() {
18         System.out.println("miao");
19     }
20 }
21 class Dog extends Animal {
22     //不定义,由父类提供,不规范
23     @Override
24     public void run() {
25         System.out.println("汪汪");
26     }
27 }
28 
29 Test.java
30 public class Test {
31     public static void main(String[] args){
32         Animal a = new Cat();
33         a.run();
34     }
35 }

 =================================Interface==============================                                                                                                                                                                                                                                                                                                                                     

接口Interface:只有声明,没有实现,比抽象类还要抽象的类,

一个类可以实现多个接口

定义接口,格式:

[访问修饰符] interface 接口名 [extends 父接口1,父接口2..]{

  常量定义   // public static final

  方法定义   // public abstract

}

子类通过implements实现接口中的规范

interface无法new实例化,可以用于声明引用变量类型

一个类实现接口,必须实现接口中的所有方法,并且这些方法只能是public的;接口支持多继承

为什么需要接口?接口和抽象类的区别?

--接口就是比“抽象类”还“抽象”的“抽象类”,可以更加规范的对子类进行约束。全面专业地实现了:规范和具体实现的分离

--接口就是规范,定义的是一组规则,体现了现实世界中“如果你是...则必须能..."的思想。eg:如果你是天使,必须会飞

--接口的本质是契约,就像我们人间的法律一样,制定好后大家都遵守

--项目的具体需求是多变的;开发项目往往都是面向接口的编程

 1 MyInterface.java
 2 public interface MyInterface {
 3     //接口中只有:常量、抽象方法!
 4     //public static final String MAX_GREAD = "BOSS";
 5     String MAX_GREAD = "BOSS";
 6     int MAX_SPEED =  120;
 7     
 8     public void test01();
 9     public int test02(int a,int b);
10     
11 }
12 
13 interface InterfaceC extends MyInterface {
14     //接口可以继承
15 }
16 
17 MyClass.java
18 public class MyClass implements MyInterface {
19     //接口里的方法必须被重写
20     @Override
21     public void test01(){
22         System.out.println("test01");
23     }
24     
25     @Override
26     public int test02(int a,int b){
27         return (a+b);
28     }
29 }
30 
31 Test.java
32 public class Test {
33     public static void main(String[] args){
34         //接口无法new
35         MyInterface a = new MyClass();  
36         a.test01();
37     }
38 }

 

posted on 2016-01-19 16:10  lucifer179  阅读(226)  评论(0编辑  收藏  举报

导航