面向对象(上)
Java面向对象学习的三条主线
- java类及类的成员:**属性、方法、构造器;**代码块、内部类
- **面向对象的三大特征:**封装、继承、多态
- 其他关键字:this、super、static、final、abstract、interface、package、import
面向对象与面向过程
面向过程(POP)与面向对象(OOP)
-
面向过程:强调的是功能、以函数为最小单位,考虑怎么做 -
面向对象:强调具备了功能的对象,以类/对象为最小单位,考虑谁来做
面向对象的思维概述:
- 程序员从面相过程的执行着转化成了面向对象的指挥者
- 面向对象分析方法分析问题的思路和步骤:
- 根据问题需要,选择问题所针对的现实世界中的实体。
- 从实体中寻找解决问题相关的属性和功能,这些属性和功能就形成了概念世界中的类。
- 把抽象的实体用计算机语言进行描述,形成计算机世界中类的定义。即接著某种程序语言,把类构造成计算机能够识别和处理的数据结构。
- 将类实例化成计算机世界中的对象。对象是计算机世界中解决问题的最终工具。
Java语言中的基本元素:类和对象
类
-
比如人、猪、狗、玩具、水果,对某一类实物的抽象 -
面向对象程序设计的重点是对类的设计 -
类的设计,就是设计类的成员
- 现实世界中的生物体,达到鲸鱼,小到蚂蚁,都是有最基本的细胞构成的。同理,Java代码世界是由诸多个不同功能的类构成的。
- 类中的两个主要的成员:属性和方法
-
属性=成员变量=field=域、字段 -
方法=成员方法=函数=method
类和对象的创建与使用
- 创建类,设计类的成员
- 创建类的对象
- 通过“对象.属性”或“对象.方法”调用对象的结构
public class Mini {
public static void main(String[] args) {
Person p1 = new Person();
p1.name = "小狗蛋";
p1.sex = '女';
p1.age = 24;
p1.height = 158;
p1.eat();
p1.sleep();
p1.talk("中文");
}
}
class Person {
String name;
int age;
char sex;
double height;
public void eat(){
System.out.println("人会吃饭");
}
public void sleep(){
System.out.println("人要睡觉");
}
public void talk(String language){
System.out.println("中国人说的是"+language);
}
}
如果创建了一个类的多个对象,则每个对象都独立拥有一套属性。(非static的)
? 也就是说,我们修改了一个对象的属性,并不会影响另一个对象的属性
对象的内存解析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TOGaTTUu-1644334828455)(C:\Users\lin\AppData\Roaming\Typora\typora-user-images\image-20220111212301417.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O5LeUIsv-1644334828456)(C:\Users\lin\AppData\Roaming\Typora\typora-user-images\image-20220111213339194.png)]
属性(成员变量)与局部变量的对比
-
相同点
- 定义变量的格式相同:数据类型 变量名 = 变量值;
- 先声明,后使用
- 变量都有其对应的作用域
-
不同点
- 定义的位置不同:
- 成员变量:直接定义在类中的变量,在类的大括号{}里面
- 局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量
- 关于权限修饰符的不同:
- 属性可以在声明属性时,使用权限修饰符指明其权限。
- 常用的权限修饰符:public、private、protected 、缺省(未声明权限修饰符)–>封装性
- 局部变量不能使用权限修饰符,他的权限与方法的权限一致。
- 默认初始化值的情况:
- 属性:类的属性,根据其基本类型,都有默认初始化值。
- 整形(byte、short、int、long):0
- 浮点型(float、double):0.0
- 字符型(char):0或\u0000
- 引用数据类型(类、数组、接口):null
- 局部变量:没有默认初始化值
- 意味着我们在调用局部变量时必须先赋值public (public static void main(String[] args) { //这里面的args(形式参数)也是局部变量)
- 形式参数我们在调用时再赋值即可
- 在内存中加载的位置不同
- 属性:加载到堆空间中(非static)
- 局部变量:加载到栈中
方法的举例和声明的格式
类中方法的声明和使用
- 方法:描述该类具有的功能
- 比如:
- Math类:sqrt()\random()…
- Scanner类:nextXxx()…
- Arrays类:sort()\binarySearch()\toString()\equals()…
public class Text {
public static void main(String[] args) {
}
class Customer{
String name;
int age;
boolean married;
public void eat(String food){
System.out.println("客户去吃饭了,吃的是"+food);
}
public void sleep(){
System.out.println("客户现在在休息");
}
public String getName(){
return name;
}
public String getNation(String nation){
String info ="我的国籍是:"+ nation;
return info;
}
}
}
方法声明的说明
- 关于权限修饰符(四个):private、public、缺省、protected–>封装性再细讲
- 返回值类型:有返回值 & 没有返回值
- **如果方法有返回值:**必须在方法声明时指定返回值的类型。同时在方法中需要使用return 指定返回值类型的数据。
- **没有返回值:**在声明方法时,则需要使用void来表示。农场没有返回值的方法中,不需要使用return。也可以使用“return;”来结束方法,只有结束方法的作用,后面的语句不能执行。
- 方法名:属于标识符,需要满足首字母大写,驼峰原则,需要见名知意。
- 形参列表:方法可以声明0个、一个或者多个形参
- 格式:数据类型1 形参1,数据类型2 形参2,…
- 我们定义方法时,是否需要定义形参:视情况而定
- 方法体:具体方法的实现
return关键字的使用
- 使用范围:使用在方法体中
- 作用:
- 结束方法
- 针对有返回值类型的方法, 使用“return 数据”方法返回所要的数据
- return关键字后面不能声明语句,这一点和break是一样的
方法的使用
- 方法在使用中可以调用当前类的属性及当前类中的方法
利用面向对象的方法,设计Circle类计算园的面积
package OOP.Circle;
public class CircleText {
public static void main(String[] args) {
Circle cir = new Circle();
cir.radius = 3;
cir.getArea();
}
}
class Circle{
double radius;
public void getArea(){
System.out.println("圆的面积为:"+Math.PI*radius*radius);
}
}
打印自定义矩形
package OOP.Exer;
import java.util.Scanner;
public class RectangleText {
public static void main(String[] args) {
Rectangle rect = new Rectangle();
System.out.println("请输入长度m的值:");
rect.m = rect.getVal();
System.out.println("请输入宽度n的值:");
rect.n = rect.getVal();
rect.diagramPrint();
rect.printArea();
}
}
class Rectangle{
int m;
int n;
public void printArea(){
System.out.println("矩形面积为:"+m*n);
}
public void diagramPrint(){
System.out.println("打印矩形:");
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
System.out.print("*\t");
}
System.out.println();
}
}
public int getVal(){
int val = 0;
for (; ; ) {
Scanner sca = new Scanner(System.in);
if (sca.hasNextInt()){
val= sca.nextInt();
return val;
}else {
System.out.println("请输入正确的数据类型!");
}
}
}
}
打印学生信息
package OOP.Student;
public class StudentText {
public static void main(String[] args) {
Student[] student = new Student[20];
for (int i = 0; i < student.length; i++) {
student[i] = new Student();
student[i].number = i+1;
student[i].state = (int) (Math.random()*(6-1+1)+1);
student[i].score = (int) (Math.random()*(100-0+1)+0);
if (student[i].state == 3){
student[i].info();
}
}
for (int i = 0; i < student.length-1; i++) {
for (int j = 0; j < student.length-1-i ; j++) {
if (student[j].score>student[j+1].score){
Student temp = student[j];
student[j] = student[j+1];
student[j+1] = temp;
}
}
}
for (int i = 0; i < student.length-1; i++) {
student[i].info();
}
}
}
class Student{
int number;
int state;
int score;
public void info(){
System.out.println("学号"+number+"\t年级:"+state+"\t成绩:"+score);
}
}
改进
package OOP.Student;
public class StudentText {
public static void main(String[] args) {
Student[] student = new Student[20];
for (int i = 0; i < student.length; i++) {
student[i] = new Student();
student[i].number = i+1;
student[i].state = (int) (Math.random()*(6-1+1)+1);
student[i].score = (int) (Math.random()*(100-0+1)+0);
}
StudentText studentText = new StudentText();
System.out.println("打印指定年级的学生信息:");
studentText.searchInfo(student,3);
studentText.sort(student);
System.out.println("打印排序后的学生信息");
studentText.arrPrint(student);
}
public void searchInfo(Student[] stu,int state){
for (int i = 0; i < stu.length; i++) {
if (stu[i].state == state){
stu[i].info();
}
}
}
public void sort(Student[] stu){
for (int i = 0; i < stu.length-1; i++) {
for (int j = 0; j < stu.length-1-i ; j++) {
if (stu[j].score>stu[j+1].score){
Student temp = stu[j];
stu[j] = stu[j+1];
stu[j+1] = temp;
}
}
}
}
public void arrPrint(Student[] stu){
for (int i = 0; i < stu.length-1; i++) {
stu[i].info();
}
}
}
class Student{
int number;
int state;
int score;
public void info(){
System.out.println("学号"+number+"\t年级:"+state+"\t成绩:"+score);
}
}
面向对象 一 复习
1.面向对象学习的三条主线
- 类与类的成员:属性、方法、构造器;代码块、内部类
- 面向对象的三大特性:封装、继承、多态
- 其它关键字:static、interface、import、package、final、this…
2.面向对象与面向过程(理解)
- 面向过程:强调的是工程行为,以函数为最小单位,考虑怎么做
- 面向对象:清点具备功能的对象,以类/对象为最小单位,考虑谁来做
- 举例:人把大象放冰箱
3.完成一个项目(功能)的思路:
- 根据问题的需要,选择问题所针对的现实世界中的实体。
- 从实体中寻找解决问题相关的属性和功能,这些属性和功能就形成了概念世界中的类。
- 把抽象的实体用计算机语言进行描述,形成计算机世界中类的定义。即借助某种程序语言,把类构造成计算机能够识别和处理的数据结构。
- 将类实例化成计算机世界中的对象。对象是计算机世界中解决问题的最终工具。
4.面向对象中的两个重要的概念
- 类:对一类事物的描述,是抽象的、概念上的定义
- 对象:是实际存在的该类事物的每个个体,因而也被称为实例(instance)
- 面向对象程序设计的重点是类的设计
- 设计类,就是设计类的成员
- 类是对象的抽象描述,对象是类的实例化
5.面向对象思想落地的规则一
- 创建类,设计类的成员
- 实例化类,创建类的对象
- 调用类中的属性和方法(“对象.方法”“对象的.属性”)
6.属性(成员变量)和局部变量的异同
- 相同点:
- 命名规则规范相同
- 都是先声明、后使用
- 变量都具有其对应的作用域
- 异同:
- 声明的位置不同:属性是在类中声明的声明的。局部变量是在方法内、内部类、构造器内声明的,形式参数也属于局部变量。
- 初始化值:属性(成员变量)有初始化值,局部变量没有初始化值(形式参数必须初始化值才能使用)
7.return关键字
理解万物皆对象
理解“万事万物皆对象”
- 在Java语言范畴中,我们都将功能、结构等封装到类中,通过类的实例化,来调用具体的功能结构
- Scanner,String
- 文件:File
- 网络资源:URL
- 涉及到Java语言与前端的Html、后端的数据库交互时,前后端的结构在Java层面交互时,头体现为类、对象。
对象数组的内存解析
- 引用类型的变量,只可能存储两类值:null或者地址值(含变量类型)[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zgXsDTX7-1644334828457)(C:\Users\lin\AppData\Roaming\Typora\typora-user-images\image-20220113233156025.png)]
匿名对象的使用
-
理解:匿名对象,我们创建对象时间 -
匿名对象不能重复使用,因为没有在栈空间中创建地址值,每一次调用都是一个新的对象 -
使用如下: -
package OOP.Instance;
public class InstanceText {
public static void main(String[] args) {
Phone p = new Phone();
p.playGame();
p.sendEmail();
new Phone().price = 1999;
new Phone().showPrice();
ShowMall mall = new ShowMall();
mall.show(new Phone());
}
}
class ShowMall{
public void show(Phone phone){
phone.price = 1996;
phone.sendEmail();
phone.readNews();
phone.readMovies();
phone.showPrice();
}
}
class Phone{
int price;
public void showPrice(){
System.out.println("此手机价格为:"+price);
}
public void sendEmail(){
System.out.println("发送邮件");
}
public void playGame(){
System.out.println("打游戏");
}
public void readNews(){
System.out.println("看新闻");
}
public void readMovies(){
System.out.println("看电影");
}
}
工具类的封装
package OOP.ArrayUtil;
class ArrayUtil {
public int getMax(int[] arr){
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if (max<arr[i]){
max = arr[i];
}
}
return max;
}
public int getMin(int[] arr){
int min = arr[0];
for (int i = 0; i < arr.length; i++) {
if (min>arr[i]){
min = arr[i];
}
}
return min;
}
public int getSum(int[] arr){
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum+=arr[i];
}
return sum;
}
public int getAverage(int[] arr){
return getSum(arr)/arr.length;
}
public void reversal(int[] arr){
for (int i = 0; i < arr.length/2; i++) {
int temp = arr[i];
arr[i] = arr[arr.length-i-1];
arr[arr.length-i-1] = temp;
}
}
public void sort(int[] arr){
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j+1]){
int y = arr[j];
arr[j] = arr[j+1];
arr[j+1] = y;
}
}
}
}
public int[] arrCopy(int[] arr){
int[] name = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
name[i] = arr[i];
}
return name;
}
public void printArr(int[] arr){
for (int i = 0; i < arr.length-1; i++) {
System.out.print(arr[i]+"\t");
}
System.out.println();
}
public int search(int[] arr,int val){
for (int i = 0; i < arr.length; i++) {
if (arr[i] == val){
return i;
}
}
return -1;
}
}
测试封装的工具类
package OOP.ArrayUtil;
public class ArrayUtilText {
public static void main(String[] args) {
int[] arr1 = new int[]{3,0,-1,2,99,88,12,-21};
ArrayUtil util = new ArrayUtil();
util.sort(arr1);
util.printArr(arr1);
System.out.println("最大值:"+util.getMax(arr1));
System.out.println("最小值:"+util.getMin(arr1));
System.out.println("数组求和:"+util.getSum(arr1));
util.reversal(arr1);
util.printArr(arr1);
System.out.println("在数组中找到元素,在数组中的位置为:"+(util.search(arr1,3)+1));
}
}
再谈方法
方法的重载
可变形参数
- 可变形参数是jdk5.0的新特性
- 具体使用:
- 可变个数形参格式:数据类型…变量名
- 当调用可变个数形参的方法是,传入的参数个数可以是0个、一个或者多个
- 可变个数形参的方法与本类中方法名相同,形参不同的方法直接构成重载
- 可变个数形参的方法与本类中方法名相同,形参类型相同的数组之间不构成重载(不能共存)。其实与数组的参数是一样的
- 可变形参数必须声明在参数列表的末尾,也就是只能声明一个可变型参数
方法参数的值传递机制**
基本数据类型传递
package OOP.ValueTransferText;
public class ValueTransferText {
public static void main(String[] args) {
Order or1 = new Order();
or1.orderId = 1001;
Order or2 =or1;
System.out.println("or1.orderId:"+or1.orderId+
",or2.orderId:"+or2.orderId);
or2.orderId= 1002;
System.out.println("or1.orderId:"+or1.orderId+
",or2.orderId:"+or2.orderId);
}
}
class Order{
int orderId;
}
错误示例
写方法时不能使用值传递,因为不会改变原参数的
解决方法:可以使用引用传递来进行参数调整
package OOP.ValueTransferText2;
public class ValueTransferText2 {
public static void main(String[] args) {
int x = 10;
int y = 20;
System.out.println(x+"--"+y);
ValueTransferText2 val = new ValueTransferText2();
val.swap(x,y);
System.out.println(x+"--"+y);
}
public void swap(int i,int j){
int temp = i;
i=j;
j=temp;
}
}
引用数据类型传递
引用传递使用:交换数据值
- 使用引用传递调换值
package OOP.ValueTransferText2;
public class ValueTransferText2 {
public static void main(String[] args) {
Date date = new Date();
date.x=10;
date.y=20;
System.out.println("date.x:\t"+date.x+"\tdate.y:\t"+date.x);
ValueTransferText2 v2 = new ValueTransferText2();
v2.swap(date);
System.out.println("date.x:\t"+date.x+"\tdate.y:\t"+date.y);
}
public void swap(Date date){
int temp = date.x;
date.x = date.y;
date.y=temp;
}
}
class Date{
int x,y;
}
- 创建调换位置的方法,在冒泡排序中进行调用
package OOP.ValueTransferText2;
import java.util.Arrays;
public class ValueTransferText2 {
public static void main(String[] args) {
ValueTransferText2 v2 = new ValueTransferText2();
int[] x = new int[]{1,-2,30,9,7,25,15};
for (int i = 0; i < x.length; i++) {
for (int j = 0; j < x.length-1-i; j++) {
if (x[j]>x[j+1]){
v2.swap(x,j,j+1);
}
}
}
System.out.println(Arrays.toString(x));
}
public void swap(int[] arr,int i,int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j]=temp;
}
}
练习
1.创建一个类,让他包含一个double类型的半径(Radius),一个findAreas()方法返回一个double类型圆的面积 2.创建一个PassObject类,在类中定义一个方法printAreas(), 该方法的定义如下:public void printAreas(Circle circle,int time)。在printAreas中打印出1到time之间每个整数半径值,以及其对应的面积,
package OOP.ValueTransferText2;
public class ValueTransferText2 {
public static void main(String[] args) {
System.out.println("Radius\tArea");
Circle circle = new Circle();
PassObject pso = new PassObject();
pso.printAreas(circle,6);
}
}
class Circle{
double radius;
public double findAreas(){
return Math.PI*radius*radius;
}
}
class PassObject{
public void printAreas(Circle c,int time){
int i = 1;
for (; i < time ; i++) {
c.radius = i;
System.out.println(c.radius+"\t\t"+c.findAreas());
}
System.out.println("\n"+"now radius is:"+ (double)i);
}
}
递归
- 递归方法:一个方法体调用它自身。
- 方法递归包含了一种隐式的循环,他会重复执行某段代码,但这种重复执行无需循环控制。
- 递归一定要向已知方向递归,否则这种地柜就变成了无穷递归,类似于死循环。
- 例1:求1~n的自然数之和
package OOP.ValueTransferText2;
public class ValueTransferText2 {
public static void main(String[] args) {
System.out.println(getSum(100));
}
public static int getSum(int n){
if (n==1){
return 1;
}else {
return n+getSum(n-1);
}
}
}
package OOP.ValueTransferText2;
public class ValueTransferText2 {
public static void main(String[] args) {
System.out.println(getSum(100));
}
public static int getSum(int n){
if (n==1){
return 1;
}else {
return n*getSum(n-1);
}
}
}
- 例3,一直有一个数列:f(0)=1,f(1)=4,f(n+2)=2*f(n+1)+f(n),其中n是大于0的整数,求f(10)的值
package OOP.ValueTransferText2;
public class ValueTransferText2 {
public static void main(String[] args) {
System.out.println(getSum(10));
}
public static int getSum(int n){
if (n==0){
return 1;
}else if(n==1) {
return 4;
}else {
return 2*getSum(n-1)+getSum(n-2);
}
}
}
- 例4,输入一个数据n,计算斐波那契数列(Fibonacci)的第n个值,1 1 2 3 5 8 13 21 34 55
package OOP.ValueTransferText2;
public class ValueTransferText2 {
public static void main(String[] args) {
System.out.println(fbArr(10));
}
public static int fbArr(int n){
if (n==1||n==2){
return 1;
}else {
return fbArr(n-1)+fbArr(n-2);
}
}
}
复习
1.匿名对象的使用
2.理解万事万物皆对象
3.方法的重载
4.Java方法中的值传递机制
- 基本数据类型变量:
- 引用数据类型变量:
- 形参和实参:方法的封装时使用的是形参,调用时是实参
5.return关键字的使用
6.递归
7.可变个数形参的方法,调用方法与数组一致
面向对象特征之一:封装
1.概述
-
为什么要封装?疯转的作用和含义?
-
程序设计追求“高内聚、低耦合”。
-
3.隐藏对象内部的复杂性,支队挖公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。就是该藏的藏、该露的露。这就是封装性的设计思想。
2.问题的引入
- 当我们创建一个类的对象后,我们可以通过“对象的.属性”的方式,对对象的属性进行复制。这里赋值操作要受到属性的数据类型和存储范围的制约
- 加入额外的限制条件。这个条件就不能在属性声明是体现,我们只能通过方法进行限制条件的添加。比如(set同时我们需要避免面用户再使用“对象的.属性”的方法对属性进行赋值。则需要将属性声明为私有的额(private)–>此时,针对于属性就体现了封装)
package OOP.AnimalText;
public class AnimalText {
public static void main(String[] args) {
Animal p1 = new Animal();
p1.variety = "human";
p1.setHeight(168);
p1.setLegs(2);
p1.show();
}
}
class Animal {
String variety;
private int legs;
private double height;
private int age;
public void setLegs(int l){
if (l>0 && l%2==0){
legs =l ;
}else {
legs =0;
}
}
public void setHeight(int h){
if (h>0){
height =h ;
}else {
height =0;
}
}
public int getAge(){
return age;
}
public void show(){
System.out.println("variety:"+variety+"\tage:"+legs+"\theight:"+height+"\tage:"+age);
}
}
3.封装的体现
- 我们将类的属性xxx私有化(private),同事,提供公共的(public)方法来获取(getXxx)和设置(setXxx)
- 不对外暴露的私有的方法
- 单例模式…
4.封装性的体现需要权限修饰符来配合
- Java规定的4中权限(从小到大):private、缺省、protected、public
package Order.O1;
public class Order2 {
public static void main(String[] args) {
Order1 o1 = new Order1();
o1.orderPublic = 1;
o1.orderProtected = 2;
o1.orderDefault = 3;
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hlrOEYx8-1644334828457)(C:\Users\lin\AppData\Roaming\Typora\typora-user-images\image-20220118205302470.png)]
- 4种权限都可以用来修饰类的内部结构:属性、方法、构造器、内部类
- 只有public和缺省可以用来修饰类(非内部类)
总结封装
java提供了四种权限修饰符来修饰类及类的内部结构,体现类及类的内部结构权限的大小
- 创建一个Person类,定义一个私有属性age,使用set和get方法来体会封装
package OOP.Person;
public class PersonText {
public static void main(String[] args) {
Person p1 = new Person();
p1.setAge(26);
System.out.println("age:"+p1.getAge());
}
}
class Person {
private int age;
public void setAge(int a) {
if (a>=0 && a<=130){
this.age = a;
}else {
throw new RuntimeException("输入数据非法!");
}
}
public int getAge() {
return age;
}
}
类的成员三:构造器(构造方法)
一、构造器的作用
-
创建对象
- Person p1 = new Person();//后面的这个Person()就是Person类中的构造器
-
初始化对象的属性
二、说明
- 如果没有显式的构造器的话,系统默认提供一个空参构造器
- 定义构造器的方法:权限修饰符 类名(形参){//方法体}
- 一个类中可以存在多个构造器,就是构造器的重载
- 构造器和方法的异同
- 一旦我们显式的定义了类的构造器之后,系统就不会再提供空参构造器(一旦挣钱,就不给低保了)
- 一个类中,至少存在一个构造器
三、练习
- 在Person类中添加构造器,利用构造器设置所有人的age属性初始值都为18。
package OOP.Person;
public class PersonText {
public static void main(String[] args) {
Person p1 = new Person();
System.out.println(p1.getAge());
}
}
class Person {
String name;
private int age;
public Person(){
age = 18;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
- 修改上题中的类和构造器,增加name属性,使得每次创建Person对象时初始化对象的age和name
package OOP.Person;
public class PersonText {
public static void main(String[] args) {
Person p1 = new Person("小林",25);
System.out.println("name:"+p1.getName()+"\tage:"+p1.getAge());
}
}
class Person {
String name;
private int age;
public Person(String n,int a){
name = n;
age = a;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
public Person(){
}
}
- 编写两个类,TriAngle和TriAngleText,其中TriAngle类中声明私有的边长base和高height,同事声明公告的方法访问私有变量,提供类必要的构造器。另一个类中使用这些公共方法,计算三角形的面积
package OOP.TriAngle;
public class TriAngleText{
public static void main(String[] args) {
TriAngle t1 = new TriAngle();
t1.setBase(5.1);
t1.setHeight(5.2);
System.out.println("Base:"+ t1.getBase()+"\tHeight:"+ t1.getHeight()+"\tArea:"+ t1.getArea());
}
}
class TriAngle {
private double base;
private double height;
public TriAngle(double b,double h){
base = b;
height = h;
}
public TriAngle(){
}
public double getBase() {
return base;
}
public void setBase(double base) {
this.base = base;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public double getArea(){
return base*height;
}
}
- 定义Student类,
- 有四个属性:String name; int age; String school; String major;
- 三个构造器:
- 第一个构造器Student(String n, int a)设置类的name和age;
- 第二个构造器Student(String n, int a,String s)设置类的name、age和school;
- 第三个构造器Student(String n, int a,String s,String m)设置类的name、age、school和major属性;
- 在main方法中分别调用不同的构造器创建对象,并输出其属性值
四、总结
- 类中属性赋值的顺序:默认初始化–>显式初始化–>构造器赋值–>通过“对象.方法”或者“对象.属性”进行赋值
- 前面三个赋值都只执行一次,可以叫初始化,后面的可以多次反复执行
- 默认构造器的权限与类的权限一致
- 在一个类中创建另一个类类型的属性,这叫做关联
JavaBean–拓展知识
- JavaBean是一种Java语言写成的可重用组件
- 所谓JavaBean,是指符合如下标准的Java类:
- 类是公告的
- 有一个无参的构造器
- 有属性,且有对应的get、set方法
- 用户可以使用JavaBean将功能、处理、值、数据库访问和其他的任何可以使用Java代码创造的对象进行打包,并且其他的开发者可以通过JSP页面、Servlet、其他的JavaBean、applet程序或者应用来使用这些对象。用户可以认为JavaBean提供了一种随时随地的复制和粘贴的功能,而不用关心任何改变
this关键字的使用
this是什么?
- 在Java中,this关键字比较难立即,它的作用和其词义很接近。
- 它在方法内部使用,即这个方法所属对象的引用;
- 它在构造器内部使用,表示该构造器正在初始化的对象
- this表示当前正在创造的对象,可以调用类的属性、方法和构造器
- 什么时候使用this关键字呢?
- 当在方法内需要调用到该方法的对象是,就用“this.属性”或“this.方法”。但在大部分情况下,我们都选择省略“this.”。如果方的的形参与类的属性同名时,我们必须显式的使用“this.变量”的方式,表明此变量是属性,而非形参。
- 具体的:我们可以使用this来区分局部变量和属性。
- 比如:this.name=name
this调用构造器
- 我们在类的构造器中,可以显式的使用“this(形参列表)”方法,调用本类中制定的其他构造器
- 构造器中不能通过“this(形参列表)”方式调用自己
- 如果一个类中有n个构造器,则最多有n-1构造器中使用了“this(形参列表)”
- 规定:“this(形参列表)”必须声明在当前构造器的首行
- 构造器内部,最多只能声明一个“this(形参列表)”,用来调用其他的构造器
练习一复习
简易银行
package OOP.BankText;
public class BankText {
public static void main(String[] args) {
Bank bank = new Bank();
bank.addCustomer("Jane","Smith");
bank.getCustomer(0).setAccount(new Account(2000));
bank.getCustomer(0).getAccount().withdraw(500);
System.out.println("客户:"+bank.getCustomer(0).getFirstName()+","+
bank.getCustomer(0).getLastName()+",余额为:"+
bank.getCustomer(0).getAccount().getBalance());
System.out.println("***********************");
bank.addCustomer("狗蛋","小");
System.out.println("银行现在的客户数量为:"+bank.getNumberOfCustomer());
}
}
class Bank {
private Customer[] customers;
private int numberOfCustomer;
public Bank(){
customers = new Customer[10];
}
public void addCustomer(String f,String l){
customers[numberOfCustomer++] = new Customer(f,l);
}
public int getNumberOfCustomer() {
return numberOfCustomer;
}
public Customer getCustomer(int index){
if (index >=0 && index<numberOfCustomer){
return customers[index];
}
return null;
}
}
class Customer {
private String firstName;
private String lastName;
private Account account;
public Customer(String f,String l){
firstName = f;
lastName = l;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
}
class Account {
private double balance;
public Account(double init_balance){
balance = init_balance;
}
public double getBalance() {
return balance;
}
public void deposit(double amt){
if (amt > 0){
balance+=amt;
System.out.println("成功存入:"+amt+"!");
}
}
public void withdraw(double amt){
if (amt>0 && amt <= balance){
balance-=amt;
System.out.println("成功取出:"+amt+"!");
return;
}
System.out.println("取款失败:余额不足!");
}
}
项目二:客户信息管理软件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RPWIGbt6-1644334828457)(C:\Users\lin\AppData\Roaming\Typora\typora-user-images\image-20220123151528541.png)]
添加用户,删除用户,修改用户信息,查询用户信息
面向对象(中)
面向对象特征二:继承性(inhertance)
一:继承性的好处:(Why?)
- 减少代码的冗余,提高代码的复用性
- 便于功能的扩展
- 为了以后多态的使用提供了前提
二:继承性的格式:class A extends B{}
- A:子类、派生类、subclass
- B:父类、超类、基类、superclass
- 2.1 体现:子类A一旦继承到父类B之后,子类会获得父类所有的属性和方法
特别的,父类结构中声明的private属性和方法,子类继承父类后,任然认为获取了父类中私有的结构 只是因为封装性的影响,子类不能直接调用父类中private的结构 - 2.2 子类继承父类后,可以声明自己的属性和方法,实现功能的扩展。
子类和父类的关系,不同于集合与子集的关系
? extends:扩展、延展
三:Java中关于继承性的一些规定
- 一个类可以允许多个子类继承。
- Java中类的单继承性:一个子类只能有一个父类。(C++中可以多继承)
- 子类是相对概念
- 子类直接继承的父类叫直接父类,间接继承的类叫间接父类
- 子类继承父类后,也继承了所有间接父类的结构
四
- 所有的类都继承与java.lang.Object(除了它本身)类
- 意味着所有的类都具有java.lang.Object声明的功能
继承性的复习
1.为什么要有类的继承性?(继承性的好处)
- 减少代码的冗余,提高代码的复用性
- 便于功能的扩展
- 为之后多态性的使用,提供了前提
2.继承性的格式
3.子类继承父类以后有哪些不同?
- 子类继承父类后拥有父类的所有属性和方法
- 子类可以声明属性及方法实现功能的扩展
- 子类可以通过父类提供的public方法使用父类private的结构
4.java.lang.Object类的理解
- 所有的类都继承与java.lang.Object(除了它本身)类
public void deposit(double amt){ if (amt > 0){ balance+=amt; System.out.println(“成功存入:”+amt+"!"); } } public void withdraw(double amt){ if (amt>0 && amt <= balance){ balance-=amt; System.out.println(“成功取出:”+amt+"!"); return; } System.out.println(“取款失败:余额不足!”); } }
## 项目二:客户信息管理软件
[外链图片转存中...(img-RPWIGbt6-1644334828457)]
添加用户,删除用户,修改用户信息,查询用户信息
# 面向对象(中)
## 面向对象特征二:继承性(inhertance)
### 一:继承性的好处:(Why?)
- 减少代码的冗余,提高代码的复用性
- 便于功能的扩展
- 为了以后多态的使用提供了前提
### 二:继承性的格式:class A extends B{}
- A:子类、派生类、subclass
- B:父类、超类、基类、superclass
- 2.1 体现:子类A一旦继承到父类B之后,子类会获得父类所有的属性和方法
特别的,父类结构中声明的private属性和方法,子类继承父类后,任然认为获取了父类中私有的结构
只是因为封装性的影响,子类不能直接调用父类中private的结构
- 2.2 子类继承父类后,可以声明自己的属性和方法,实现功能的扩展。
子类和父类的关系,不同于集合与子集的关系
? extends:扩展、延展
### 三:Java中关于继承性的一些规定
1. 一个类可以允许多个子类继承。
2. Java中类的单继承性:一个子类只能有一个父类。(C++中可以多继承)
3. 子类是相对概念
4. 子类直接继承的父类叫直接父类,间接继承的类叫间接父类
5. 子类继承父类后,也继承了所有间接父类的结构
### 四
1. 所有的类都继承与java.lang.Object(除了它本身)类
2. 意味着所有的类都具有java.lang.Object声明的功能
### 继承性的复习
1.为什么要有类的继承性?(继承性的好处)
1. 减少代码的冗余,提高代码的复用性
2. 便于功能的扩展
3. 为之后多态性的使用,提供了前提
2.继承性的格式
- class A extends B{}
3.子类继承父类以后有哪些不同?
- 子类继承父类后拥有父类的所有属性和方法
- 子类可以声明属性及方法实现功能的扩展
- 子类可以通过父类提供的public方法使用父类private的结构
4.java.lang.Object类的理解
- 所有的类都继承与java.lang.Object(除了它本身)类
- 意味着所有的类都具有java.lang.Object声明的功能
|