第四章 Java面向对象1
此笔记通过观看【尚学堂】+《Java程序设计(赖小平主编)清华大学出版社》整理得出
4.1对象和类的概念
- 类的概念:
类是具有相同特征(属性)和相同行为(方法)的事物的描述。类是一个抽象的概念,类似于造船、造车的设计图纸。例如:设计一个人类。人类有共同同的属性:姓名、性别、年龄、身高、体重。类只是描述特征的结构和类型,不指定具体值。除了描述一类事物的特征外,还包含该事物共有的功能(行为)。如:人可以说话、吃东西、走路、睡觉。
- 对象的概念:
对象实际存在的该类事物的每个个体,也成实例。
两者的关系:对象是类的实例,类是对象的模板
面向对象的三大特征:继承、封装、多态
4.2类的定义
【语法格式:】
访问修饰符 class 类{ [成员变量] [构造器声明] [成员方法声明] }
类可以包括成员变量、构造方法、成员方法、内部类,甚至包括代码块
【实例 定义一个人(person)类】
package objectClassTest;
public class Person {
//定义属性
String name;
int age;
double hight;
double wight;
//定义构造方法,不写系统自动生成
public Person() {
}
//定义成员方法
public void walk() {
System.out.println("人在走路...");
}
public void talk() {
System.out.println("人在说话...");
}
//系统输入
public static void main(String[] args) {
//创建对象
Person a1 = new Person();
a1.name = "卫善";
a1.age = 18;
a1.talk();
}
}
结果:
人在说话…
构造方法:用于创建类的对象(可以直接给变量赋值),无参的构造方法可以由系统生成,名称一定要跟类名一样。
说明:
通常类名要有意义,首字母要大写。
创建java自定义类的步骤如下:
1、 用关键字class定义类(考虑修饰符、类名)
2、 编写类的属性(考虑修饰符、属性类型、属性名和初始化值)
3、 编写类的构造器(考虑修饰符和形参)
4、 编写类的方法(考虑修饰符、返回值类型、方法名和形参等)
4.2.1内存分析
Java虚拟机的内存可以分为三个区域:栈stack、堆heap、方法区method area。
- 栈的特点:
1、 栈描述的是方法执行的内存模板。每个方法被调用都会创建一个栈帧
2、 Jvm为每个线程创建一个栈,用于存放该线程执行方法的信息。
3、 栈属于线程私有,不能实现线程间的共享。
4、 存储特征是“先进后出,后进后出”。
5、 栈由系统自动分配,速度快,是一个连续的内存空间。
思考:存放对象的地址
- 堆的特点:
1、 堆用于存储创建好的对象和数组
2、 Jvm只有一个堆,被所有线程共享
3、 堆是一个不连续的内存空间,分配灵活,速度慢。
方法区(又叫静态区)特点:
1、 jvm只有一个方法区,被所有线程共享
2、 方法区实际也是堆,只是用于存储类、常量相关的信息
3、 用来存放程序中永远是不变或唯一的内容。(类常量、class对象、静态变量、字符串常量等)
【实例】
4.2.2构造方法
【语法格式:】
访问修饰符 构造方法名([参数列表])[throws 子句]{ 方法体
}
说明:
1、 访问修饰符通常使用public,因为构造方法主要提供给其它类调用
2、 构造方法名必须与类名相同,注意大小写
3、 构造也可以不带参数,也可以带多个参数,不带参数时不写时,系统自动生成
4、 构造方法不显示声明返回类型,也不能使用void声明
5、 通过new关键字调用!!一个对象只能调用一次构造方法。
6、 不能在构造器使用return返回某个值
7、 构造方法可以重载,重载原则与普通方法相同
【实例 创建一个圆类】
package objectClassTest;
/**
* 构造方法
* @author 卟淡
*
*/
public class Circle {
private double radius;
private static final double PI = 3.14;
//带参构造方法,不能加返回值的return。可加return,退出方法
public Circle(double radius)throws Exception {
if(radius<=0)throw new Exception("半径不能小于0");
this.radius = radius; //也可以写成this.setRadius(radius);
}
public void setRadius(double radius)throws Exception{
if(radius<=0)throw new Exception("半径不能小于0");
this.radius = radius;
}
public double getRadius() {
return radius;
}
public double getArea() {
return PI*radius*radius;
}
public double getGirth() {
return 2*PI*radius;
}
public static void main(String[] args) {
try {
Circle a = new Circle(2.9);
System.out.println(a.getArea());
} catch (Exception e) {
e.printStackTrace();
}
}
}
注:此题运用封装知识、抛出异常知识。
4.2.3对象的创建与关键字this
通过new创建对象(new→开辟新的堆空间)
【语法格式:】
类名 对象名 = new 类名();
不定义对象名的成为匿名对象 格式:
new 类名().调用的方法名称
创建一个对象分为如下四步:
1、 分配对象空间,并将对象成员变量初始化为0或空值。
2、 执行属性值显式初始化
3、 执行构造方法
4、 给对象属性赋值
- This关键字
关键字this指代当前对象。在内部类使用this作为前缀,引用成员变量、调用构造方法和调用成员方法。
this的本质就是“创建好的对象的地址”!由于在构造方法调用前,对象已经创建。因此,在构造方法中也可以使用this代表“当前对象”。
- 1、引用成员变量
语法格式:
this.成员变量名
当一个方法定义了和成员变量同名的变量时,为了区分成员变量和局部变量,在变量前加上前缀this。创建一个圆类时,定义的构造方法其参数radius与成员变量radius同名,引用成员变量用使用this.radius。
- 2、调用成员方法
语法格式:
this.成员方法名(参数列表)
【如4.2.2实例定义的一个构造方法,其主要功能是给半径设置值,类中的setRadius()方法用于设置半径值。故构造方法可修改为:】
- 3、 调用构造方法
this.构造方法名(参数列表);
调用构造方法的原则:
(1)在构造方法中使用this关键字时,必须作为构造方法的第一条语句。
(2)只能在构造方法中使用this关键字来调用其它类中的其他构造方法。
(3)只能用this关键字调用其它构造方法,不能使用方法名直接调用构造方法。
【实例 构造方法重载时this关键字的使用】
package objectClassTest;
public class TestThis {
int a,b,c;
public TestThis(int a,int b) {
this.a = a;
this.b = b;
}
public TestThis(int a,int b,int c) {
this(a,b);
//也可以写成this.a=a\this.b=b\this.c=c
//这样可以简化开头
this.c = c;
}
void sing() {
System.out.println("别唱歌了!");
}
void eat() {
this.sing();//调用本类的sing();
System.out.println("吃饭啦!");
}
public static void main(String[] args) {
TestThis c = new TestThis(2,3);
c.eat();
}
}
结果:
别唱歌了!
吃饭啦!
4.2.4 关键字static
关键字static是静态的意思。在类的内部可以用static修饰属性、方法,还可以定义代码块,被修饰的元素是属于类,被类的所有对象共享。
- 1、 类属性
用关键字static修饰的属性成为类属性,也可以叫静态属性、静态字段或静态变量。
无static修饰的叫实例属性、实例变量或实例子段。
不同点:
实例属性是在创建对象的时候初始化值,每个实例化属性归各个对象所有,互不影响。而静态属性是在JVM加载类后分配内存空间时初始化,被该类的对象共享。类属性直接使用类名来引用:类名.类属性。
- 2、 类方法
Static修饰的方法为静态方法或类方法,无static修饰的为实例方法。
调用类方法语法格式:
类名.类方法名(参数列表)
- 3、 静态初始化块
一般用于显示初始化类属性,代码块仅在JVM加载类到内存中时执行一次,以后不再执行。
【实例 测试类属性、类方法】
package objectClassTest;
public class StaticTest {
private String name;
private static String type = "狗";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static void PrintType(){
//不能调用非静态成员
System.out.println(type);
}
public static void main(String[] args) {
StaticTest c = new StaticTest();
c.name = "小黑";
StaticTest.PrintType();
StaticTest.type = "猫";
StaticTest.PrintType();
}
}
结果:
狗
猫
【实例 测试初始化块】
package objectClassTest;
public class StaticTest02 {
private String name;
private static String type;
static {
type = "猫类";
System.out.println("Jvm已加载StaticTest02类");
System.out.println("StaticTest02类型为:"+type);
}
public StaticTest02(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static void main(String[] args) {
StaticTest02 c1 = new StaticTest02("小黑");
System.out.println(c1.getName());
}
}
JVM加载该类时,首先执行static代码块,初始化类属性type
结果:
Jvm已加载StaticTest02类
StaticTest02类型为:猫类
小黑
4.2.5类与对象的测试实例
【实例 设计一个学生类,包括学生的三项成绩:计算机、数学、英语要求可以求总分、平均分、最高分和最低分,并且可以输出学生的完整信息。】
package objectClassTest;
/**
* 设计一个学生类,包括学生的三项成绩:计算机、数学、英语
* 要求可以求总分、平均分、最高分和最低分,并且可以输出学生
* 的完整信息。
* @author 卟淡
*
*/
public class Testclass01 {
private String name;
private long id;
private float computer;
private float math;
private float English;
public Testclass01() {
}
public Testclass01(String name,long id,float computer,float math
,float English) {
this.name = name;
this.id = id;
this.computer = computer;
this.math = math;
this.English = English;
}
public float sum() {
return computer + math + English;
}
public float avg() {
return sum()/3;
}
public float max() {
float max = computer>math?computer:math;
max = max>English?max:English;
return max;
}
public float min() {
float min = computer<math?computer:math;
min = min<English?min:English;
return min;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public float getComputer() {
return computer;
}
public void setComputer(float computer) {
this.computer = computer;
}
public float getMath() {
return math;
}
public void setMath(float math) {
this.math = math;
}
public float getEnglish() {
return English;
}
public void setEnglish(float English) {
this.English = English;
}
public String show() {
return "-学生基本信息-"+"\n"+"姓名:"+name+"\n"+"学号:"+id+"\n";
}
public static void main(String[] args) {
//第一个学生成绩表
Testclass01 student01 = new Testclass01();
student01.name = "张三";
student01.id = 1812302308008L;
student01.computer = 80;
student01.math = 90.5f;
student01.English = 89.5f;
student01.show();
System.out.println(student01.show()+"你的成绩如下:"+"\n"+"计算机成绩:"+student01.getComputer()
+"\n"+"数学成绩:"+student01.getMath()+"\n"+"英语成绩:"
+student01.getEnglish()+"\n"+"总分:"+student01.sum()+"\n"+"平均分:"+student01.avg()
+"\n"+"最高分:"+student01.max()+"\n"+"最低分:"+student01.min());
System.out.println();
//第二个学生成绩表
Testclass01 student02 = new Testclass01("李四",1812402308009L,80,90,76);
student02.show();
System.out.println(student02.show()+"你的成绩如下:"+"\n"+"计算机成绩:"+student02.getComputer()
+"\n"+"数学成绩:"+student02.getMath()+"\n"+"英语成绩:"
+student02.getEnglish()+"\n"+"总分:"+student02.sum()+"\n"+"平均分:"+student02.avg()
+"\n"+"最高分:"+student02.max()+"\n"+"最低分:"+student02.min());
}
}
结果:
-学生基本信息-
姓名:张三
学号:1812302308008
你的成绩如下:
计算机成绩:80.0
数学成绩:90.5
英语成绩:89.5
总分:260.0
平均分:86.666664
最高分:90.5
最低分:80.0
-学生基本信息-
姓名:李四
学号:1812402308009
你的成绩如下:
计算机成绩:80.0
数学成绩:90.0
英语成绩:76.0
总分:246.0
平均分:82.0
最高分:90.0
最低分:76.0
【编写一个矩形类,包括3个成员变量:长、宽和个数(类变量);构建若干个矩形对象,分别输出它们的面积、周长和总个数。】
package objectClassTest;
import java.util.Scanner;
/**
* 测试矩形
* @author 卟淡
*
*/
public class RectangleTest {
private double length;
private double wide;
//创建一个静态属性(所有对象都可使用)
private static int count;
//无参构造方法
public RectangleTest() {
count++;
//调用一次count+1
}
//有参构造方法
public RectangleTest(double length,double wide) {
this.length = length;
this.wide = wide;
count++;
}
//获取长
public double getLength() {
return length;
}
//获取宽
public double getWide() {
return wide;
}
//求面积方法
public double getArea() {
return length*wide;
}
//求周长
public double getperimeter() {
return 2*length*wide;
}
//返回count,修饰符为静态初始化,可以被其它类调用
public static int getcount() {
return count;
}
//设置长
public void setLength(double length)throws Exception{
if(length<0)throw new Exception("长不能小于0");
this.length = length;
}
//设置宽
public void setWide(double wide)throws Exception{
if(wide<0)throw new Exception("宽不能小于0");
this.wide = wide;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("=====矩形对象====");
while(true) {
System.out.println("输入长与宽:");
double a1 = sc.nextDouble();
double a2 = sc.nextDouble();
if(a1==0||a2==0) {
System.out.println("====程序结束====");
break;
//结束循环
}
RectangleTest rectangle01 = new RectangleTest(a1,a2);
System.out.println("构建了长为"+rectangle01.getLength()+" "+"宽为"
+rectangle01.getWide()+","+"面积为"+rectangle01.getArea()
+","+"周长为"+rectangle01.getperimeter());
System.out.println("目前矩形的个数:"+RectangleTest.getcount());
}
}
}
结果:
注:懂得用while 、break、if语句重复调用对象
4.3包的使用
Java系统常用的API包
java.lang---------------Java基础类库,提供基本的类和接口,包括String、system、Math和Thread类、runnable与Cloneable接口
java.util-----------------实用工具包
java.io------------------Java数据流相关的包
java.awt----------------抽象窗口工具集包
java.awt.event -------图形用户界面事件包
java.sql-----------------数据库访问包
java.swing-------------“轻量级”图形用户界面包
java.applet-------------小应用程序包
java.net-----------------网络开发包
注意:除了java.lang包由系统自动引入以为,其它包均需使用import导入。
包的定义
除了可以导入(import 包名.类名)Java系统的API包以外,程序员还可以自定义。使用关键字package定义,格式:package 包名;
说明:
1、 允许分成命名,各层用.隔开,层数数量不受限制
2、 包一般采用小写字母命名
3、 首行
4、 一个源程序只能有一条package语句
5、 如果没有使用package语句定义的包,则类属于默认包(或无包)。默认的包中的类无法被其它的包中的类使用
6、 命名一般是域名从后往前写起(如com.gdlgxy.demo.Hello)
7、 包相当于文件夹,.就相当于上个文件夹下的子文件
引入包
格式 :
import 包名.类名|接口名;
或import 包名.*;(*表示包所包含的所有类和接口)