类 class
类名的规则
- 如果类名使用拉丁字母,那么名字的首字母使用大写字母
- 当类名由几个“单词”复合而成时,每个单词的首字母应大写
对象:
用类声明的变量被称为对象
在用类声明对象后,还必须要创建对象,即为声明的对象分配所拥有的变量(确定对象所具有的属性)
实例:
当使用一个类创建一个对象时,也称给出了这个类的一个实例
类的目的:
是抽象出一类事物的属性和行为,并用一定的语法格式来描述所抽象出的属性和行为
方法:
方法可以对类中声明的变量进行操作,即给出算法(体现对象所具有的行为)
成员变量:类中声明的变量
局部变量:
在方法体中声明的变量和方法的参数被称为局部变量,局部变量只在方法内有效
如果局部变量的声明是在一个复合语句中,那么该局部变量的有效范围是该复合语句
如果局部变量的声明是在一个循环语句中,那么该局部变量的有效范围是该循环语句
- 如果局部变量和成员变量的名字相同,则成员变量被隐藏,即该成员变量在这个方法内暂时失效,如果想在该方法中使用被隐藏的成员变量,必须使用关键字
this
- 成员变量有默认值,未定义时默认为0,但局部变量没有默认值,在使用局部变量之前,必须保证局部变量有具体的值
- 对成员变量的操作只能放在方法中,方法使用各种语句对成员变量和方法体中声明的局部变量进行操作
如下允许:
class A {
int a = 12; // 声明的同时赋予初值
float b = 12.56f;
}
不允许
class A {
int a;
float b;
a = 12; //非法,这是赋值语句(语句不是变量的声明,只能出现在方法体中)
b = 12.56;
}
构造方法:
类中的构造方法的名字必须与它所在的类的名字完全相同,而且没有类型
class Point{
int x,y;
Point() { //是构造方法
x=1;
y=1;
}
Point(int a, int b){ //是构造方法
x=a;
y=b;
}
void Point(int a, int b){ //不是构造方法 (该方法的类型是void)
x=a;
y=b;
}
int Point(){ //不是构造方法 (该方法的类型是void)
return 12;
}
}
创建对象
创建一个对象包括对象的声明和为对象分配变量两个步骤
-
对象的声明
类的名字 对象名字;
-
为声明的对象分配变量
使用new
运算符和类的构造方法为声明的对象分配变量,即创建对象
如果类中没有构造方法,系统会调用默认的构造方法,默认的构造方法是无参数的,且方法体中没有语句
如果类中定义了一个或多个构造方法,那么Java不提供默认的构造方法,即p1=new Point(); //该方法创建对象时非法的
举例
class XiyoujiRenwu{
float height,weight;
String head,ear;
void speak(String s) {
head = "歪着头";
System.out.println(s);
}
}
public class Example4_3 {
public static void main(String args[]) {
XiyoujiRenwu zhubajie,sunwukong; //声明对象
zhubajie = new XiyoujiRenwu(); //为对象分配变量(使用new和默认的构造方法)
sunwukong = new XiyoujiRenwu();
zhubajie.height = 1.80f; //对象给自己的变量赋值
zhubajie.head = "大头";
zhubajie.ear = "一双大耳朵";
sunwukong.height = 1.62f; //对象给自己的变量赋值
sunwukong.weight = 1000f;
sunwukong.head = "秀发飘飘";
System.out.println("猪八戒的身高:"+zhubajie.height);
System.out.println("猪八戒的头:"+zhubajie.head);
System.out.println("孙悟空的重量:"+sunwukong.weight);
System.out.println("孙悟空的头:"+sunwukong.head);
zhubajie.speak("俺老猪我想取媳妇"); //对象调用方法
System.out.println("猪八戒现在的头:"+zhubajie.head);
sunwukong.speak("老孙我重1000斤,我想骗八戒背我"); //对象调用方法
System.out.println("孙悟空现在的头:"+sunwukong.head);
}
}
对象的内存模式:
- 当用XiyoujiRenwu类声明一个变量zhubajie,即对象zhubajie时, 如
XiyoujiRenwu zhubajie;
,声明对象zhubajie后,zhubajie的内存中还没有任何数据,称这时的zhubajie是一个空对象,空对象不能使用,因为它还没有得到任何“实体”,必须再进行为对象分配变量的步骤,即为对象分配实体 - 对象分配变量后的内存模式
即当系统见到zhubajie = new XiyoujiRenwu();
就会做如下两件事
a. 为 height,weight,hear,ear 各个变量分配内存,即 XiyoujiRenwu 类的成员变量被分配内存空间,然后执行构造方法中的语句。如果成员变量在声明时没有指定初值,所使用的构造方法也没有对成员变量进行初始化操作
整型的成员变量,默认初值是0
浮点型的成员变量,默认初值是0.0
boolean型的成员变量,默认初值是false
引用型的成员变量,默认初值是null
b. 给出一个信息,以确保这些变量时属于对象zhubajie的,即这些内存单元将由zhubajie操作。为了做到这一点,new运算符在为变量height,weight,head,ear分配内存后,将返回一个引用给对象变量zhubajie
c. 创建多个不同对象
一个类通过使用new运算符可以创建多个不同的对象,这些对象将被分配不同的内存空间,因此,改变其中一个对象的状态不会影响其他对象的状态
使用对象
- 对象操作自己的变量(体现对象的属性)
对象.变量;
- 对象调用类中的方法 (体现对象的行为)
对象.方法;
- 体现封装
当对象调用方法时,方法中出现的成员变量就是指分配给该对象的变量
当对象zhubajie调用方法speak之后,就将自己的头(head变量),改写成:“歪着头”
当对象sunwukong调用方法speak之后,就将自己的头(head变量),改写成:“歪着头”
class Point{
int x,y;
void setXY(int m, int n) {
x = m;
y = n;
}
}
public class Example4_4 {
public static void main(String args[]) {
Point p1,p2;
p1 = new Point();
p2 = new Point();
System.out.println("p1的引用:"+p1);
System.out.println("p2的引用:"+p2);
p1.setXY(1111, 2222);
p2.setXY(-100, -200);
System.out.println("p1的x,y坐标:"+p1.x+","+p1.y);
System.out.println("p2的x,y坐标:"+p2.x+","+p2.y);
p1 = p2;
System.out.println("将p2的引用赋值给p1后:");
System.out.println("p1的引用:"+p1);
System.out.println("p2的引用:"+p2);
System.out.println("p1的x,y坐标:"+p1.x+","+p1.y);
System.out.println("p2的x,y坐标:"+p2.x+","+p2.y);
}
}
例题5:
Rect.java
public class Rect {
double width; //梯形的宽
double height; //梯形的高
double getArea() {
double area = width*height;
return area;
}
}
Lader.java
public class Lader {
double above; //梯形的上底
double bottom; //梯形的下底
double height; //梯形的高
double getArea() {
return (above+bottom)*height/2;
}
}
Example4_5.java
public class Example4_5 {
public static void main(String args[]) {
Rect ractangle = new Rect();
ractangle.width = 109.87;
ractangle.height = 25.18;
double area = ractangle.getArea();
System.out.println("矩形的面积:"+area);
Lader lader = new Lader();
lader.above = 10.798;
lader.bottom = 156.65;
lader.height = 18.12;
area = lader.getArea();
System.out.println("梯形的面积:"+area);
}
}
参数传值
方法中最重要的部分之一就是方法的参数,参数属于局部变量,当对象调用方法时,参数被分配内存空间,并要求调用者向参数传递值,即方法被调用时,参数变量必须有具体的值
例6
Example4_6.java
class Computer {
int add(int x, int y) {
return x+y;
}
}
public class Example4_6 {
public static void main(String args[]) {
Computer com = new Computer();
int m = 100;
int n = 200;
int result = com.add(m,n); //将m,n的值“传值”给参数x,y
System.out.println(result);
result = com.add(100+m, n*10+8); //将表达式 120+m 和 n*10+8 的值,“传值”给参数x,y
System.out.println(result);
}
}
引用类型参数的传值
当参数是引用类型时,“传值"传递的是变量中存放的"引用”,而不是变量所引用的实体
依赖关系 虚线
如果A类中某个方法的参数是用B类声明的对象或某个方法返回的数据类型是B类对象,那么A和B的关系是依赖关系,称A依赖B。如果A和B的关系是依赖关系,称A依赖于B。如果A依赖于B,那么UML通过使用一个虚线连A和B的UML图,虚线的起始端是A的UML图,终点端是B的UML图,但终点端是使用了一个指向B的UML图的方向箭头表示虚线的结束
例7
Battery.java
public class Battery {
int electricityAmount;
Battery(int amount) {
electricityAmount = amount;
}
}
Radio.java
public class Radio {
void openRadio(Battery battery) {
battery.electricityAmount = battery.electricityAmount - 10; //消耗了电量
}
}
Example4_7.java
public class Example4_7 {
public static void main(String args[]) {
Battery nanfu = new Battery(100); //创建电池对象
System.out.println("南孚电池的储电量是:"+nanfu.electricityAmount);
Radio radio = new Radio(); //创建收音机对象
System.out.println("收音机开始使用南孚电池");
radio.openRadio(nanfu); //打开收音机
System.out.println("目前南孚电池的储电量是:"+nanfu.electricityAmount);
}
}
例8
关联关系: 实线
如果A类中成员变量是用B类声明的对象,那么A和B的关系就是关联关系,称A类的对象关联于B类的对象或A类的对象组合了B类的对象。
如果A关联于B,那么UML通过一个实线连A和B的UML图,实线的起始端是A的UML图,终点端是B的UML图,但终点端使用了一个指向B的UML图的方向箭头表示实线的结束
Circle.java
public class Circle {
double radius,area;
Circle(double r) {
radius = r;
}
void setRadius(double r) {
radius = r;
}
double getRadius() {
return radius;
}
double getArea() {
area = 3.14*radius*radius;
return area;
}
}
Circular.java
public class Circular {
Circle bottom; //圆锥的底bottom是Circle类型的对象
double height;
Circular(Circle c, double h) { //构造方法,将Circular类的实例的引用传递给bottom
bottom = c;
height = h;
}
double getVolme() {
return bottom.getArea()*height/3.0;
}
double getBottomRadius() {
return bottom.getRadius();
}
public void setBottomRadius(double r) {
bottom.setRadius(r);
}
}
Example4_8.java
public class Example4_8 {
public static void main(String args[]) {
Circle circle = new Circle(10);
System.out.println("main方法中circle的引用:"+circle);
System.out.println("main方法中circle的半径:"+circle.getRadius());
Circular circular = new Circular(circle,20);
System.out.println("circular圆锥的bottom的引用:"+circular.bottom);
System.out.println("圆锥的bottom的半径:"+circular.getBottomRadius());
System.out.println("圆锥的体积:"+circular.getVolme());
double r = 8888;
System.out.println("圆锥更改底圆bottom的半径:"+r);
circular.setBottomRadius(r);
System.out.println("圆锥的bottom的半径:"+circular.getBottomRadius());
System.out.println("圆锥的体积:"+circular.getVolme());
System.out.println("main方法中circle的半径:"+circle.getRadius());
System.out.println("main方法中circle的引用将发生变化");
circle = new Circle(1000); //重新创建circle
System.out.println("现在main方法中circle的引用:"+circle);
System.out.println("main方法中circle的半径:"+circle.getRadius());
System.out.println("但是不影响circular圆锥的bottom的引用:");
System.out.println("circular圆锥的bottom的引用:"+circular.bottom);
System.out.println("圆锥的bottom的半径:"+circular.getBottomRadius());
}
}
例9
SIM.java
public class SIM {
long number;
SIM(long number) {
this.number = number;
}
long getNumber() {
return number;
}
}
MobileTelephone.java
public class MobileTelephone {
SIM sim;
void setSIM(SIM card) {
sim = card;
}
long lookNumber() {
return sim.getNumber();
}
}
Example4_9.java
public class Example4_9 {
public static void main(String args[]) {
SIM simOne = new SIM(13889776509L);
MobileTelephone mobile = new MobileTelephone();
mobile.setSIM(simOne);
System.out.println("手机号码:"+mobile.lookNumber());
SIM simTwo = new SIM(15967563567L);
mobile.setSIM(simTwo); //更换SIM卡
System.out.println("手机号码:"+mobile.lookNumber());
}
}
例10
Lader.java
public class Lader {
double 上底, 高; //实例变量
static double 下底; //类变量
void 设置上底(double a) {
上底 = a;
}
void 设置下底(double b) {
下底 = b;
}
double 获取上底() {
return 上底;
}
double 获取下底() {
return 下底;
}
}
Example4_10.java
public class Example4_10 {
public static void main(String args[]) {
Lader.下底 = 100; //Lader的字节码被加载到内存,通过类名操作类变量
Lader laderOne = new Lader();
Lader laderTwo = new Lader();
laderOne.设置上底(28);
laderTwo.设置上底(66);
System.out.println("laderOne的上底:" + laderOne.获取上底());
System.out.println("laderOne的下底:" + laderOne.获取下底());
System.out.println("laderTwo的上底:" + laderTwo.获取上底());
System.out.println("laderTwo的上底:" + laderTwo.获取下底());
}
}
例11
Example4_11.java
import java.util.*;
public class Example4_11 {
public static void main(String args[]) {
Scanner scanner = new Scanner(System.in);
int [] a = {12,34,9,23,45,6,45,90,123,19,34};
Arrays.sort(a);
System.out.println(Arrays.toString(a));
System.out.println("输入整数,程序判断该整数是否在数组中:");
int number = scanner.nextInt();
int index = Arrays.binarySearch(a,number);
if (index>=0)
System.out.println(number+"和数组中索引为"+index+"的元素值相同");
else
System.out.println(number+"不与数组中任何元素值相同");
}
}
Java中存在两种多态: 重载(Overload )和重写(Override)
方法重载
一个类中可以有多个方法具有相同的名字,但这些方法的参数必须不同。两个方法的参数不同是指满足下列之一:
- 参数的个数不同
- 参数个数相同,但参数列表中对应的某个参数的类型不同
例12
Example4_12.java
class People {
float hello(int a, int b) {
return a+b;
}
float hello(long a, int b) {
return a-b;
}
double hello(double a,int b) {
return a*b;
}
}
public class Example4_12 {
public static void main(String args[]) {
People tom = new People();
System.out.println(tom.hello(10,20));
System.out.println(tom.hello(10L,20));
System.out.println(tom.hello(10.0,20));
}
}
例13
Circle.java
public class Circle {
double radius,area;
void setRadius(double r) {
radius = r;
}
double getArea() {
area = 3.14*radius*radius;
return area;
}
}
Tixing.java
public class Tixing {
double above,bottom,height;
Tixing(double a, double b, double h) {
above = a;
bottom = b;
height = h;
}
double getArea() {
return (above+bottom)*height/2;
}
}
Student.java
public class Student {
double computerArea(Circle c) { //是重载方法
double area = c.getArea();
return area;
}
double computerArea(Tixing t) { //是重载方法
double area = t.getArea();
return area;
}
}
Example4_13.java
public class Example4_13 {
public static void main(String args[]) {
Circle circle = new Circle();
circle.setRadius(196.87);
Tixing lader = new Tixing(3,21,9);
Student zhang = new Student();
System.out.println("zhang计算圆的面积:");
double result = zhang.computerArea(circle);
System.out.println(result);
System.out.println("zhang计算梯形的面积:");
result = zhang.computerArea(lader);
System.out.println(result);
}
}
this 关键字
this 是Java的一个关键字,表示某个对象。this 可以出现在实例方法和构造方法中,但不可以出现在类方法中。
this 关键字出现在类的构造方法中时,代表使用该构造方法所创建的对象
- 实例方法只能通过对象来调用,不能用类名来调用。当this关键字出现在实例方法时,this就代表正在调用该方法的当前对象对象
- 通常情况下,可以省略实例成员变量名字前面的“this”以及static变量前面的“类名”
但是,当实例成员变量的名字和局部变量的名字相同时,成员变量前面的“this.”或“类名.”就不可以省略
例14
public class People {
int leg,hand;
String name;
People(String s) {
name = s;
this.init(); //可以省略this,即将this.init();写成init();
}
void init() {
leg = 2;
hand = 2;
System.out.println(name+"有"+hand+"只手"+leg+"条腿");
}
public static void main(String args[]) {
People boshi = new People("布什"); //创建boshi时,构造方法中的this就是对象boshi
}
}
访问权限
所谓访问权限:是指对象是否可以通过.
运算符操作自己的变量或通过 .
运算符调用类中的方法
private 用此关键词修饰的成员变量和方法称为私有变量和私有方法
当我们用某个类在另外一个类中创建对象后,如果不希望该对象直接访问自己的变量,即通过.
运算符来操作自己的成员变量,就应该将该成员变量访问权限设置为private
如果A类中的某个成员是私有类变量(静态成员变量),那么在另外一个类中,不能通过类名A来操作这个私有类变量
如果A类中某个方法是私有的类方法,那么在另外一个类中,也不能通过类名A来调用这个私有的类方法
public 共有变量和共有方法
如果A类中的某个成员是public类变量,那么在另外一个类中,也可以通过类名A来操作A的这个类的成员变量
如果A类中的某个方法是public类变量,那么在另外一个类中,也可以通过类名A来调用A类中的public类方法
protected 受保护的成员变量和成员方法
如果在另外一个类中用类A创建了一个对象后,如果这个类与类A在同一个包中,那么该对象能访问自己的protected变量和protected方法
任何一个与A在同一包中的类也可以通过A类的类名访问A类的protected类变量和protected类方法
友好变量、友好方法 不同private,public,protected修饰的成员变量和方法
如果在另外一个类中用类A创建了一个对象后,如果这个类与A类在同一个包中,那么该对象能访问自己的友好变量和友好方法。
在任何一个与A同包的类中,也可以通过A类的类名访问A类的类友好变量和类友好方法
子类 中介绍 protected 与 友好之间的区别
public类 与 友好类 之间的区别
class 前有 public 关键词修饰的,叫public类
class 前没有 public 关键词修饰的,叫友好类
不能用 protected 和 private 修饰类
访问权限从高到底的排序 public , protected, 友好的, private