您的位置:首页 > 编程语言 > Java开发

孙鑫-JAVA学习笔记(1-3)

2013-04-02 20:24 211 查看
一。 JAVA基础

javac 编译器  -》字节码         >javac hello.java

java 解释器                     >java  Hello      (加载的是Hello类,是由javac产生的字节码类;必须大写头)

所有java程序都是以类来执行的;

.多个class可以编辑到一个.java文件中,但编译后会分别产生各个.class字节码文件;可以将多个.class打包成.jar文件.

.如果在源文件中定义了一个public的class之后,此文件名必须为这个类名; -- 一个源文件中最多只能有一个Public的类

. classpath 设置为 E:/JAVA,.   点代表当前路径

语法:

基本类型

byte -128~+127

boolean 取值: true/false 不能是0,1

while(1)  不能编译

int num[3] JAVA中不能这样定义

必须:

int num[];

num = new int[3];

或者

int num[] = new int[3]

建议的数组定义方式

int[] num;

定义时可以分配元素:

int[] num = {1,2,3}



int[] num = new int[] {1,2,3}

但:

int[] num;

num = {1,2,3}; error

最基本的方式:

int num[];

num = new int[3];

num[1] = 11

num[2] = 22

num[3] = 33;

二维数组的每行的列数可以不同;类似与c的指针数组

int [][] num;

num = new int[3][];

num[0] = new int[5];

num[1] = new int[3];

num[2] = new int[2];

int[][] num = {{1,2,3}, {4,5}, {6}}  // OK, 最大下标分别是2,1,0

for (int i=0; i <= 10; i++)  //在java中这个i只在for循环内部有效; 不像C语言

{

}

 

 

二. 面向对象基础

1.构造方法和类同名,必须定义,如果没有则系统自动产生一个不带参数的构造函数如: point();

.javap.exe --反编译工具;将字节码类反编译成源文件;

用缺省构造函数初始化,则成员变量被初始化为默认值:

数值型: 0

boolean: false

char     '\0'

对象:   null

2.重载 -- 构造函数的重载

  必要条件:参数类型和参数个数必须不同!

void output (int x, int y)

{

   x = x; //error;  this.x=x;

   y = y; //error;  this.y=y;

}   this在成员函数中指向当前对象;

无参构造函数可以调用带参数的构造函数:

Point()

{

this(1,1)   //已定义 Point(int a, int b)

}

3. 静态成员函数 -- 类方法-- 从类名可直接调用; Point.output(); not pt1.out();

static void output()

{

}

静态成员函数只能使用静态成员变量:

static int z;

静态方法和静态变量是属于某一个类,而不属于类的对象。

静态方法和静态变量的引用直接通过类名引用。 (也可用对象名)

在静态方法中不能调用非静态的方法和引用非静态的成员变量。反之,则可以。

可以用类的对象obj去调用静态的方法method(),如:obj.method()

之所以main方法是static的;

虽然静态方法和非静态的成员函数在内存中都只有一个copy,但它们还是不同的;

4.常量

JAVA中没有define语句;所以常量可以用final声明:

final double PI = 3.1415926  (声明时必须赋初值)  -- 也可以将初始化放在构造函数中!

使用关键字final定义常量,例如:

    final double PI=3.1415926;

作为一种约定,在定义常量时,通常采用大写形式。

final常量可以在声明的同时赋初值,也可以在构造函数中赋初值。

为了节省内存,我们通常将常量声明为静态的(static)

static final double PI = 3.14;

5.继承 -- extends

父类,超类,基类

子类,派生类;

java不允许多继承;

6.覆盖

子类函数覆盖父类函数;

在子类中定义一个与父类同名、返回类型、参数类型均相同一个方法,称为方法的覆盖。

覆盖发生在子类与父类之间。

用super可以调用父类被覆盖的成员函数或者变量;

super.eat();

特殊变量super,提供了对父类的访问。

可以使用super访问父类被子类隐藏的变量或覆盖的方法。

每个子类构造方法的第一条语句,都是隐含地调用super(),如果父类没有这种形式的构造函数,那么在编译的时候就会报错.

子类自动调用父类构造函数,然后执行自身构造函数; 父类必须有无参的构造;不然自动执行会出错;

7.多态

通过覆盖父类的方法来实现,在运行时根据传递的对象引用,来调用相应的方法。

根据运行时传递参数的对象引用类型,来决定调用哪个方法;

8.instanceof用法

