Java学习笔记一

一、面向对象编程(OOP

目标(goal):与面向过程编程相比,是为了在解决现实问题时,以问题为核心,建立对问题结构的考虑,而不是将问题的解决基于计算机的结构、程序员必须建立机器和实际待解决问题之间的关联。

特性(feature):抽象性(类和对象)、封装性、继承性、多态性

抽象性和封装性——对问题空间的抽象是面向对象的核心,人们所能够解决的问题的复杂性直接取决于抽象的类型和质量。Bruce告诉我们的抽象原则是,将问题肢解成一小块儿一小块儿,然后针对每一小块儿去构想一个角色,该角色就是能够解决该一小块儿问题的对象,然后确定了该对象应该提供什么服务及具备什么属性后,便可将其封装成类。

访问控制的意义:当把程序员按角色分成类创建者和类使用者后,通过访问控制将类内部构造完全对类使用者屏蔽,这样,一方面,类创建者对内部进行修改,只要保证对类使用者公开的接口保持不变,便不影响其正常使用,另一方面,类使用者无法在不知情的情况下破坏类内部脆弱的部分,从而可以减少程序的BUG。Java除了pulic、private和protected三个访问控制词外,还包含包的访问权限。

继承性——“是一个”表示继承后覆盖基类的方法,“像一个”表示继承后在子类中增加基类没有的方法,部分继承可通过private来控制。

多态性——通过后期绑定实现将子类对象当作其泛化基类型对象来看待,从而达到功能的扩展不更改或者尽量少的更改原有代码,进一步降低维护的成本。

在对对象的数量和生存周期没有确切的把握时最好使用范型容器

除了基本类型外,Java中对象都是通过new创建在堆上的,且有垃圾回收器来处理内存释放问题

Java中异常处理是强制的

Java提供了很多库来支持多线程,为了提高程序的响应能力,比如用户界面响应与后台处理的多任务执行

在“Java与Internet”一节中,Bruce以选择什么样的解决方案为引子简单介绍了Java在B/S模式中的应用及优势,其中涉及到的Java的元素有Java applet(客户端编程)、Java Web Start(客户端编程)、Java servlet(服务器端编程)

最后的结论是:根据问题的实际情况来选择什么样的编程语言、选择采用什么样的技术提供合理的解决方案 

二、构建Java类和Java程序

第二章的标题是“一切都是对象”,Bruce按照声明对象->定义类->构建Java程序的顺序,介绍了不少细节,现将这些知识点梳理如下:

个人总结的思路是(1)定义类->(2)实例化对象->(3)调用对象的方法(向对象发送消息)

1)定义类

[访问修饰符]  class  类名  {

      [访问修饰符]  [静态修饰符]  类型  成员变量名;                                 //定义成员变量(字段)

      [访问修饰符]  [静态修饰符]  返回值类型  成员函数名(参数列表){       //定义成员函数(方法)

             //方法体

      }

}

Java中,如果成员变量为基本数据类型,在其定义时若未指定初始值,Java也会确保它获得一个默认值,此特点不适用于局部变量。

2)实例化对象

实例化对象分两部分:定义对象的引用,为对象分配内存空间;两部分可以一起进行,也可以分开进行,例如:

String s = new String("abc");   或者

String s;

s = new String ("abc");

引用和指针的相同与不同:二者的相同之处是都指向一块内存,其内容都是内存的地址;但引用的地址在初始化后是没法改变的,而指针是可以重新指定其他内存地址。

通过new的方式为对象分配内存,该内存空间具体指的是堆,Java中有垃圾回收器,不需要再去考虑内存释放的问题。

3)调用对象的方法

在对对象进行实例化后,为了完成具体的功能,便需要调用对象的方法,调用方式是:

对象名.方法名(参数列表);

了解了上述内容还无法构建一个完整的Java程序,下面结合一个具体的实例补充其他重要的内容:

//Main.java
import java.util.*;
import java.lang.System;  //其实这个是自动导入的,这里写出的目的是为了后面对import的描述
/** The first example program.
 *   Display a string and today's date.
 *   @author :pickuper
 *   @version:1.0
 */
