必须用this关键字的三种情况:
1、我们想通过构造方法将外部传入的参数赋值给类的成员变量,构造方法的形式参数名称与类的成员变量名相同。例如:
class Person
{
String name;
public Person(String name)
{
this.name = name;
}
}
2、假设有一个容器类和一个部件类,在容器类的某个方法中要创建部件类的实例对象,而部件类的构造方法要接受一个代表其所在容器的参数。例如:
class Container
{
Component comp;
public void addComponent()
{
comp = new Component(this);
}
}
class Component
{
Container myContainer;
public Component(Container c)
{
myContainer = c;
}
}
3、构造方法是在产生对象时被java系统自动调用的,我们不能再程序中像调用其他方法一样去调用构造方法。但我们可以在一个构造方法里调用其他重载的构造方法,不是用构造方法名,而是用this(参数列表)的形式,根据其中的参数列表,选择相应的构造方法。例如:
public class Person
{
String name;
int age;
public Person(String name)
{
this.name = name;
}
public Person(String name,int age)
{
this(name);
this.age = age;
}
}
Java关键字this、super使用总结
一、this
Java关键字this只能用于方法方法体内。当一个对象创建后,Java虚拟机(JVM)就会给这个对象分配一个引用自身的指针,这个指针的名字就是 this。因此,this只能在类中的非静态方法中使用,静态方法和静态的代码块中绝对不能出现this,这在“Java关键字static、final 使用总结”一文中给出了明确解释。并且this只和特定的对象关联,而不和类关联,同一个类的不同对象有不同的this。下面给出一个使用this的综合实例,以便说明问题:
package org.leizhimin;
public class Test6 {
private int number;
private String username;
private String password;
private int x = 100;
public Test6(int n) {
number = n; // 这个还可以写为: this.number=n;
}
public Test6(int i, String username, String password) {
// 成员变量和参数同名,成员变量被屏蔽,用"this.成员变量"的方式访问成员变量.
this.username = username;
this.password = password;
}
// 默认不带参数的构造方法
public Test6() {
this(0, "未知", "空"); // 通过this调用另一个构造方法
}
public Test6(String name) {
this(1, name, "空"); // 通过this调用另一个构造方法
}
public static void main(String args[]) {
Test6 t1 = new Test6();
Test6 t2 = new Test6("游客");
t1.outinfo(t1);
t2.outinfo(t2);
}
private void outinfo(Test6 t) {
System.out.println("-----------");
System.out.println(t.number);
System.out.println(t.username);
System.out.println(t.password);
f(); // 这个可以写为: this.f();
}
private void f() {
// 局部变量与成员变量同名,成员变量被屏蔽,用"this.成员变量"的方式访问成员变量.
int x;
x = this.x++;
System.out.println(x);
System.out.println(this.x);
}
//返回当前实例的引用
private Test6 getSelf() {
return this;
}
}
运行结果如下:
-----------
0
未知
空
100
101
看着上面的例子,说明在什么情况下需要用到this:
第一、通过this调用另一个构造方法,用发是this(参数列表),这个仅仅在类的构造方法中,别的地方不能这么用。
第二、函数参数或者函数中的局部变量和成员变量同名的情况下,成员变量被屏蔽,此时要访问成员变量则需要用“this.成员变量名”的方式来引用成员变量。当然,在没有同名的情况下,可以直接用成员变量的名字,而不用this,用了也不为错,呵呵。
第三、在函数中,需要引用该函所属类的当前对象时候,直接用this。
其实这些用法总结都是从对“this是指向对象本身的一个指针”这句话的更深入的理解而来的,死记不然容易忘记而且容易搞错,要理解!
二、super
super关键和this作用类似,是被屏蔽的成员变量或者成员方法或变为可见,或者说用来引用被屏蔽的成员变量和成员成员方法。
不过super是用在子类中,目的是访问直接父类中被屏蔽的成员,注意是直接父类(就是类之上最近的超类)。下面是一个综合运用super的例子,有两个类:一个Father类,一个Father类的子类Son,通过这两个类完全演示了super的用法,一下是代码:
package org.leizhimin;
public class Father {
public String v="Father";
public String x="输出了Father类的public成员变量x!!!";
public Father() {
System.out.println("Father构造方法被调用!");
}
public Father(String v){
this.v="Father类的带参数构造方法!运行了.";
}
public void outinfo(){
System.out.println("Father的outinfo方法被调用");
}
public static void main(String[] args) {
// TODO 自动生成方法存根
}
}
package org.leizhimin;
public class Son extends Father{
public String v="Son";
public Son() {
super(); //调用超类的构造方法,只能放到第一行.
System.out.println("Son无参数构造方法被调用!");
//super(); //错误的,必须放到构造方法体的最前面.
}
public Son(String str){
super(str);
System.out.println("Son带参数构造方法被调用!");
}
//覆盖了超类成员方法outinfo()
public void outinfo(){
System.out.println("Son的outinfo()方法被调用");
}
public void test(){
String v="哈哈哈哈!"; //局部变量v覆盖了成员变量v和超类变量v
System.out.println("------1-----");
System.out.println(v); //输出局部变量v
System.out.println(this.v); //输出(子类)成员变量v
System.out.println(super.v); //输出超类成员变量v
System.out.println("------2-----");
System.out.println(x); //输出超类成员变量v,子类继承而来
System.out.println(super.x); //输出超类成员变量v
System.out.println("------3-----");
outinfo(); //调用子类的outinfo()方法
this.outinfo(); //调用子类的outinfo()方法
super.outinfo(); //调用父类的outinfo()方法
}
public static void main(String[] args) {
new Son().test();
}
}
子类Son运行结果:
Father构造方法被调用!
Son无参数构造方法被调用!
------1-----
哈哈哈哈!
Son
Father
------2-----
输出了Father类的public成员变量x!!!
输出了Father类的public成员变量x!!!
------3-----
Son的outinfo()方法被调用
Son的outinfo()方法被调用
Father的outinfo方法被调用
说明:次例子仅仅为了说明super的用法,实际在设计类的时候一般都尽可能私有(private)化。
通过上面的例子,下面总结一下super的用法:
第一、在子类构造方法中要调用父类的构造方法,用“super(参数列表)”的方式调用,参数不是必须的。同时还要注意的一点是:“super(参数列表)”这条语句只能用在子类构造方法体中的第一行。
第二、当子类方法中的局部变量或者子类的成员变量与父类成员变量同名时,也就是子类局部变量覆盖父类成员变量时,用“super.成员变量名”来引用父类成员变量。当然,如果父类的成员变量没有被覆盖,也可以用“super.成员变量名”来引用父类成员变量,不过这是不必要的。
第三、当子类的成员方法覆盖了父类的成员方法时,也就是子类和父类有完全相同的方法定义(但方法体可以不同),此时,用“super.方法名(参数列表)”的方式访问父类的方法。
介绍:
我们已经说过类是对象的模板,当用类创建一个对象时,我们也就给出了这个类的一个实例。
对象的使用需要专门分配内存,又new关键字来完成。对象的内存结构和该类是相同的。
对象的申明:
格式--- 类的名字 对象的名字
举例--- People zhanPing
对象的内存分配:
zhangPing=new People ();
举例------
class XiyoujiRenwu
{
float height,weight;
String head,ear,hand,foot,mouth;
void speak(String s)
{
System.out.println(s);
}
}
class A
{
public static void main(String arg[])
{
XiyoujiRenwu zhubajie; //对象申明,西游记人物类,对象是猪八戒
zhubajie=new XiyoujiRewu (); //分配空间,猪八戒和其他西游记人物一样,有脑袋 头等
}
}
上面程序很好的说明了,申明的方法,分配类西游记人物类的空间,使猪八戒也像其他人一样属性,属性值当然可以改变。如果没有分配空间,那么zhubajie对象是一个空对象,内存中没有任何数据,当然也不能被使用,所以对象申明之后,想使用就必须分配空间。
使用对象:
还记得类中除了变量的申明还有什么吗?是的,还有方法。对象除了可以操作自己的变量外,还可以操作类中的方法,使用方法产生一定的行为。下面就分两部分谈下。
1.对象操作自己的变量(对象的属性)
通过运算符"“.”,对象可以实现对自己变量的访问。
举例:zhubajie.weight=160f;
2.对象调用类中的方法:
概念---类方法的调用同变量,使用“.”运算符来完成,对象调用类时,方法中的局部变量被分配空间,方法执行完毕,内存被释放。当对象调用方法时,方法中的成员变量就是指该对象的成员变量。
举例:zhubajie.speak("老猪我不帅吗?嫁给我吧";
*以上例句都以上面完整程序为例
java的垃圾回收机制是怎么回事?
Point p1=new Point(12,6);
Point p2=new Point(6,18);
p1=p2;
这种机制周期的检测某个实体是否已不再被对象所拥有,如发现这样的实体(对象的属性),就释放实体的内存,因此,java编程不必像C++程序员那样要时刻的检查那些对象应该释放内存。
下面一个较完整的程序:
class 圆 //****************************************************************************
{ //圆类 其中包含了面积,半径等操作方法
double 半径;
圆(double r)
{
半径=r;
}
double 计算面积()
{
return 3.14*半径*半径;
}
void 修改半径(double 新半径)
{
半径=新半径;
}
double 获取半径()
{
return 半径;
}
} //**********************************************************************
class 圆锥 //*****************************************************************
{ //圆锥类,完称了 对象 的变量和方法的调用。
圆 底圆;
double 高;
圆锥(圆 circle,double h)
{
this.底圆=circle;
this.高=h;
}
double 计算体积()
{
double volume;
volume=底圆.计算面积()*高/3.0;
return volume;
}
void 修改底圆半径(double r)
{
底圆.修改半径(r);
}
double 获取底圆半径()
{
return 底圆.获取半径();
}
} //*******************************************************************
class Example //******************************************************************************
{
public static void main(String args[]) //main,程序执行的开始,无论书写顺序。
{
圆 circle=new 圆(10);
圆锥 circular=new 圆锥(circle,20);
System.out.println("圆锥底圆半径:"+circular.获取底圆半径());
System.out.println("圆锥的体积:"+circular.计算体积());
circular.修改底圆半径(100);
System.out.println("圆锥底圆半径:"+circular.获取底圆半径());
System.out.println("圆锥的体积:"+circular.计算体积());
}
} //******************************************************************************************
static关键字:
static关键字用来声明类变量,类方法,类变量。
class 梯形
{
static float 下底; //类变量
............
}
class Example
{
public static void main(String args[]) //类方法
{
梯形.下底=60; // 通过类名操作类变量
...........
}
}
*注意:该类被加载到内存后,就分配了空间。一般类创建对象,不同对象的实例变量互不相同,既分配不同的空间。而类变量不在分配空间,而是共享变量空间。
类方法与实例方法区别:
实例方法:创建对象后分配入口地址。不能通过类名调用。
类方法:该类被加载到内存后,分配入口地址。方法的入口被所有对象共享。可直接通过类名被对象调用。
this关键字:
this出现的位置:1.类的实例方法中,代表使用该类的当前对象
2.构造方法中,代表使用该构造方法所创建的对象
class A
{
int x;
void f ()
{
this.x=100;
}
}
当对象调用方法,方法中的成员变量就是指分配给该对象的成员变量。因此,这里将100赋给该对象的变量x。通常情况下,这里的this可以省略。当成员变量名与局部变量名相同,则this就不可省略。
class B
{
void f ()
{
this.g(); //对象调用方法f又调用了方法g
}
void g ()
{
System.out.println("ok");
}
}
类的实例方法可以调用类的其他方法,调用格式this.方法。
this不能出现在类方法中,这是因为,类方法可以通过类名直接调用,这时,可能还没有任何对象诞生。
包:
概念:
包是java语言中有效地管理类的一个机制。
包语句:
打包:package 格式:package 包名;
调用:import 格式:import 包名或路径;
包名可以是一个合法的标识符,也可以是若干个标识符加 "."此符号为目录结构符号
例子:
package tom.jiafei; //目录结构:.../tom/jiafei 且原文件在该目录中,编译后使用。
import java.applet.*; //调用系统applet包中所有类,*代表所有类
常用java系统包:
java.applet 包含所有实现java applet的类
java.awt 包含抽象窗口工具集中的图形,文本,窗口GUI类
java.awt.image 包含抽象窗口工具集中的图像处理类
java.lang 包含所有的基本语言类
java.io 包含所有输入/输出类
java.net 包含所有实现网络功能的类
java.until 包含有用的数据类型类
当然我们也可以调用自己的包 import tom.jiafei;
还可以使用无名类,就是把编写好的类存放在要调用该类程序目录中。
其实我们可以简单的把包想象成c语言中的函数,库函数就像java的系统包,c用include调用,java用import调用。
访问权限:
1.私有变量及方法 关键字:private
2.共有变量及方法 关键字:public
3.友好变量及方法 关键字:无修饰符
4受保护的变量及方法 关键字:protected
1.私有变量:
class Tom
{
private float weight; //weight被修饰为私有的float型变量
private float f (float a,float b) //方法f是私有方法
{
.......
}
}
class Jerry
{
void g()
{
Tom=cat=new Tom();
cat.weight=23f; //非法;
cat.f(3f,4f); //非法
}
}
只有在本类中创建该类的对象时,这个对象才能访问自己的私有成员变量中的私有方法。当在另一个类中用类Tom船舰这个对象后,该对象不能访问自己的私有变量和私有方法。
2.公用变量及公用方法:
class Tom
{
public float weight; //weight被修饰为public的float型变量
public float f(float a,float b) // f被修饰为public的方法
{
}
}
其他类可以调用其类变量或方法。
3.友好变量及友好方法:
class Tom
{
float weight; //无修饰为友好变量
float f(float a,float b) // f无修饰为友好方法
{
}
}
基本与public相同,特点是在任何一个与Tom同一个包的类中,可通过Tom类名访问Tom类中的友好变量及友好方法。
4.受保护的成员变量及方法:
class Tom
{
protected float weight; //weight修饰为受保护的变量
protected float f(float a,float b) // f被修饰为受保护的方法
{
}
}
基本与友好变量及友好方法相同,他们的区别在类的继承中会仔细谈到。
这里强调下protected和private不可以修饰类
访问权限排序:
高----低
public----- protected----- 友好的 ----private
下篇将会谈到类的继承问题
对象实例由new关键字创建,而不是由方法创建,也就是说,构造方法不用返回任何结果。因此,在构造方法中不要有返回结果的return语句。使用new关键字创建一个对象实例后,JavaScript会接着自动调用所使用的构造函数,执行构造函数中的程序。
一个对象可以创建多个对象实例,在使用时,各个对象实例之间没有任何关系,为一个对象实例新增加的属性和方法,不会增加到同一个对象所产生的其他对象实例上,修改一个对象实例的属性值,不会影响其他对象实例的同名属性。
this关键字一般只在用作对象成员方法的函数中出现,代表某个成员方法执行时,引用该方法的当前对象实例。在对象的构造函数中使用“this.成员名” 的形式,可以为该对象的每个对象实例都增加新成员。下面例子演示了如何使用构造函数为对象增加属性和方法:
<script language = "javascript" type = "text/javascript">
<!--
function student(name,website)
{
this.name = name;
this.website = website;
this.out = print_student;
}
function print_student()
{
document.write(this.name + this.website);
}
var stu1 = new student("阿会楠","sosuo8.com");
stu1.out();
//-->
</script>
<script language = "javascript" type = "text/javascript">
<!--
function student(name,website)
{
this.name = name;
this.website = website;
this.out = new Function
{
document.write(this.name + this.website);
}
}
function print_student()
{
document.write(this.name + this.website);
}
var stu1 = new student("阿会楠","sosuo8.com");
stu1.out();
//-->
</script>
try...catch...finally 语句
为 JScript 实现错误处理。
try {
tryStatements}
catch(exception){
catchStatements}
finally {
finallyStatements}
=============
参数
tryStatement
必选项。可能发生错误的语句。
exception
必选项。任何变量名。exception 的初始化值是扔出的错误的值。
catchStatement
可选项。处理在相关联的 tryStatement 中发生的错误的语句。
finallyStatements
可选项。在所有其他过程发生之后无条件执行的语句。
说明
try...catch...finally 语句提供了一种方法来处理可能发生在给定代码块中的某些或全部错误,同时仍保持代码的运行。如果发生了程序员没有处理的错误,JScript 只给用户提供它的普通错误信息,就好象没有错误处理一样。
tryStatements 参数包含可能发生错误的代码,而 catchStatement 则包含处理任何发生了的错误的代码。如果在 tryStatements 中发生了一个错误,则程序控制被传给 catchStatements 来处理。exception 的初始化值是发生在 tryStatements 中的错误的值。如果错误不发生,则不执行 catchStatements。
如果在与发生错误的 tryStatements 相关联的 catchStatements 中不能处理该错误,则使用 throw 语句来传播、或重新扔出这个错误给更高级的错误处理程序。
在执行完 tryStatements 中的语句,并在 catchStatements 的所有错误处理发生之后,可无条件执行 finallyStatements 中的语句。
请注意,即使在 try 或 catch 块中返回一个语句,或在 catch 块重新扔出一个错误,仍然会执行 finallyStatements 编码。一般将确保 finallyStatments 的运行,除非存在未处理的错误。(例如,在 catch 块中发生运行时错误。)。
示例
下面的例子阐明了JScript 特例处理是如何进行的。
try {
print("Outer try running..");
try {
print("Nested try running...");
throw "an error";
}
catch(e) {
print("Nested catch caught " + e);
throw e + " re-thrown";
}
finally {
print("Nested finally is running...");
}
}
catch(e) {
print("Outer catch caught " + e);
}
finally {
print("Outer finally running");
}
// Windows Script Host 作出该修改从而得出 WScript.Echo(s)
function print(s){
document.write(s);
}
将得出以下结果:
Outer try running..
Nested try running...
Nested catch caught an error
Nested finally is running...
Outer catch caught an error re-thrown
Outer finally running
extends 继承类;implements 实现接口。
类和接口是不同的:类里是有程序实现的;而接口无程序实现,只可以预定义方法 extends 继承类。
implements 实现接口:
Java也提供继承机制﹐但还另外提供一个叫interface的概念。由于Java的继承机制只能提供单一继承(就是只能继承一种父类别)﹐所以就以 Java的interface来代替C++的多重继承。interface就是一种介面﹐规定欲沟通的两物件﹐其通讯该有的规范有哪些。如以Java程式语言的角度来看﹐Java的interface则表示:一些函数或资料成员﹐为另一些属于不同类别的物件所需共同拥有﹐则将这些函数与资料成员﹐定义在一个interface中﹐然后让所有不同类别的Java物件可以共同操作使用之。
Java的class只能继承一个父类别(用extends关键字)﹐但可以拥有(或称实作)许多interface(用implements关键字)。
extends和implements有什么不同?
对于class而言,extends用于(单)继承一个类(class),而implements用于实现
一个接口(interface)。
interface的引入是为了部分地提供多继承的功能。
在interface中只需声明方法头,而将方法体留给实现的class来做。
这些实现的class的实例完全可以当作interface的实例来对待。
在interface之间也可以声明为extends(多继承)的关系。
注意一个interface可以extends多个其他interface。
this 是 JavaScript 中很强大的关键字之一。但是不幸的是,如果你不能完全明白它的特征和用法的话,你可能会在使用的时候碰到很多问题。
本文从事件响应的列子开始,来试图说明this关键字的用法和一些知识。
Owner(宿主)
在余下的篇幅中,我们会一直围绕着一个函数来讨论,doSomething(),在这个方法中,this到底指向什么?
js 代码
1. function doSomething() {
2. this.style.color = '#cc0000';
3. }
在JavaScript中this是始终指向正在被执行的方法的“owner”(宿主),或者是包含这个方法的对象本身。如果我们在某个页面中定义了一个doSomething()函数,那么这个方法的owner则是这个页面,即当前window对象或JavaScript的全局对象。举个例子来说:一个“onclick”属性是被包含于某个HTML元素中的,那这个属性的owner就是这个HTML元素。
ownership(存在关系)是JavaScript的面向对象模型的产物。实际上对象都是以关联数组的形式来组织的。
js 代码
1. ------------ window --------------------------------------
2. | / / |
3. | | |
4. | this |
5. | ---------------- | |
6. | | HTML element | <-- this ----------------- |
7. | ---------------- | | doSomething() | |
8. | | | ----------------- |
9. | -------------------- |
10. | | onclick property | |
11. | -------------------- |
12. | |
13. ----------------------------------------------------------
当我们不做任何准备直接执行doSomething()函数的话,此时this是指向window对象的,然后方法试图改变window对象的style.color,当然,此时window对象并不存在这样一个style对象,所以该函数执行失败,并抛出一个JavaScript错误。
Copying(拷贝)
如果我们想要这个函数正常工作的话,我们就要让这个函数被包含在正确的HTML对象中。
换句话来说,就是我们要把这个函数“拷贝”到onclick属性上。然后传统的事件注册模型会自动处理余下的工作。
js 代码
1. element.onclick = doSomething;
这段代码把整个doSomething()函数拷贝到了某个HTML元素的onclick属性上(然后这个函数变成了一个成员方法)这时再单击该HTML元素时,事件响应会自动调用onclick属性绑定的方法,此时this已经指向了该HTML对象,然后方法顺利执行,改变了element元素的原色。
js 代码
1. ------------ window --------------------------------------
2. | |
3. | |
4. | |
5. | ---------------- |
6. | | HTML element | <-- this ----------------- |
7. | ---------------- | | doSomething() | |
8. | | | ----------------- |
9. | ----------------------- | |
10. | |copy of doSomething()| <-- copy function |
11. | ----------------------- |
12. | |
13. ----------------------------------------------------------
我们可以把这个函数拷贝到很多个HTML对象的事件响应函数中。然后每次运行的时候this就会指向正确的HTML对象。
js 代码
1. ------------ window --------------------------------------
2. | |
3. | |
4. | |
5. | ---------------- |
6. | | HTML element | <-- this ----------------- |
7. | ---------------- | | doSomething() | |
8. | | | ----------------- |
9. | ----------------------- | |
10. | |copy of doSomething()| <-- copy function |
11. | ----------------------- | |
12. | | |
13. | ----------------------- | |
14. | | another HTML element| <-- this | |
15. | ----------------------- | | |
16. | | | | |
17. | ----------------------- | |
18. | |copy of doSomething()| <-- copy function |
19. | ----------------------- |
20. | |
21. ----------------------------------------------------------
做完所有拷贝后,当函数被执行时,this就被自动指向到正确的响应这个事件的HTML对象上了,此时该HTML对象就包含了doSomething()这个函数的拷贝。
Referring(引用)
你还可以使用inline(内联)的方式来绑定这个函数,即在HTML文档中对HTML元素制定onclick属性。
代码
1. <element οnclick="doSomething()">
记住,此时你并没有拷贝这个函数!你只是指向了这个函数,这个差异是很不容忽视的。这时onclick属性并没有包含这个方法,只是包含了对这个方法的一个调用。
代码
1. doSomething();
此时当元素被单击时,代码的动作是“找到doSomething()方法,然后执行”。然后当我们找到并执行doSomething()方法时,this又被指向到了全局window对象,函数就会产生错误。
js 代码
1. ------------ window --------------------------------------
2. | / / |
3. | | |
4. | this |
5. | ---------------- | |
6. | | HTML element | <-- this ----------------- |
7. | ---------------- | | doSomething() | |
8. | | | ----------------- |
9. | ----------------------- / / |
10. | | go to doSomething() | | |
11. | | and execute it | ---- reference to |
12. | ----------------------- function |
13. | |
14. ----------------------------------------------------------
The difference(区别)
如果你要在事件响应中用this来访问HTML元素的话,你就必须保证this关键字已经写入到了onclick属性中。只有这样才能让this正确的指向HTML对象。所以你执行以下代码时:
js 代码
1. element.onclick = doSomething;
2. alert(element.onclick)
你会得到
js 代码
1. function doSomething()
2. {
3. this.style.color = '#cc0000';
4. }
就像alert的结果所展示的,this关键字已经存在于onclick方法中了,于是它就指向到了该HTML元素。
如果这样做:
js 代码
1. <element οnclick="doSomething()">
2. alert(element.onclick)
你会得到
js 代码
1. function onclick()
2. {
3. doSomething()
4. }
这只是一个包含doSomething()函数的调用,this关键字并不存在于onclick方法中,当然也不会指向HTML对象。
示例 - copying
下列情形中,this已经被写入了onclick方法:
js 代码
1. element.onclick = doSomething
2. element.addEventListener('click',doSomething,false)
3. element.onclick = function () {this.style.color = '#cc0000';}
4. <element οnclick="this.style.color = '#cc0000';">
示例 - referring
下列情形中,this指向的是window对象:
js 代码
1. element.onclick = function () {doSomething()}
2. element.attachEvent('onclick',doSomething)
3. <element οnclick="doSomething()">
注意attachEvent()这个方法。微软事件注册模型的主要缺点是attachEvent()只是创建一个函数的引用,而并没有拷贝函数。因此,有些时候它是完全不知道目前的事件是绑定在哪个HTML对象的。
Combination(结合)
当你使用内联方式注册事件时,你可以指定this引用作为参数传递给响应方法。
代码
1. <element οnclick="doSomething(this)">
2. function doSomething(obj) {
3. // this是存在于这个方法中的,只不过名字变成了obj
4. // obj此时就指向了正确的HTML对象,然后我们就可以继续操作了
5. obj.style.color = '#cc0000';
6. }
this 关键字的含义:可为以调用了其方法的那个对象生成相应的句柄。
thinking in java里面有这么一个例子
有两个同一个类型的对象,分别叫做a和b,那我们怎样区别在调用方法f()的时候,是谁再调用这个方法呢?
例如:
class Banana {
void f(int i){
/***方法主体*****/
}
}
Banana a = new Banana();//生成Banana的对象a
Banana b= new Banana();//生成Banana的对象b
a.f(1);
b.f(2);
那么编译器是怎样知道你是要调用哪个对象的f()函数呢?其实幕后的传送应该是:
a.f(1)<<====>>Banana.f(a,1);
b.f(1)<<====>>Banana.f(b,2);
我理解为:生成一个Banana的对象a,调用a的方法f()的时候,会同时生成一个指向这个对象的一个句柄this 。这里就是this 这个指向对象 new Banana()或者 this 在这里等价于句柄 a;this《==》a;
当我们在一个方法的内部的时候。并且希望获得当前对象的句柄,由于这个句柄是编译器秘密传递的,所以时没有明确的标志符来识别的,这个时候我们可以使用this这个关键字
this的通俗含义:不论是生成的哪个对象调用了这个方法,都会生成一个指向这个对象的指针 this
thinking in java 里面的经典例子:
public class Leaf{
private int i=0;
Leaf increment(){
i++;
return this;
}
void print(){
Systme.out.println("i="+i);
public static void main (String [] args)
{
Leaf x =new Leaf();
x.increment().increment(). increment().print();
}
}
1、生成一个对象的句柄 x ;语法格式为 Leaf x;
2、生成一个Leaf class的对象;语法格式为 new Leaf();
3、建立句柄与对象的联系 ;语法为 x = new Leaf();
4、调用对象 new Leaf()里面的方法 increment();语法为 x.increment()
谁调用了方法 increment()呢?是Leaf类的对象x(或者是new Leaf()),所以对应系统会生成一个this 引用,并把它秘密的指向 x 或者是 指向 new Leaf()这个对象,所以 increment()返回的是一个指向x的引用!是一个内存的地址,我们可以把它打印出来看看,就知道了!
在面向对象编程语言中,对于this关键字我们是非常熟悉的。比如C++、C#和Java等都提供了这个关键字,虽然在开始学习的时候觉得比较难,但只要理解了,用起来是非常方便和意义确定的。JavaScript也提供了这个this关键字,不过用起来就比经典OO语言中要"混乱"的多了。
下面就来看看,在JavaScript中各种this的使用方法有什么混乱之处?
1、在HTML元素事件属性中inline方式使用this关键字:
<div οnclick="
// 可以在里面使用this
">division element</div>
我们一般比较常用的方法是在此使用:javascirpt: EventHandler(this),这样的形式。不过这里其实可以写任何合法的JavaScript语句,要是高兴在此定义个类也可以(不过将会是个内部类)。这里的原理是脚本引擎生成了一个div实例对象的匿名成员方法,而onclick指向这个方法。
2、用DOM方式在事件处理函数中使用this关键字:
<div id="elmtDiv">division element</div>
<script language="javascript">
var div = document.getElementById('elmtDiv');
div.attachEvent('onclick', EventHandler);
function EventHandler()
{
// 在此使用this
}
</script>
这时的EventHandler()方法中的this关键字,指示的对象是IE的window对象。这是因为EventHandler只是一个普通的函数,对于attachEvent后,脚本引擎对它的调用和div对象本身没有任何的关系。同时你可以再看看EventHandler的caller属性,它是等于null的。如果我们要在这个方法中获得div对象引用,应该使用:this.event.srcElement。
3、用DHTML方式在事件处理函数中使用this关键字:
<div id="elmtDiv">division element</div>
<script language="javascript">
var div = document.getElementById('elmtDiv');
div.onclick = function()
{
// 在此使用this
};
</script>
这里的this关键字指示的内容是div元素对象实例,在脚本中使用DHTML方式直接为div.onclick赋值一个EventHandler的方法,等于为div对象实例添加一个成员方法。这种方式和第一种方法的区别是,第一种方法是使用HTML方式,而这里是DHTML方式,后者脚本解析引擎不会再生成匿名方法。
4、类定义中使用this关键字:
function JSClass()
{
var myName = 'jsclass';
this.m_Name = 'JSClass';
}
JSClass.prototype.ToString = function()
{
alert(myName + ', ' + this.m_Name);
};
var jc = new JSClass();
jc.ToString();
这是JavaScript模拟类定义中对this的使用,这个和其它的OO语言中的情况非常的相识。但是这里要求成员属性和方法必须使用this关键字来引用,运行上面的程序会被告知myName未定义。
5、为脚本引擎内部对象添加原形方法中的this关键字:
Function.prototype.GetName = function()
{
var fnName = this.toString();
fnName = fnName.substr(0, fnName.indexOf('('));
fnName = fnName.replace(/^function/, '');
return fnName.replace(/(^/s+)|(/s+$)/g, '');
}
function foo(){}
alert(foo.GetName());
这里的this指代的是被添加原形的类的实例,和4中类定义有些相似,没有什么太特别的地方。
6、结合2&4,说一个比较迷惑的this关键字使用:
function JSClass()
{
this.m_Text = 'division element';
this.m_Element = document.createElement('DIV');
this.m_Element.innerHTML = this.m_Text;
this.m_Element.attachEvent('onclick', this.ToString);
}
JSClass.prototype.Render = function()
{
document.body.appendChild(this.m_Element);
}
JSClass.prototype.ToString = function()
{
alert(this.m_Text);
};
var jc = new JSClass();
jc.Render();
jc.ToString();
我就说说结果,页面运行后会显示:"division element",确定后点击文字"division element",将会显示:"undefined"。
7、CSS的expression表达式中使用this关键字:
<table width="100" height="100">
<tr>
<td>
<div style="width: expression(this.parentElement.width);
height: expression(this.parentElement.height);">
division element</div>
</td>
</tr>
</table>
这里的this看作和1中的一样就可以了,它也是指代div元素对象实例本身。
8、函数中的内部函数中使用this关键字:
function OuterFoo()
{
this.Name = 'Outer Name';
function InnerFoo()
{
var Name = 'Inner Name';
alert(Name + ', ' + this.Name);
}
return InnerFoo;
}
OuterFoo()();
运行结果显示是:"Inner Name, Outer Name"。按我们在2中的讲解,这里的结果如果是"Inner Name, undefined"似乎更合理些吧?但是正确的结果确实是前者,这是由于JavaScript变量作用域的问题决定的,详细了解推荐参看"原来JScript中的关键字'var'还是有文章的"一文及回复。
说了这么多JavaScript中this的用法,其实this最根本的特性还是和OO语言中的定义相吻合的。之所以有这么多看似混乱的使用方式,是因为 JavaScript语言(解释器和语言本身的内容)本身在实现上是遵循OO的(Object-based),连它的所有数据类型都是对象,也有 Object这样一个super Object。但是这个语言在运行上(runtime),就没有遵循完备的OO特点,所以就出现了this的指代混乱。
1.静态方法什么时候初始化,在main前还是main后
在main方法后,静态方法是属于类的,只有在调用时才初始化(main例外,main的调用是在初始化工作完成后程序进入运行状态时),但静态方法在内存中只有一份;
2.构造函数与继承的关系
子类的构造函数内会包含一个父类构造函数,因为在子类构造函数第一行会默认调用父类构造函数,如果覆写该行则可以自行控制父类构造函数版本;可见得父类构造函数和子类构造函数得关系是“继承”不是“覆写”,(每个)子类构造函数继承(包含)父类构造函数的一个版本,并可以有自己的部分,类似继承,子类不完全继承父类方法并可由自己的方法,父类私有不能继承。
3.接口没有构造函数的原因
1.接口里的方法完全抽象构造函数没有实现体,无意义
2.接口为了实现多继承,子类构造函数必须调用父类构造函数,如果接口有构造函数子类不知道调用哪个父类构造函数
类的初始化顺序如下:
使用new(或其它方法)生成一个新对象时,虚拟机会先加载父类,同时执行父类的静态初始化,然后顺序向下加载子类并执行相应的静态初始化。当加载完后,虚拟机会在此时将所有的实例变量初始化为Java中的默认值(0,false等,不是程序中定义的默认值)。随后,准备执行构造方法体,执行构造方法体之前,会先调用父类的构造方法,再执行父类的构造方法体之前,会先初始化父类实例变量(初始化为程序中定义的默认值)。然后执行父类的构造方法体,接着再依次往回准备执行子类的构造方法体,同样,要先初始化子类的实例变量(初始化为程序中定义的默认值),最后执行子类的构造方法体。
1. 父类的静态初始化
2. 子类的静态初始化
3. 父类的实例变量
4. 父类的构造方法
5. 子类的实例变量
6. 子类的构造方法
总线是将计算机微处理器与内存芯片以及与之通信的设备连接起来的硬件通道。前端总线将CPU连接到主内存和通向磁盘驱动器、调制解调器以及网卡这类系统部件的外设总线。人们常常以MHz表示的速度来描述总线频率。
前端总线(FSB)频率是直接影响CPU与内存直接数据交换速度。由于数据传输最大带宽取决于所有同时传输的数据的宽度和传输频率,即数据带宽=(总线频率×数据位宽)÷8。目前PC机上所能达到的前端总线频率有266MHz、333MHz、400MHz、533MHz、800MHz, 1066MHz,1333MHz几种,前端总线频率越大,代表着CPU与内存之间的数据传输量越大,更能充分发挥出CPU的功能。现在的CPU技术发展很快,运算速度提高很快,而足够大的前端总线可以保障有足够的数据供给给CPU。较低的前端总线将无法供给足够的数据给CPU,这样就限制了CPU性能得发挥,成为系统瓶颈。
外频与前端总线频率的区别:前端总线的速度指的是数据传输的速度,外频是CPU与主板之间同步运行的速度。也就是说,100MHz外频特指数字脉冲信号在每秒钟震荡一千万次;而100MHz前端总线指的是每秒钟CPU可接受的数据传输量是100MHz×64bit=6400Mbit/s= 800MByte/s(1Byte=8bit)。
主板支持的前端总线是由芯片组决定的,一般都带有足够的向下兼容性。如865PE主板支持800MHz前端总线,那安装的CPU的前端总线可以是800MHz,也可以是533MHz,但这样就无法发挥出主板的全部功效。
硬件镜像主要就是利用多个一样磁盘(尤其是在磁盘阵列中),保证这多个磁盘的内容完全一样(同时往做镜像的磁盘中写入完全相同的内容),是通过硬件(比如说RAID卡)来实现的。软件镜像一般是利用特定的软件来实现。不管硬件镜像还是软件镜像,目的都是保证同样的一份数据有多份拷贝,使得万一在某一份拷贝出现问题时,数据不会丢失或很容易就恢复。镜像站点顾名思义就是像镜子一样,主力站点有什么变化,它也有什么变化。这只是个概念,具体实现不确定的。如果是人工同步的话,经常会主力站点更新了镜像站点还没有更新。也可以用程序同步。
接下来看看什么是宽带。
宽带网又称“宽频网路”或简称“宽频”。我们知道,虽然在短短几年间,拨号上网的速率就从 14.4Kbps上升到了 56Kbps,然而受限于电话线路的品质,56Kbps应该是一般 Modem 的极限了。要想获得更快的上网速度,势必得另劈溪径,因此近年来各式各样的宽带接入服务相继出现。那么,什么是宽带?其实并没有很严格的定义,一般是以目前拨号上网速率的上限 56Kbps为分界,将 56Kbps及其以下的接入称为“窄带”,之上的接入方式则归类于“宽带”
世界飞速地发展、网络改变了人们的生活;宽频(宽带)技术的相继推出,极大地提高了上网速度,其不可替代的作用对我们的网络生活的影响也越来越大------“光的速度,海的容量”,这是当今年宽带一直致力追求的目标。到目前为止,中国上网用户总数接近3000万。中国电信在加快建设 CHINANET骨干网的同时,加大力度发展光纤化的高速宽带城域网,从长远的战略角度出发、,构筑完整统一的宽带网络平台。
参考资料:PC脑电波
镜象就是一种文件形式,可以把许多文件做成一个镜象文件。比如你的系统,本来有很多文件,做成镜象后就一个文件,与GHOST等程序放在在一个盘里用GHOST等软件打开后,又恢复成许多文件,总之用镜象给你装系统就是原样复制一分现有系统的意思
镜像就是像照镜子一样。我们一般说的镜像是指给系统作个ghost镜像。这样可以在很短时间,很方便的还原出一个完整的系统来。镜像可以说是一种文件,比如iso,gho都属于镜像文件,镜像文件可以直接刻录到光盘中,也可以用虚拟光驱打开.
专业解释:镜像(Mirroring)是冗余的一种类型,一个磁盘上的数据在另一个磁盘上存在一个完全相同的副本即为镜像。分软件镜像与硬件镜像,它们的的区别就在于实现镜像所需的CPU周期所处的位置。最终,都是根据程序的指令,为硬件(磁盘,以及磁盘上存储的数据)制作一个镜像副本。镜像主要作备份用,镜像内容可以是系统、光盘、软件,网站,甚至服务器
Java基础
最新推荐文章于 2024-10-01 18:51:18 发布