if(fh instanceof Animal)

  {

   System.out.println("fh is an animal's instance");

  }

  else

  {

   System.out.println("fh isn't animal's instance");

  }

输出: fh is animal's instance; 子类对象可以是父类的一个实例;

 

三(上).包,对象,方法,接口...

包,类,对象,方法,接口,垃圾回收,异常处理;

1.包 -- 包相当于类的限定名;

java.lang.String

package 名用小写;

>javac test.java

>java mybole/Test   //执行,并且必须创建mybole目录,将Test.class 放入目录;

package语句必须是文件中的第一条语句。也就是说,在package语句之前,除了空白和注释之外不能有任何语句。

如果不加package语句,则指定为缺省包或无名包。

包对应着文件系统的目录层次结构。

在package语句中,用“.”来指明包(目录)的层次。

在当前目录下生成包

    javac -d . Test.java

在指定目录下生成包

    javac -d E:\JavaLesson Test.java

-d 还能对应的生成目录结构,如:

>javac -d  . Test.java

则自动生成目录cn/mybole;

set classpath = %classpath%;D\cn\mybole;

1.1 import

引入包中的类。

    import java.io.File;

引入整个包。

    import java.io.*;

在同一包中的类可以互相引用,无需import语句。

java.lang 是默认就导入的,可以直接用;

如果没有导入一个类,也可以用:

java.io.File f;        //指定包路径进行外部类的使用

或者直接导入所有类: import java.io.*;

类的访问说明符

 (1)public   -- 跨包引用必须加上public关键字;

 (2)default(不加访问说明符时) -- 只能包内被访问

 -- 在不同的包之间访问类的时候,只能访问到声明为public的类;

类的其它修饰符

 (1)final  -- 表明它是最终的类;不能再派生出其它子类;

 (2)abstract  -- 抽象类

方法的访问说明符

 (1)public

 (2)protected

 (3)default(不加访问说明符时)

 (4)private

方法的其它修饰符

 (1)static

 (2)final

 (3)abstract

 (4)native

 (5)synchronized

访问说明符:     public   protected   default   private

同类                        Y             Y                Y            Y    

同包                        Y             Y                Y            N     

子类(不同包)     Y             Y                N            N    

通用性(不同包) Y             N                N            N    

final:

为了确保某个函数的行为在继承过程中保持不变,并且不能被覆盖(overridden),可以使用final方法。

为了效率上的考虑,将方法声明为final,让编译器对此方法的调用进行优化。要注意的是:编译器会自行对final方法进行判断,并决定是否进行优化。通常在方法的体积很小,而我们确实不希望它被覆盖时,才将它声明为final。

class中所有的private和static方法自然就是final。

子类中不能覆盖父类的final方法;

子类中定义新的private和static方法,虽然编译不报错,但是只是产生了新的函数,并没有覆盖父类的函数;

抽象方法和抽象类:

在类中没有方法体的方法,就是抽象方法。

含有抽象方法的类,即为抽象类。 -- 如果类中声明了抽象方法,则类也必须声明为抽象的;

如果一个子类没有实现抽象基类中所有的抽象方法,则子类也成为一个抽象类。

我们可以将一个没有任何抽象方法的类声明为abstract,是为了避免由这个类产生任何的对象。

构造方法、静态方法、私有方法、final方法不能被声明为抽象的方法。

如果抽象类的子类没有实现父类的抽象方法,则它也是抽象的,必须加abstract;   可以用空实现 void fn(){}

native方法:

native方法是用户在Java中可以使用,但不能编写的方法。

JNI - JAVA Native Interface

tutorial...

Linux 平台 .SO文件为: 动态链接库

JNI(Java Native Interface),它允许Java虚拟机(JVM)内部运行的Java代码能够与用其它编程语言(如C、C++、汇编语言)编写的应用程序和库进行互操作。

JNI最大的好处是它没有对底层Java虚拟机的实现施加任何限制,因此,Java虚拟机厂商可以在不影响虚拟机其它部分的情况下添加对JNI的支持。程序员只需编写一种版本的本地(Native)应用程序和库,就能够与所有支持JNI的Java虚拟机协同工作。

JNI可以理解为Java和本地应用程序之间的中介。

可以给类定义一个静态变量,在构造函数里让其自增来记录生成对象的数量;

垃圾回收:

垃圾回收器是一个低优先级的进程,在后台运行...当内存不足是才会调用;

System.gc(); 强制执行垃圾回收器

接口:

接口中所有的方法都是public abstract。

在接口中声明方法时,不能使用native、static 、final 、synchronized 、private 、protected等修饰符。

