2007年8月26日
定义一个长方形,求它的周长和面积。用面向对象的方法。
class 长方形 {
int
长;int
宽;
int 周长()
{
return 2*(长+宽);
}
int 面积()
{
return
长*宽;
}
public
static
void main(String[] args)
{
长方形 chang1=new 长方形();
长方形 chang2=new 长方形();
chang1.长=10;
chang1.宽=5;
System.out.println("周长="+chang1.周长());
System.out.println("面积="+chang1.面积());
chang2.长=20;
chang2.宽=8;
System.out.println("周长="+chang2.周长());
System.out.println("面积="+chang2.面积());
}
}
public
class Animal
{
int
height;
int
weight;
void animal()
{
System.out.println("Animal constract");
}
void eat()
{
System.out.println("Animal eat");
}
void sleep()
{
System.out.println("Animal sleep");
}
void breathe()
{
System.out.println("Animal breathe");
}
}
/*
* 理解继承是理解面向对象程序设计的关键
* 在java中,通过关键字extends继承一个已有的类,被继承的类称为父类(超类,基类),新的类称为子类(派生类)。
* * 在java中,不允许多继承
*/
class Fish extends Animal
{
void fish()
{
System.out.println("fish constract");
}
void breathe()
{
//super.breathe();
//super.height=40;
System.out.println("fish boo");
}
}
class Integration
{
public
static
void main(String[]args)
{
//Animal an=new Animal();
Fish fh=new Fish();
//an.breathe();
//fh.height=30;
fh.breathe();
}
}
/*
*在子类当中定义一个与父类同名,返回类型,参数类型均一致的方法,称为方法的覆盖
*方法的覆盖发生在子类和父类之间。
*调用父类的方法使用super
*/
/*特殊变量super,提供了父类的访问
* 可以使用super访问被父类被子类隐藏的变量或覆盖的方法
* 每个子类构造方法的第一句,都是隐藏的调用super(),如果父类没有这种形式的构造函数,那么在编译器中就会报错。
*
*
*
*/
静态方法和静态变量是属于某一个类,而不属于类的对象。
静态方法和静态变量的引用直接通过类名引用。
在静态方法中不能调用非静态的方法和引用非静态的成员变量。反之,则可以。
可以用类的对象obj去调用静态的方法method(),如:obj.method()。
Final在声明时需要进行初始化。
使用关键字final定义常量,例如:final double PI=3.1415926
作为一种约定,在定义常量时,通常采用大写的形式。
Final常量可以在声明的同时赋初值,也可以在构造函数中赋初值。
为了节省内存,我们通常将常量声明为静态的(static)
在声明为static时,就要在声明final常量时进行初始化。
static
final
double
//PI=3.1415926;
int
x,y;
point(int a,int b)
{
PI=3.1415926;
x=a;
y=b;
}
这种方式是错误的。
正确的方法如下:
static
final
double
PI=3.1415926;
This变量表示成员对象本身。
public
class point
{
int
x,y;
point(int a,int b)
{
x=a;
y=b;
}
point()
{
}
void output()
{
System.out.println(x);
System.out.println(y);
}
void output(int x,int y)
{
this.x=x;
this.y=y;
}
public
static
void main(String[] args)
{
point pt;
/*pt=new point();
{
pt.output();
}*/
pt=new point(3,3);
{
pt.output(5,5);
pt.output();
}
}
}
当类中有2个同名变量,一个属于类(类的成员变量),而另一个属于某个特定的方法(方法中的局部变量),使用this区分成员变量和局部变量。
使用this简化构造函数的调用。
public
class point
{
int
x,y;
point(int a,int b)
{
x=a;
y=b;
}
point()
{
this(1,1);
}
void output()
{
System.out.println(x);
System.out.println(y);
}
void output(int x,int y)
{
this.x=x;
this.y=y;
}
public
static
void main(String[] args)
{
point pt;
pt=new point();
pt.output();
}
}
我们使用一个不带参数的构造方法来调用带参数的构造方法,在不带参数的构造方法中使用this(1,1);this本身表示pt对象,他调用带参数的成员方法,来给x和y赋值。大大简化了调用方法。
在一个类中所有的实例(对象)调用的成员方法在内存中只有一份拷贝,尽管在内存中可能有多个对象,而数据成员(实例变量,成员变量)在类的每个对象所在的内存中都存在着一份拷贝。This变量允许相同的实例方法为不同的对象工作。每当调用一个实例方法时,this变量将被设置成引用该实例方法的特定的类对象。方法的代码接着会与this所代表的对象的特定数据建立关联。
面向对象的方法要先建一个类,这个类相当于一个模板,然后要为这个类实例化一个对象。然后对这个对象才能进行操作。
类具有状态和行为的方式。
状态就像人这个类的状态有身高和体重,行为有吃饭这个行为。
下面用一个点来说明
public
class
point
{
int
x,y;
void output()
{
System.out.println(x);
System.out.println(y);
}
public
static
void main(String[] args)
{
point pt;
pt=new
point();
{
pt.x=10;
pt.y=10;
pt.output();
}
}
}
构造函数,构造函数和类的方法类似。构造方法的名字和类名相同,并且没有返回值,构造方法主要为类的对象定义初始化状态。
我们不能直接调用构造函数,只能通过new关键字来调用从而创建类的实例
Java的类都要求有构造方法,如果没有定义构造方法,则java会默认使用一个缺省的方法,就是不带参数的方法。
public
class point
{
int
x,y;
point()
{
x=5;
y=10;
}
void output()
{
System.out.println(x);
System.out.println(y);
}
public
static
void main(String[] args)
{
point pt;
pt=new point();
{
pt.output();
}
}
}
对于构造方法,还可以使用参数的方法,在实例化对象的时候,直接传递参数就可以了
public
class point
{
int
x,y;
point(int a,int b)
{
x=a;
y=b;
}
void
output()
{
System.out.println(x);
System.out.println(y);
}
public
static
void main(String[] args)
{
point pt;
pt=new point(3,3);
{
pt.output();
}
}
}
New关键字的作用
为对象分配内存空间。
引起对象构造方法的调用。
为对象返回一个引用。
各种数据类型的默认值是:
数值型: 0
Boolean: false
Char: "\0"
对象: null
public
class point
{
int
x,y;
point(int a,int b)
{
x=a;
y=b;
}
void
output()
{
System.out.println(x);
System.out.println(y);
}
public
static
void main(String[] args)
{
point pt;
pt=new point(3,3);
{
pt.output();
}
}
}
输出是0 0
带参数的构造方法和不带参数的构造方法可以同时使用。只要参数类型或参数个数不同。在调用是是通过对指定参数类型和参数个数的方法来调用哪个构造方法。
这就是方法的重载(overload):重载构成的条件:方法的名称相同,但参数类型或参数个数不同,才能构成方法的重载。
public
class point
{
int
x,y;
point(int a,int b)
{
x=a;
y=b;
}
point()
{
}
void output()
{
System.out.println(x);
System.out.println(y);
}
public
static
void main(String[] args)
{
point pt;
pt=new point();
{
pt.output();
}
/*pt=new point(3,3);
{
pt.output();
}*/
}
}
这2种方法都是可以使用的。
Java中有3个移位运算符
左移: <<
带符号右移:>>
无符号右移:>>>
数 x x<<2 x>>2 x>>>2
17 00010001 01000100 00000100 00000100
-17 11101111 10111100 11111011 00111011
看一下程序0x表示16进制。ffffffff表示-1
public
class test {
public
static
void main(String[] args) {
int i=0xffffffff;
int c=i<<2;
System.out.println(i);
System.out.println(c);
}
}
输出是-1和-4.这表示
public
class test {
public
static
void main(String[] args) {
int i=0xffffffff;
int c=i<<2;
System.out.println(Integer.toHexString(i));
System.out.println(Integer.toHexString(c));
}
}
使用Integer.toHexString()将10进制转换位16进制。
输出位ffffffff 和fffffffc左移2位最后补2个0,最后的1100转换位16进制就是c
public
class test {
public
static
void main(String[] args) {
int i=0xffffffff;
int c=i>>>2;
System.out.println(Integer.toHexString(i));
System.out.println(Integer.toHexString(c));
}
}
无符号右移输出是ffffffff和3fffffff 右移2位后最左段是0011,转换位16进制就是3
练习:
将一个整数110从右端开始的4到7位变为0.
答:要想将4到7位变为0,先构造一个4到7位是0的数,然后用110和这个数与&。任何数和0与都是0,就完成了任务。要构造一个4到7位是0的数,先构造一个低4位是1的数15,然后将它左移3位,然后取反,就构造成4到7位是0的数了。程序如下。
public
class test {
public
static
void main(String[] args) {
int i=15;
int j=i<<3;
int c=~j;
int k=110;
int
l=k&c;
System.out.println(Integer.toBinaryString(i));
System.out.println(Integer.toBinaryString(j));
System.out.println(Integer.toBinaryString(c));
System.out.println(Integer.toBinaryString(k));
System.out.println(Integer.toBinaryString(l));
}
}
输出是
00001111
01111000
10000111
01101110
00000110
将一个数左移一位等于是将数*2,右移一位相当于将数/2。
左移2位相当与乘两次2,右移2位相当与除两次2.
& 按位与 都真才真
01101101
&
00110111
00100101
| 按位或 只要1个真就真,都假才假
01101101
|
00110111
01111111
^按位异或 一真一假才为真,都真都假就是假。
01101101
^
00110111
01011010
~按位取反 0变1,1变0
~01101101
10010010
在java中一个字节由8个二进位组成。
计算机中有原码,反码,和补码。
原码
将最高为作为符号位0正,1负。其余各位表示数值的绝对值。
+7的原码是 00000111
-7的原码是 10000111
原码的问题是+0和-0的表示
+0是00000000
-0是 10000000
2个数值不同。
反码
一个数如果为正,则它的反码与原码相同,如果为负,则符号位为1,其余取反。
+7是00000111
-7 是 11111000
反码的问题也是+0和-0的问题
+0是 00000000
-0 是 11111111
2个数值不同。
补码
利用溢出,我们将减法变成加法。 一个数如十进制,一个字节一个数,有8位,超过就进一。
一个数为正,则它的原码,反码,补码相同。如果为负,则符号位为1,其余对原码取反。然后加1
+7是 00000111
-7是 11111001
+0是00000000
-0是100000000,然后丢掉最高的9位则为00000000
和+0的表示相同,所以计算机中是采用的是补码。
已知一个负数的补码,转换为十进制。
- 先对各位取反。
- 将其转换为十进制数
- 加上负号,再减去1.
如 11111010 先取反
00000101 转换为十进制
是5 加上负号
是-5 再减去1
是-6
public
class Welcome {
public
static
void main(String[] args) {
for(int i=0;i<10;i++)
{System.out.println(i);
}
}
}
对于java中for语句中定义的变量的作用域只在{}内。For以外不能访问。这点和c语言不同,知道就可以了。
I++ 是先取出i的值,然后参与运算+1。
public
class Welcome {
public
static
void main(String[] args) {
int
i=3;
System.out.println(i++);
}
}
输出为3
++i是先+1,然后参与运算。
public
class Welcome {
public
static
void main(String[] args) {
int
i=3;
System.out.println(++i);
}
}
输出为4
下面这个例子说明了这个道理
public
class Welcome {
public
static
void main(String[] args) {
int i=3;
int count=(i++)+(i++)+(i++);
System.out.println(i);
System.out.println(count);
}
}
输出为6和12,i取了3次是6,count是3+4+5=12
public
class Welcome {
public
static
void main(String[] args) {
int
i=3;
int count=(++i)+(++i)+(++i);
System.out.println(i);
System.out.println(count);
}
}
输出为6和15,i取了3次是6,count是4+5+6=15
Java中,二维数组的定义和一维数组是一样的。
public class Welcome {
public static void main(String[] args) {
int [][] num;
num=new int[3][4];
num[0][1]=1;
num[1][3]=12;
num[2][2]=21;
}
}
Java中二维数组的列数可以不同,比如第一行是2列,第二行是4列,等等。
有些类似与c语言中的指针数组。
public class Welcome {
public static void main(String[] args) {
int [][] num;
num=new int[3][];
num[0]=new int[2];
num[1]=new int[4];
num[2]=new int[3];
num[0][1]=12;
num[1][3]=23;
num[2][2]=34;
System.out.println(num[0][1]);
System.out.println(num[1][3]);
System.out.println(num[2][2]);
}
}
在java中没有定义的自动赋值为0.
在定义时可以为二维数组来定义,但是在赋初值时 ,不要在定义大小了
int [][] num=new int[3][]{1,2,3,4,5,2,3,4,5,6} //error
public class Welcome {
public static void main(String[] args) {
int [][] num=new int[][]{1,2,3,4,5,2,3,4,5,6}; //error
int [][] num=new int[][]{{1,2,3,4,5},{2,3,4,5,6}}; //ok
}
}
定义二维数组还有一种方式
public class Welcome {
public static void main(String[] args) {
int [][] num={1,2,3,4,5,2,3,4,5,6}; //error
}
}
也可以定义不规则的二维数组
public class Welcome {
public static void main(String[] args) {
int [][] num={{1,2,3},{4,5},{2}};
System.out.println(num[0][2]);
System.out.println(num[1][1]);
System.out.println(num[2][0]);
}
}
在java中,不能使用像int num[3];这样的定义数组,在定义数组时不能分配空间的大小,只能通过为数组添加对象来分配空间。
public class Welcome {
public static void main(String[] args) {
int num[];
num=new int[3];
}
}
或者在定义时直接定义大小。
public class Welcome {
public static void main(String[] args) {
int num[]=new int[3];
}
}
Java中建议使用int[] num 这种方式这种方式定义了一个int类型的数组[],数组名称为num。
在定义时还可以直接初始化
public class Welcome {
public static void main(String[] args) {
int[] num={1,2,3};
}
}
但是这种方法只能在定义时进行。
public class Welcome {
public static void main(String[] args) {
int[] num=new int[]{1,2,3};
}
}
还可以使用new int方法来定义,如上
int[] num =new int[3]{1,2,3};这样的写法也是不允许的。不能分配空间大小。
最简单的方法是
public class Welcome {
public static void main(String[] args) {
int [] num;
num=new int[3];
num[0]=1;
num[1]=12;
num[2]=21;
System.out.println(num[0]);
System.out.println(num[1]);
System.out.println(num[2]);
}
}
对字符类型赋值使用单引号' ',
public class Welcome {
public static void main(String[] args) {
char ch;
ch='a';
System.out.println(ch);
}
}
输出为a
字符类型还可以直接使用整数来赋值,因为java中对字符类型使用的是uncode字符。
public class Welcome {
public static void main(String[] args) {
char ch;
ch=98;
System.out.println(ch);
}
}
输出为b
在java中小数常量被默认为double类型,如1.3默认为double类型。如果要声明为float类型,需要在之后加f,如1.3f
public class Welcome {
public static void main(String[] args) {
float f;
f=1.3f;
System.out.println(f);
}
}
输出为1.3
在java中boolean 布尔类型只有2个取值是true和false,不能赋值为1之类的整数。
public class Welcome {
public static void main(String[] args) {
boolean bool;
bool=true;
System.out.println(bool);
}
}
输出为true
在做条件判断的时候,不能再像c语言那样使用if(1)或where(1)这样的语句。
只能写为if(true)或where(true)这样。
Byte b;
b=3;
b=b*3;
System.out.pringln(b);
编译时会提示发现int类型,需要byte类型,这是因为b=b*3java会自动将参与运算的数据自动转换为int类型。如果要输出正确的数据则要进行强制类型转换。
b=(byte)(b*3);
这样才会对
public class Welcome
//声明public的类,应该作为文件名,一个源文件只能有1个或没有public的类
{
public static void main(String[] args)
{
System.out.print("你好\n");
//不加ln,不加换行。或者在之后加\n也是换行
System.out.println("欢迎使用java开发");
//输出命令,牢记!
}
}
对象的特征:状态(state)和行为(behabior)
人 身高,体重 吃饭,睡觉
现实世界对象的状态保存在软件对象的变量中,先是世界对象的行为通过软件对象的方法(函数)来实现、。
类和对象
把相似的对象归成一个类。
类就是模版定义了通用与一个特定种类的所有对象的状态(变量)和行为(方法)
类是创建对象的模版,对象是类的实例。
掌握面向对象的难点在于思路的转换,我们通常考虑解决问题的方法。而不是考虑将问题抽象成对象再去解决它。
编写一个驾驶汽车的方法
面向过程的程序设计: 编写一个方法,void drivercar();
面向对象的程序设计: 将一辆汽车看成一个对象,将所有汽车对象的共性抽取出来,设计一个类Car,
类中有一个方法void drive(),用Car这个类实例化一个具体的对象car,调用:car.drive().
new关键字的作用。
为对象分配内存空间,引起对象构造方法的调用。为对象返回一个引用。
构造方法的名字和类名相同,并且没有返回值。
构造方法主要用于为类的对象定义初始化状态。
我们不能直接调用构造方法,必须通过new关键字来自动调用,从而创建类的实例。
java的类都要求有构造方法,如果没有定义构造方法,java编译器会为我们提供一个缺省的构造方法,也就是不带参数的构造方法。
缺省构造方法默认值:数值 0
booeean false
char ”\0"
对象 null
方法的重载:重载构成的条件:方法的名称相同,但是参数类型或参数个数不同,才能构成方法的重载。
特殊变量this
this变量代表对象本身。
当类中有两个同名变量,一个属于类(类的成员变量),而另一个属于某个特定的方法(方法的局部变量),
使用this区分成员变量和局部变量
使用this简化构造函数的调用。可以通过不带参数的构造方法调用带参数的构造方法。
Point(int a,int b)
{
x=a;
y=b;
}
Point()
{
this(1,2);
}
一个类所有的实力(对象)调用的成员方法在内存中只有一份拷贝,尽管在内存中可能有多个对象,
而数据成员在类的每个对象所在内存中都存在这一份拷贝。this变量允许相同的实例方法为不同的对象工作。
每当调用一个实例方法时,this变量将被设置成引用改实例方法的特定的类对象。方法的代码接着会与this所代表的特定数据建立关联。
内存模型 的概念
静态方法和静态变量时属于某一个类,而不属于类的对象。
静态方法和静态变量的引用直接通过类名引用。
在静态方法中不能调用非静态的方法和引用非静态的成员变量。反之,则可以。
可以用类的对象obj去调用静态的方法method(),如 obj。method()。
final定义的变量要在定义时初始化也可以放在构造函数中实现
常量通常定义为静态的,是为了节省内存。这时就要在定义时初始化。
final定义的常量一般默认用大写。
继承
继承是面向对象的关键
在java中,通过关键字extends继承一个已有的类,被继承的称为父类(超类,基类),新的类称为子类(派生类)。
在java中,不允许多继承。
方法的覆盖
在子类中定义一个与父类同名、返回类型、参数类型均相同的一个方法,称为方法的覆盖。覆盖发生在子类与父类之间。
class Animal
{
int height,weight;
void eat()
{
System.out.println("animal eat");
}
void breathe()
{
System.out.println("animal breathe");
}
void sleep()
{
System.out.println("animal sleep");
}
}
class Fish extends Animal
{
void breathe()
{
System.out.println("fish bubble");
}
}
class Integration
{
public static void main(String[] args)
{
Animal an=new Animal();
Fish fh= new Fish();
an.breathe();
fh.height=30;
fh.breathe();
}
}
特殊变量super,提供了对父类的访问。
可以使用super访问父类被子类隐藏的变量或覆盖的方法。
每个子类构造方法的第一条语句,都是隐含的调用super(),如果父类没有这种形势的构造函数,那么在编译的时候就会报错。
class Animal
{
int height,weight;
void eat()
{
System.out.println("animal eat");
}
void breathe()
{
System.out.println("animal breathe");
}
void sleep()
{
System.out.println("animal sleep");
}
}
class Fish extends Animal
{
void breathe()
{
super.breathe();
super.height=40;
System.out.println("fish bubble");
}
}
class Integration
{
public static void main(String[] args)
{
//Animal an=new Animal();
Fish fh= new Fish();
//an.breathe();
fh.height=30;
fh.breathe();
}
}
多态性,子类有就调用子类的。没有就调用父类的
instanceof
比较一个实例是否是一个类的实例