public class Main{
    public static void main(String[] args){
        HelloJava hello = new HelloJava();
        hello.printContent();       
    }
}
 
public class HelloJava{
    public void printContent(){
        System.out.println("HelloJava");
        System.out.println(new Date());
    }
} 

(1)命名自定义类库(包):使用反转域名,使得命名空间唯一。

(2)使用其他类库:通过import导入包,格式参见示例程序,*是通配符,表示包含上级目录包含的全部类。

(3)static:一般情况下,属性和方法是依赖于对象的,即有了实例化的对象,才有了对象的属性,才能调用对象的方法;但用static声明类属性和方法后,二者便不再依赖于对象:对于static属性来说,一个类对应一个属性,即多个对象共享一个数据空间,而static方法则可以通过类名来调用,不需要引用对象名。

(4)注释与javadoc:后面进行详细介绍。

三、初始化与清理

3.1、初始化

      初始化其实就是为变量分配内存空间,并确定其初始值的过程。想了解Java中初始化的各种情况,首先要了解Java中变量的类型。根据自己的理解,将Java中的变量类型分成以下几种,虽然可能不太准确,但只是为了方便理解把握:

      1)局部变量:内存空间被分配在堆栈上;一般是在方法中定义的变量;其初始化操作是必须的,否则编译器会报错,初始化操作有两种方式:一种是在定义的时候初始化其值,另一种是定义和初始化值分开,如下面所示:

int a = 6;//或者

int a;a = 6;

 

2)静态成员变量(static变量或者类变量):内存空间被分配在堆上,而且只占一份存储区域,即多个实例共享一个static变量;局部变量不能被声明为静态变量;它的初始化操作是可选的,如果不人为对其进行初始化,它将会被自动初始化,人为初始化操作是在定义时对其进行赋值;其初始化过程只在类第一次实例化或者第一次调用静态方法的时候完成的。

3)非静态成员变量(普通成员变量):内存空间被分配在堆上;初始化操作也是可选的,如果不人为初始化则会被自动初始化,初始化操作是在定义时对其赋值。

4)引用变量(对象变量):即类的实例;是通过new的方式在堆上分配内存空间的;与C++不同,Java中不允许有局部对象变量;在被new完后,类的构造器被调用,从而完成初始化过程;如果在定义类时没有定义构造器,则默认构造器会在初始化过程中被调用,构造器还可以被重载,通过参数列表的不同来区分不同的构造器。

      Java中,类在实例化后,其初始化的顺序通过下面的例子来直观说明:

package com.exercise; 
import java.awt.peer.SystemTrayPeer; 
class A {
    public A(int i) {
        System.out.println("A"+i+" was created!");
    }
} 
class B {
    public B(int i) {
        System.out.println("Static B"+i+" was created!");
    }
} 
class BaseClass {
    A a = new A(1);
    static {
        System.out.println("BaseClass's first static block was execute!");
    }
    static B b = new B(2);
    static {
        System.out.println("BaseClass's second static block was execute!");
    }
    public BaseClass() {
        System.out.println("BaseClass's constructor was called!");
    }
    A aa = new A(3);
    static B bb = new B(4);
}
 
class ChildClass extends BaseClass {
    A aaa = new A(5);
    static {
        System.out.println("ChildClass's first static block was execute!");
    }
    static B bbb = new B(6);
    static {
        System.out.println("ChildClass's second static block was execute!");
    }
    public ChildClass() {
        System.out.println("ChildClass's constructor was called!");
    }
    A aaaa = new A(7);
    static B bbbb = new B(8);
}
 
public class Test {
 
    /**
     * @param args
     */
    public static void main(String[] args) {
        System.out.println("Enter the main function!");
        ChildClass childClass = new ChildClass();
        System.out.println("Leave the main function!");
    }
}

运行结果如下:

Enter the main function!
BaseClass's first static block was execute!
Static B2 was created!
BaseClass's second static block was execute!
Static B4 was created!
ChildClass's first static block was execute!
Static B6 was created!
ChildClass's second static block was execute!
Static B8 was created!
A1 was created!
A3 was created!
BaseClass's constructor was called!
A5 was created!
A7 was created!
ChildClass's constructor was called!
Leave the main function!

根据运行结果可以看出,初始化顺序是

      1、父类静态成员变量和静态初始化块,按在代码中出现的先后顺序

      2、子类静态成员变量和静态初始化块,按在代码中出现的先后顺序

      3、父类非静态成员变量,按在代码中出现的先后顺序

      4、父类构造器

      5、子类非静态成员变量,按在代码中出现的先后顺序

      6、子类构造器

3.2 清理      

Java中提供了垃圾回收器用于自动回收在程序中通过new创建的内存空间,垃圾回收不能保证不用的内存空间立刻就能得到释放,如果程序对性能要求较高的话,可能要自己创建清理函数,然后在需要的时候调用。      除了通过new方式分配内存空间,有时候可能调用了“本地方法”分配了内存空间(如调用C语言中的malloc()),针对类似的情况,Java中提供了finalize()方法来处理这类情况的内存回收,一般finalize()有用武之地的情况是,用于验证对象终结条件,从而发现潜在的缺陷。例如如下代码(摘自《Java编程思想》):

class Book {
      boolean checkedOut=false;
      Book(boolean checkOut) {
           checkedOut=checkOut;
      }
      void checkIn() {
           checkedOut=false;
      }
 
      protected void finalize() {
           if(checkedOut)
                System.ouy.println("Error:checked out"); 
                //Normally,you'll also do this:
                //super.finalize();//Call the base-class version
      }
}
public class TerminatoinCondition {
      public static void main(String[]args) {
           Book novel=new Book(true);
           //Proper cleanup:
           novel.checkIn();
           //Drop the reference,forget to clean up:
           new Bool(true);
           //Force garbage collection & finalization:
           System.gc();
      }
}
 

四、this总结

用法一:引用当前对象的成员变量:如果在类的方法中定义了与类的成员变量同名的局部变量, 则在该方法中,类的成员变量会被覆盖,为了在该方法中引用类的成员变量,则用到了this,例如:

package com.exercise; 
public class Test { 
    /**
     * @param args
     */
    int i = 0;
   
    public void print() {
        int i = 1;
        System.out.println(i);
        System.out.println(this.i);
    }
   
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Test test = new Test();
        test.print();
    }
 
}

用法二:将当前对象作为参数传递:有时候,在类的某一个方法中需要调用一个外部方法,该方法的参数是该类的对象,这种情况下,调用时便可将this传递进去。例如:

class Person {
    public void eat(Apple apple) {
        Apple peeled = apple.getPeeled();
        System.out.println("Yummy");
    }
}
 
class Peeler {
    static Apple peel(Apple apple) {
        //... remove peel
        return apple; // Peeled
    }
}
 
class Apple {
    Apple getPeeled() {
        return Peeler.peel(this);
    }
}
 
public class PassingThis {
    public static void main(String[] args) {
        new Person().eat(new Apple());
    }
}

用法三:在类的重载构造函数中调用其他构造函数:当一个类有多个构造函数时,为了增加代码的复用,可以在一个构造函数中调用其他构造函数,但,只允许在当前构造函数中的第一句调用一次其他构造函数,否则将无法编译通过,如下面代码所示:

package com.exercise; 
public class Test { 
    public int i;
    Test(int i) {
        this.i = i;
    }
    Test(String s) {
        System.out.println(s);
    }
    Test(int i, String s) {
        this(s);
        //this(i);    编译无法通过
        this.i = i;
    }
    public static void main(String[] args) {
        Test test = new Test(6, "Hello");
        System.out.println(test.i);
    }
}

用法四:在内部类或匿名类中的用法,还未接触,待补充

注意:1、this不能用在static方法里  2、在构造函数中通过this调用其他构造函数的时候只能放在第一句

(待完善)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

法哥2012

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值