和public类一样,public接口也必须定义在与接口同名的文件中。

接口中可以有数据成员,这些成员默认都是public static final。

接口通常定义为public的

在类中实现接口的方法,必须也定义成public的;

实现类中必须实现接口中所有的方法,才能实例对象;否则它还是抽象类;

类中方法的形参可以用接口名;而实参调用的时候再使用实现类的对象来实例化;

接口的成员变量默认就是静态的公用常量!

访问方法有如下三种:

System.out.println(Math.PI);  //接口名称调用

  System.out.println(Arithmetic.PI); //实现类名调用

  System.out.println(a.PI);  //实现类对象调用

一个接口可以继承自另一个接口。

Java中不允许类的多继承,但允许接口的多继承。

interface Sofa extends Sittable, Lie

在Java中,一个类可以实现多个接口。

一个类在继承另外一个类的同时,可以实现多个接口。

class Sofa extends Chair implements Lie, HealthCare

{

 public void sleep(){};

 public void massage(){};

}

注意先后顺序!先继承再实现 --- extends放implements之前

 

三.(下)内部类,异常处理

1. 内部类

在一个类中定义另外一个类,这个类就叫做内部类或内置类 (inner class) 。

内部类可以让我们将逻辑上相关的一组类组织起来,并由外部类(outer class)来控制内部类的可见性。

当我们建立一个inner class时,其对象就拥有了与外部类对象之间的一种关系,这是通过一个特殊的this reference形成的,使得内部类对象可以随意的访问外部类中所有的成员。

内部类产生的字节码类名: outer$inner.class

new 产生的对象都在堆内存中!

Outer.this 来引用外部类成员变量; 外部类名.THIS

 

    class Inner

 {

  private int index=50;

  static void print()

  {

   int index=30;

   System.out.println(index);

   System.out.println(this.index);

   System.out.println(Outer.index);

   

  }

 }

静态的main方法不能直接new一个非静态的inner对象!

inner对象不能直接用new产生!

必须先产生一个外部类才能有内部类!

Outer.Inner inner = outer1.new Inner();// 必须与一个具体的外部类对象关联。

内部类也可以放在外部类的一个方法内定义,但是它的有效范围也只有方法内部!

内部类也可以放在一个条件语句中,或者语句块内;-- 无论它嵌套多深,它都能访问外部类的成员;

方法中声明的内部类如果要访问方法的局部变量,则该局部变量必须声明为final的常量!

当内部类声明为static后,生成时就无需先产生外部类的对象了,但也不能访问外部类对象的成员变量了; 只能访问静态的成员变量或者静态的成员方法了...

非静态的内部类不能有静态的方法;

在方法中定义的内部类,如果要访问方法中定义的本地变量或方法的参数,则变量必须被声明final。

内部类可以声明为private或protected;还可以声明为abstract或final。

内部类可以声明为static的,但此时就不能再使用外部类的非static的成员变量和非static的成员方法;

非static的内部类中的成员不能声明为static的,只有在顶层类或static的内部类中才可声明static成员。

我们为什么使用内部类

1、在内部类(inner class)中,可以随意的访问外部类的成员,这可以让我们更好地组织管理我们的代码,增强代码的可读性。

2、内部类可以用于创建适配器类,适配器类是用于实现接口的类。使用内部类来实现接口,可以更好地定位与接口关联的方法在代码中的位置。

3、内部类的更多用法。

匿名内置类:

