注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

享受编码

    的乐趣

 
 
 

日志

 
 

基础加强1到4-构造函数、包、var-arg、变量、访问修饰符、重写\重载、初始化块、返回值规则、instanceof比较  

2011-05-27 22:27:41|  分类: Java |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

封装(Encapsulation):多态(polymorphic):

static关键字:(重点在使用的原因)

标示为static的变量和方法属于类,而不是属于任何具体实例。
不能从静态方法访问非静态(实例)变量。即:类的静态方法不能访问其自己类的非静态方法或变量(a static methodof a class can’t access a nonstatic (instance) method or variable of its own class.)。
静态方法不能被重写(static methods can't be overridden!)。但可以重新定义。eg:
class Animal {
          static void doSt?() {
             System.out.print("a ");
          }
}
class Dog extends Animal {
      static void dost?() { // it's a redefinition,not an override
         System.out.print("d ");
       }
     p lic static void main(String [] args) {
          Animal [] a = {new Animal(), new Dog(), new Animal()};
          for(int x = 0; x < a.length; x++) //也可:for(Animal e:a) e.doSt?()
               a[x].doSt?(); // invoke the static method
     }
}
Running this code prod?s the output:
a a a
动态绑定与静态绑定:

动态绑定是多态的基础,所谓动态绑定,即虚拟机在运行时才能确定要调用的方法(变量)究竟是哪个类的方法(变量)
静态绑定与多态无关,所谓静态绑定,即在编译时(无需等到运行时)就可以确定调用的是哪个类的方法(变量);私有成员(变量和方法)和静态成员是静态绑定的。
具有可变参数列表var-arg的方法(相当于一个数组):

基本语法:类型后面依次接省略号(...)、一个空格,以及用于保存接收到的参数的数组名称。
var-arg限制:var-arg必须是方法签名中的最后一个参数,且一个方法中只能有一个var-arg 
构造方法(Constr tor):

每个类包括抽象类都必须有一个构造函数。通常构造函数用于初始化实例变量(又叫成员变量)的状态。eg:class Foo{
int size;//实例变量
String name;
Foo(int size){
this.name = name;//状态
this.size = size;
}}
不能显示调用类的构造方法,构造方法通常是通过new隐式调用的。
new关键字在生成对象时完成了三件事情:
a) 为对象开辟内存空间。
b) 调用类的构造方法。
c) 将生成的对象的地址返回。
构造函数的规则:
永远不能继承构造函数
构造函数能够使用任何访问修饰符,包括private(私有构造函数指只有该类自身内的代码才能实例化这种类型的对象,因此,如果私有构造函数类想允许使用该类的实例,则该类必须提供静态方法或变量,他们允许访问从该类内部创建的实例)
调用构造函数的唯一方法式从另一构造函数内部进行。eg:下面则有误:
class Horse{
    Horse(){}
    void doSt?(){
      Horse();   //illegal
   }
}
抽象类具有构造函数,这些构造函数总是当具体子类被实例化时才调用。
接口没有构造函数,接口不是对象继承树的一部份
每个构造函数必须调用重载构造函数(this())或调用超类构造函数(super())作为其第一条语句。
默认构造函数:具有与类相同的访问修饰符;没有任何参数;包含对超类构造函数(super())的无参调用(invoke)。
如果父类没有无参数构造函数,则在子类中将不能使用编译器提供的默认构造函数。
注意:super关键字也可以用于非构造方法中,eg:用super.name或super.getName()来调用父类的属性或方法。
局部变量和成员变量:

属性需要定义在类中,又叫做成员变量;而定义在方法中的变量叫做局部变量。
局部变量使用前必须要声明并赋初值;成员变量使用前必须要声明,但可以不赋初值。
成员变量与局部变量的联系与区别:
a) 无论是成员变量还是局部变量,使用前都需要声明(定义)。
b) 对于局部变量来说,使用前必须要初始化;对于成员变量来说,使用前可以不初始化。如果没有初始化成员变量就开始使用,那么每个类型的成员变量(又叫实例变量)都有一个默认的初始值:(静态变量(又叫类变量)获得的默认值与实例变量获得的相同)
i. byte、short、int、long类型的初始值为0
ii. float、do le类型的初始值为0.0
iii. char类型的初始值‘\’
iv. boolean类型的初始值为false
引用类型(reference type):引用类型是用在对向上的。
this是动态绑定且隐含的(即:this是多态的)指向当前对象。this关键字不可用于静态方法中。eg:

p lic class Animal{
   p lic void doit(){

     System.out.println("Animal.doit");

  }
}

p lic class Dog extends Animal{
   p lic static void main(String[] args){
     Dog d = new Dog();

     d.callSomething();
  }

  p lic void callSomething(){
     ((Animal)this).doit();//this 指向当前对象,而不是引用;这里仅仅转换了引用。
  }

  p lic void doit(){
    System.out.println("Dog.doit");
  }
}  //输入:Dog.doit

环境变量的设置有几种方式?

  设置环境变量有两种方式:第一种是在命令提示符运行窗口中设置(set path=%path%;C:\Program Files\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\bin);第二种是通过单击“我的电脑→属性→高级”标签的“环境变量”按钮设置。需要注意的是,第一种设置环境变量的方式只对当前运行窗口有效,关闭运行窗口后,设置就不起作用了,而第二种设置环境变量的方式则是永久有效。
 
对于Boolean类型的property,在定义其getters的时候,不是通过get来定义的,而是通过is来定义的。
package和import语句:

为便于管理大型软件系统中数目众多的类,解决类的命名冲突问题,Java引入包(package)机制,提供类的多重命名空间。(包名起名约定:公司的域名倒过来。eg:com.baidu)
Java编译器把包对应于文件系统的目录管理,package语句中,用‘.’来指明包(目录)的层次。
如果将一个类打包,则使用该类时,必须使用该类的全名(eg:com.baidu.MyClass),Java编译器才会找到该类。也可以使用import在文件的开头引入要使用到的类;可以不用import语句直接使用lang包中的类
不要让类的源代码位于classpath下。
想访问另外的类的话:(1)写全名。(2)import (*或具体类名)(3)访问位于同一包中的类不需引入
必须class文件的最上层包的父目录位于classpath下。执行一个类需要写全包名。
不同的项目设置不同的classpath。
将自己的类打成jar包:

在命令行窗口中,定位到最上层包(eg:com包)的上一层路径里。输入:jar -cvf **.jar *.*

可以将jar包放到classpath中,让别人能用。你在源文件中写了package,你编译出来的class文件就必须位于package所示的目录下。

访问控制:

对于class的权限修饰只能是p lic和默认,p lic类可以在任意地方访问。default类只可以被同一包内部的类访问。
protect:子类可以访问。
p lic class 指这个类在任何地方都可以用。
方法的重写:

子类中可以根据需要对从基类中继承来的方法进行重写。
重写方法必须和被重写方法具有相同的方法名,参数列表和返回类型。
重写方法不能使用比被重写方法更严格的访问权限。
super关键字:

      在Java类中使用super来引用基类的成分,

继承中的构造方法:

子类 构造的过程中必须调用其父类的构造方法。
子类可以在自己的构造方法中使用super调用父类的构造方法。使用this调用本类另外的构造方法,如果调用super,必须写在子类构造方法的第一行。
如果子类的构造方法中没有显示的调用父类的构造方法,则系统默认调用父类无参数的构造方法。
如果子类构造方法中既没有显示调用父类的构造方法,父类中又没有无参数的构造方法,则编译出错。
 基础加强-2-访问修饰符、eclipse常见配置、文档注释

访问修饰符:

   可见性                  p lic        protected       默认        private

从同一个类                  是             是                   是           是

从同一包中的任何类      是             是                   是           否

从同一包中的子类         是             是                   是           否

从包外的子类               是       是,通过继承          否           否

从包外的任何非子类      是             否                   否           否

总结:
(1).包外子类不能使用超类引用访问超类的保护成员。对于包外子类,只能通过继承访问超类的保护成员。(s classes outside the package can't use a superclass reference to access a protected member. For a s class outside the package, the protected member can be accessed only through inheritance.)
(2).一旦包外子类继承保护成员,该成员(被子类继承的)对这一子类外的任何代码来说都变成私有的。(Once the s class-outside-the-package inherits the protected member,that member (as inherited by the s class) becomes private to any code outside the s class)关键点是:当一个包外子类继承保护成员时,该成员在这个子类中实际上变成私有的。(The bottom line: when a s class-outside-the-package inherits a protected member, the member is essentially private inside the s class)

(3).请记住:默认成员只对与超类处于同一包中的子类来说是可见的。(Just remember that default members are visible to s classes only if those
s classes are in the same package as the superclass.)

(4)永远不能把访问修饰符应用于局部变量。可以肯定,用访问修饰符声明的所有局部变量都无法编译。事实上,只有一个修饰符能够用于局部变量,那就是final。(There is never a case where an access modifier can be applied to a local variable。You can be certain that any local variable declared with an access modifier will not compile. In fact, there is only one modifier that can ever be applied to local variables—final.)

类只能使用4个访问控制级别中的两个(默认和p lic),成员可以有全部4个。这里需要理解两个问题:
    (1).一个类的方法是否能访问另一个类的成员。
    (2).子类是否能继承父类的成员。
当一个方法或变量成员声明为p lic时,就表示所有其他类(无论他们属于哪个包)都能访问该成员(假设类自身可见)。
标示为private的成员不能被本类以外的任何其他类中的代码访问。
保护和默认的访问控制级别几乎完全相同,只有一点区别:只有当访问默认成员的类属于同一包时,才能访问默认成员;而对于保护成员来说,即使子类位于不同的包中,该子类也能通过继承访问他。即:只有在讨论子类时,默认和保护行为才有区别。如果protected关键字被用于定义一个成员,则该方法的任何子类都能访问他,即使超类和子类位于不同的包中也没有关系。默认行为不允许子类访问超类成员,除非子类与超类位于同一包中。
当考虑默认访问时,一定要考虑到包的限制。但是,当考虑protected时,要考虑包和子类,一个拥有保护成员的类把该成员标示为对所有类来说都具有包级访问权限,但是对于包外的子类提供特殊例外处理。
注意:无论何时讨论子类有权访问超类成员,都是在谈子类继承成员,而不是指通过超类实例的引用(任何其他非子类访问他是所用的方法)访问成员。仔细分析:
package certification;
p lic class Parent {
protected int x = 9; // protected access。这里如果改为p lic则下面不会出错。
}
package other;
import certification.Parent;
class Child extends Parent {
p lic void testIt() {
System.out.println("x is " + x); // No problem; Child inherits x
Parent p = new Parent(); // Can we access x using the p reference?
System.out.println("X in parent is " + p.x); // Compiler error! 最易出错之处
}
}
The compiler is more than happy to show us the problem:
%javac -d . other/Child.java
other/Child.java:9: x has protected access in certification.Parent
System.out.println("X in parent is " + p.x);
^
1 error
重写依赖于继承。

eclipse常见快捷键:

Ctrl+Shift+O:自动导包
自动生成getter和setter方法:在类的内部空白的代码区域Alt+Shift+S 然后选...
Ctrl+Shift+F  格式化当前代码
Ctrl+1 快速修复;即:批量修改源代码中的变量名,此外还可用在catch块上。
Ctrl+Alt+↓ 复制当前行到下一行。
Ctrl+T   快速显示当前类的继承结构
Ctrl + Z 返回到修改前的状态(编写代码时的后悔药)
Ctrl + Y 与上面的操作相反 (即刚后悔完又后悔)
Ctrl + Shif + / 自动注释代码
Ctrl + Shif + \自动取消已经注释的代码
eclipse常见配置:

设置本地历史记录数:window->Preferences->Local History 
workspace:即很多个项目存放的位置。不能有中文。启动后要改工作区:File->switch workspace->other
工作环境介绍:切换视图;Alt+/:代码模板。配置代码模板:->Java->Editor->templates
Alt+Shift+X;J  Ctrl+Z  Ctrl+单击:查看源码
 Eclipse的配置参数有三级:1 全局的,window->Preferences 2.项目上的 在项目上右击->Preferences 3.java 文件级的。右击->Preferences
配置UTF-8编码:做Java开发最佳的是UTF-8。每次打开一个新的工作空间之后第一个动作是window->Preferences->general->workspace调整整个文本工作区的文本编码,该为UTF-8。可以将单个项目改成GBK。
源码关联window->Preferences->jre  (已熟悉)
导入项目:解压到workspace,然后import
自动导包:Ctrl+Shift+O 快速格式化代码: Ctrl+Shift+F
Alt+Shift+S:生成getter和setter方法。
打包:写完项目之后,给别人使用时,就需要把项目打成包发布(dist目录)。->Export->Java->JAR File->
使用jar文件:在使用的项目上右键->folder(创建一个lib的目录),然后将jar文件拷到lib文件中。再右键->Properties->java Build Path->libraries->Add JARs...
引用工程:再右键->Properties->java Build Path->projects。
Debug即断点调试:
文档注释:

一个类写完之后,这个类一旦测试通过,这个类的javadoc就必须写完。除非这给类完全是内部类,外部不允许调用。特别是一些核心类所有的方法都需要写javadoc

导出javadoc:   -encoding UTF-8 -charset UTF-8

javadoc 中可以嵌入html代码。

文档标记:@see引用其他类(参见条目)

@version版本信息

@author作者信息

@param参数名 说明

@return说明

@exception完整类名 说明

@deprecated声明方法为丢弃

默认的注释模板的设置。window->Preferences->java->Code Style->Code Templates

基础加强-3-重写/重载、初始化块

重写/重载:

总结:

调用方法的哪个重写版本(换句话说,从继承树的哪个类)是根据对象类型在运行时决定的,但是,调用该方法的哪个重载版本基于编译时传递的参数的引用类型。(To
summarize, which overridden version of the method to call (in other words, from
which class in the inheritance tree) is decided at runtime based on object type, but
which overloaded version of the method to call is based on the reference type of
the argument passed at compile time.)
多态性不会决定调用哪个重载版本;多态性只有在决定调用方法的哪个重写版本时才起作用。(polymorphism doesn't determine which overloaded version is called; polymorphism does come into play when the decision is about which overridden version of a method is called.)例子详见:《SCJP学习指南》p.72
引用类型决定选择哪个重载版本(根据声明的参数类型),这发生在编译时;对象类型(换句话说就是堆上实际实例的类型)决定选择哪个重写方法,这发生在运行时。(Reference type determines which overloaded version (based on declared argument types) is selected. Happens at compile time.Object type (in other words, the type of the act l instance on the heap) determines which method is selected.Happens at runtime.)

重写的主要优点:能够定义某个子类特有的行为。抽象方法是必须要重写的方法。

使超类引用子类实例成为可能的原因是子类保证能够做超类可做的所有事情。

重写规则:

重写方法不能比被重写方法有更严格的访问修饰符。
参数列表、方法名、返回类型必须完全匹配。
重写方法可以抛出任何非检查的(运行时)异常,无论被重写方法是否申明了该异常。
重写方法一定不能抛出新的检查异常或比被重写方法声明的检查异常更广的检查异常。
重写方法能够抛出更少或更有限的异常。
不能重写标示为final的方法,也不能重写标示为static的方法。
如果不能继承一个方法,则不能重写他。重写意味着正在实现一个继承的方法!
使用super.方法名()可以调用被重写方法的超类版本。但使用super调用被重写方法只适用于实例方法不适用于静态方法(记住,静态方法不能被重写)
重载规则:(总结:方法名相同,参数表不同)

重载方法具有相同的方法名,不同的参数列表,并可以选择不同的返回类型,不同的访问修饰符。eg:
p lic void eat(){}和p lic String eat(){}//不是重写 也不是重载。
被重载的方法可以声明新的或更广泛的检查异常。
方法能够在同一类中或在子类中被重载。
注意:调用带对象引用而不是原始类型的重载方法,引用类型(而不是对象类型)决定调用哪个重载方法。(Just remember, the reference type (not the object type) determines which overloaded method is invoked!)
仔细分析以下代码,eg:class Animal { }
class Horse extends Animal { }
class UseAnimals {
p lic void doSt?(Animal a) {
System.out.println("In the Animal version");
}
p lic void doSt?(Horse h) {
System.out.println("In the Horse version");
}
p lic static void main (String [] args) {
UseAnimals = new UseAnimals();
Animal animalObj = new Animal();
Horse horseObj = new Horse();
.doSt?(animalObj);     //In the Animal version
.doSt?(horseObj);      //In the Horse version
Animal animalRefToHorse = new Horse();
  .doSt?(animalRefToHorse);     //In the Animal version

}
}
初始化块:

在类中有三个位置可以放置执行操作的代码:方法、构造函数、初始化块。当第一次加载类或者创建一个实例时,就会分别运行静态初始化块和实例初始化块。
初始化块的语法简单,没有名称,不能带参数,并且不会返回任何内容。第一次加载类时,会运行一次静态初始化块。每创建一个新的实例时,会运行一次实例初始化块。
实例初始化块代码的运行时间恰好发生在调用构造函数中的super()之后,即:在所有超类构造函数运行之后。
如果静态初始化块中产生一个错误,则JVM可能抛出一个java.lang.ExceptionInInitializerError
            class InitError {
                static int [] x = new int[4];
                static { x[4] = 5; } // bad array index!
                p lic static void main(String [] args) { }
            }
  输出如下:Exception in thread "main" java.lang.ExceptionInInitializerError
            Caused by: java.lang.ArrayIndexOutOfBoundsException: 4
            at InitError.<clinit>(InitError.java:3)
如果类中有多个初始化块,则他们的运行次序是自顶向下的。
class Init {
Init(int x) { System.out.println("1-arg const"); }
Init() { System.out.println("no-arg const"); }
static { System.out.println("1st static init"); }
{ System.out.println("1st instance init"); }
{ System.out.println("2nd instance init"); }
static { System.out.println("2nd static init"); }
p lic static void main(String [] args) {
new Init();
new Init(7);
}
}
To figure this out, remember these rules:
      1. Init blocks execute in the order they appear.
      2. Static init blocks run once, when the class is first loaded.
      3. Instance init blocks run every time a class instance is created.
      4. Instance init blocks run after the constr tor's call to super().
With those rules in mind, the following output should make sense:
1st static init
2nd static init
1st instance init
2nd instance init
no-arg const
1st instance init
2nd instance init
1-arg const
基础加强-4-返回值规则、instanceof比较

合法的返回类型:(包括协变式返回incl ing covariant returns),)

协变式返回的实例(a covariant return in action:):

class Alpha {
   Alpha doSt?(char c) {
     return new Alpha();
   }
}
class Beta extends Alpha {
    Beta doSt?(char c) {    // legal override in Java 1.5
      return new Beta();
    }
}

返回值规则:

1. 可以在具有对象引用返回类型的方法中返回null(You can return null in a method with an object reference return type.)。eg:
                                p lic Button doSt?() {
                                       return null;
                                 }
2. 数组是完全合法的返回类型(An array is a perfectly legal return type.)。
                   p lic String[] go() {
                       return new String[] {"Fred", "Barney", "Wilma"};
                   }
3. 在具有基本返回类型的方法内,可以返回任何值或变量,只要他们能够隐式转换为所声明的返回类型(In a method with a primitive return type, you can return any val or variable that can be implicitly converted to the declared return type.)。
                 p lic int foo() {
                          char c = 'c';
                          return c; // char is compatible with int
                  }
124 Chapter 2: Object Orientation
4. 在具有基本返回类型的方法内,可以返回任何值或变量,只要能够把他们显式强制转换为所声明的返回类型。(In a method with a primitive return type, you can return any val or variable that can be explicitly cast to the declared return type.)。
                                             p lic int foo () {
                                                      float f = 32.5f;
                                                      return (int) f;
                                              }
5. 一定不能从返回类型为void的方法返回任何值。(You must not return anything from a method with a void return type.)。
                              p lic void bar() {
                                         return "this is it"; // Not legal!!
                              }
6.在具有对象引用返回类型的方法内,可以返回任何对象类型,只要他们能够隐式强制转换为所声明的返回类型( In a method with an object reference return type, you can return any object type that can be implicitly cast to the declared return type.)
                    p lic Animal getAnimal() {
                         return new Horse(); // Assume Horse extends Animal
                    }
                    p lic Object getObject() {
                        int[] nums = {1,2,3};
                        return nums; // Return an int array,which is still an object
                     }
                     p lic interface Chewable { }
                     p lic class Gum implements Chewable { }
                     p lic class TestChewable {
                           // Method with an interface return type
                           p lic Chewable getChewable() {
                                      return new Gum(); // Return interface implementer
                            }
                      }
注意:一定要留意声明抽象类或接口返回类型的方法,并且要知道通过IS-A测试(也就是使用instanceof测试为TR)的任何对象都能够从那个方法中返回(Watch for methods that declare an abstract class or interface return type, and know that any object that passes the IS-A test (in other words, would test tr using the instanceof operator) can be returned from that method— for example:)。eg:

                             p lic abstract class Animal { }
                             p lic class Bear extends Animal { }
                             p lic class Test {
                                  p lic Animal go() {
                                     return new Bear(); // OK, Bear "is-a" Animal
                                   }
                             }
This code will compile, the return val is a s type(子类型).

instanceof比较:

insuranceof运算符只被用于对象引用变量,可以使用它检查对象是否是某种类型。这里的类型指类或接口类型。换句话说,运算符左边的变量所引用的对象是否能通过右边的类或接口类型的IS-A测试(in other words, if the object referred to by the variable on the left side of the operator passes the IS-A test for the class or interface type on the right side)。即使被测试的对象不是运算符右边的类类型的实际实例化,如果被比较的对象是一个与右边类型兼容的赋值,则insuranceof仍然返回ture。(Even if the object being tested is not an act l instantiation of the class type on the right side of the operator, instanceof will still return tr if the object being
compared is assignment compatible with the type on the right.)
如果对象的任一超类实现了某个接口,我们就说该对象属于这种接口类型(表示他将通过instanceof测试)。(An object is said to be of a particular interface type (meaning it will pass the instanceof test) if any of the object's superclasses implement the interface.)
请记住:数组是对象,即使该数组是基本类型的数组也是如此。数组总是Object的实例,任何数组都是这样。(Remember that arrays are objects, even if the array is an array of primitives.An array is always an instance of Object. Any array.)eg:
                            int [] nums = new int[3];
                         if (nums instanceof Object) { } // result is tr
测试null引用是否是一个类的实例是合法的,其结果总是false。


出处:http://blog.csdn.net/wenlin1009/archive/2010/09/08/5870196.aspx

  评论这张
 
阅读(1301)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018