/*Animal getAnimal()

 {

  return new Animal()

  {

   public void eat()

   {

    System.out.println("animal eat");

   }

   public void sleep()

   {

    System.out.println("animal sleep");

   }

  };            //在;前加入实现

其它用法: --- 接口中的方法和基类方法同名,但意义不同:

interface Machine

{

 void run();

}

class Person

{

 void run()

 {

  System.out.println("run");

 }

}

class Robot extends Person

{

 private class MachineHeart implements Machine     //用来实现接口中的run方法

 {

  public void run()

  {

   System.out.println("heart run");

  }

 }

 Machine getMachine()  //相当于也继承了Machine类

 {

  return new MachineHeart();

 }

}

class Test

{

 public static void main(String[] args)

 {

  Robot robot=new Robot();

  Machine m=robot.getMachine();  //返回一个实现类对象

  m.run();

  robot.run();

 }

}

JAVA中只能单继承,可以用接口和内部类的方法来解决C++中多继承实现的问题!

C类想继承A类和B类,可以继承A类然后定义一个getB()方法来返回一个匿名内部类对象(在这个getB()之后直接实现抽象类B;) 则运行时就可以用C类对象来实现A,B类对象作为形参的方法了。 例子如下:

class A

{

 void fn1()

 {

 }

}

abstract class B

{

 abstract void fn2();

}

class C extends A

{

 B getB()

 {

  return new B()

  {

   public void fn2()

   {

   }

  };

 }

}

class Test

{

 static void method1(A a)

 {

  a.fn1();

 }

 static void method2(B b)

 {

  b.fn2();

 }

 public static void main(String[] args)

 {

  C c=new C();

  method1(c);

  method2(c.getB());

 }

}

2. 异常处理

程序运行是遇到的错误;

通过异常类来实现的;

所有异常都有个基类:exception

异常类的层次结构:

 

打开一个不存在的文件、网络连接中断、数组下标越界、正在加载的类文件丢失等都会引发异常。

Java中的异常类定义了程序中遇到的轻微的错误条件。

   Java中的错误类定义了程序中不能恢复的严重错误条件。如内存溢出、类文件格式错误等。这一类错误由Java运行系统处理,不需要我们去处理。

Java程序在执行过程中如出现异常,会自动生成一个异常类对象,该异常对象将被提交给Java运行时系统,这个过程称为抛出(throw)异常。

当Java运行时系统接收到异常对象时,会寻找能处理这一异常的代码并把当前异常对象交给其处理,这一过程称为捕获(catch)异常。

如果Java运行时系统找不到可以捕获异常的方法,则运行时系统将终止,相应的Java程序也将退出。

try/catch/finally语句。

try

  {

   return excep.division(5,0);

  }

  catch(Exception e) //四种方法

  {

   System.out.println(“不能被0除”);    //用户定义异常信息

   System.out.println(e.getMessage() );  //直接返回该exception的错误信息

   System.out.println(e.toString());   //Returns a short description of this throwable.

   e.printStackTrace();  //打印Exception。实际上如果不处理,JVM会直接调用此函数(然后终止);

  }

catch 语句中一定要填入处理语句,如果留空{},则一旦发生异常,将无任何输出!

捕获异常可以在方法调用处,也可以在方法声明处!

如果方法声明处抛出异常,则报错在调用处! 如:public int fn1(int a,int b) throws Exception {}

如果在运行主函数后也加入 throws Exception, 则异常将交给JVM来处理,最省事的做法!!

最好还是自己处理异常,打印出详细错误或者进行正确处理!

catch语句可以写多个,如:

catch(ArithmeticException e) {....}

catch(Exception e) {....}    //但必须将具体异常写之前,通用的这个写后边!

runtimeException之外的异常都要求捕获,或者抛出;

声明中抛出异常用 throws

而抛出语句用 throw

catch(ArithmeticException e)

 {

  e.printStackTrace();

  throw e;

  //return 0;

 }

用户也可以自己定义额外的异常,如:除数小于零。

class DivisorIsMinusException extends Exception

{

 DivisorIsMinusException(String str)

 {

  super(str);

 }

}

finally:

try{}catch{}finally{} ----无论是否产生异常,finally语句都要执行,一般用来释放资源(网络,数据库连接等)。即便try或catch语句最后return了;

当程序终止运行后:System.exit(-1),finally就不执行了!

对于RuntimeException,通常不需要我们去捕获,这类异常由Java运行系统自动抛出并自动处理。

如果父类中的方法抛出多个异常,则子类中的覆盖方法要么抛出相同的异常,要么抛出异常的子类,但不能抛出新的异常(注:构造方法除外--构造方法不被覆盖)。

我们可以在方法声明时,声明一个不会抛出的异常,Java编译器就会强迫方法的使用者对异常进行处理。这种方式通常应用于abstract base class和interface中。

JAVA 编程规范:

package的命名

package 的名字由全部小写的字母组成,例如:cn.mybole。

class和interface的命名

class和interface的名字由大写字母开头而其他字母都小写的单词组成,例如:Person,RuntimeException。

class变量的命名

变量的名字用一个小写字母开头,后面的单词用大写字母开头,例如:index,currentImage。

class方法的命名

   方法的名字用一个小写字母开头,后面的单词用大写字母开头,例如:run(),getBalance()。

static final变量的命名

static final变量的名字所有字母都大写,并且能表示完整含义。例如:PI,PASSWORD。

参数的命名

参数的名字和变量的命名规范一致。

数组的命名

。   数组应该总是用这样的方式来命名:byte[] buffer。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: