01面向对象编程入门
在程序中的数据存储,我们可以利用变量、数组、二维数组以及对象进行存储。
对象也是一种存储数据的存储方式。
例如要存彭于晏的数据:

1.先设计对象的模板,也就是对象的设计图:类。
public class Star{
String name;
int age;
double height;
double weight;
}
02面向对象-学生案例

//student.java文件定义student类
public class student {
String name;
double chinese;
double math;
}
//evenStudent.java主函数中进行赋值与调用
public class evenStudent {
public static void main(String[] args) {
student s1 = new student();
student s2 = new student();
s1.name = "播妞";
s1.chinese = 100;
s1.math = 100;
System.out.println("total = " + (s1.chinese + s1.math) + "; even = " + ((s1.chinese + s1.math) / 2));
s2.name = "播仔";
s2.chinese = 59;
s2.math = 100;
System.out.println("total = " + (s2.chinese + s2.math) + "; even = " + ((s2.chinese + s2.math) / 2));
}
}
***重要概念:封装***
封装 即为把数据和对数据的处理放到同一个类中去。
在上面的例子中我们可以看到 在定义了student类后,我们仍需要在主程序中写很多操作代码,封装就可以很好的解决这个问题,通过将逻辑代码写在studen.java文件中,让主程序更加的简洁。代码如下:
//student.java
public class student {
String name;
double chinese;
double math;
//定义方法打印全部分数和
public void allScore(){
System.out.println("total = " + (chinese + math));
}
//定义方法打印平均分数
public void evenScore(){
System.out.println("; even = " + ((chinese + math) / 2));
}
}
//evenStudent.java
public class evenStudent {
public static void main(String[] args) {
student s1 = new student();
student s2 = new student();
s1.name = "播妞";
s1.chinese = 100;
s1.math = 100;
s1.allScore();//调用
s1.evenScore();//调用
s2.name = "播仔";
s2.chinese = 59;
s2.math = 100;
s2.allScore();//调用
s2.evenScore();//调用
}
}
03面向对象编程:对象究竟是什么
对象本质是一种特殊的数据结构(可以理解成一张表)。
每次进行一次new操作 可以视为创建了一张表 这样比较好理解一些。

万物皆对象,谁的数据谁存储。

04类的基本语法
1.构造器
构造器是一种特殊的方法,它的特点是只有修饰符,没有返回值,名称必须是类名,就是构造器。
public class Student {
//构造器
public Student() { //只有修饰符public 没有返回类型值 这是一个无参构造器
...
}
}
构造器的特点:创建对象时,对象会自动去调用构造器
//Student.java类文件
public class Student {
String name;
int age;
char sex;
//创建类时 类自动携带一个无参构造器 此时如果创建有参构造器 则类自带的无参
//构造器失效 想要用无参构造器就需要自己创建一个
//无参构造器
public Student(){
}
//有参构造器 有接收参数
public Student(String n, int a, char s){
name = n;
age = a;
sex = s;
}
}
package com.xinsheng.constructor;
public class Test {
public static void main(String[] args) {
//调用有参构造器 从此赋值只需要一行命令
//不用是s1.name一个一个点了
Student s1 = new Student("小明",18,'男');
System.out.println(s1.name + s1.age + s1.sex);
}
}
***创建对象的逻辑***
在如下语句中:
Student s1 = new Student();
1. new Student() 实际上是创建对象的部分。它在堆内存中分配空间,并初始化一个新的Student类的实例。这个新创建的、在内存中的实例,就是对象本身。
2. s1 是一个引用变量(或者叫对象引用)。它存储着指向刚才创建的那个Student对象在堆内存中位置的地址。因此如果直接打印s1,出来的是一个地址数字。

总结:
1.对象(object)是new Student()创建出来的、住在内存堆里的那个实体。
2. s1是指向这个对象的引用,就像一个标签或遥控器,让你能够访问那个对象。
所以,在日常交流中人们经常说“s1就是那个对象”,但从技术上讲,s1是对象引用,而不是对象本身。
构造器总结:

2.this关键字
this就是一个变量,可以用在方法中,用来拿到当前对象。例如如下代码所示:
//Student.java类文件
public class Student {
String name;
public void printThis(){
System.out.println(this); //使用this拿到当前对象 这个对象是Test.java中创建的
}
}
当你在 Student.java 类的 printThis() 方法中执行 System.out.println(this); 时:
-
this关键字 确实是拿到了当前正在执行这个方法的那个Student对象。 -
这个对象 正是你在另一个文件(你提到的是
Test.java)中,通过像Student s = new Student();这样的语句创建出来的 堆内存中的实体。
public class Test {
public static void main(String[] args) {
Student s1 = new Student();
s1.name = "小明";
s1.printThis();
System.out.println(s1);
}
}
当执行到s1.printThis(); 时,Java 虚拟机(JVM)知道:现在要用 s1 指向的那个对象 来执行 printThis() 方法。在方法内部,this 变量就自动指向了 s1 指向的那个对象。
打印结果如下,打印出s1对象在堆内存中的地址,结果一直,说明确定this此时指向的是s1对象。

this有啥应用场景?
this主要用来解决:变量名称冲突问题的。举例如下代码:
代码中变量名的命名一般要做到见名知意,因此例如如下情况:
如果在Student.java类文件中定义一个方法,用来打印对象的爱好
public void printHobby(String name){
System.out.println(name + "like" + name);
}
因为要见名知意,所以对象名应为name,同时爱好名应该也为name,此时如果在Test.java文件中调用这个方法:
Student s2 = new Student();
s2.name = "小刘";
s2.printHobby("打游戏");
原本预期结果应为“小刘like打游戏” 运行则出现以下情况

这是因为在printHobby(String name)方法中 依据就近原则 Java会将两个name都认为是方法本身的变量name,而非对象的变量name,因此出现这种情况。
此时如果在方法体中使用this变量,此时this.name变量表明指向当前调用printHobby(String name)方法的这个对象的name变量,即为小刘,则此时打印结果为“小刘like打游戏”
public void printHobby(String name){
System.out.println(this.name + "like" + name);
}

3.封装
封装是面向对象的三大特征之一,面向对象的三大特征为:封装、继承、多态。
封装的设计要求:合理隐藏、合理暴露
类就是一种封装
例如 我们上文提到的学生类Student.java,其中的String name等就是暴露出来的变量属性,我们可以在Test.java轻松的对其进行非法赋值,比如将int age变量赋值为-18或者200岁,这是明显不可能的事情,但如果没有封装,那外界调用学生类时就可以对其进行非法修改。

如果此时我们对其进行封装,即为对student类中的变量,用private对其进行修饰,并写出每个变量的setter和getter方法,则如下图所示,我们可以在setter方法中加入验证逻辑,确保每一个写入的年龄数值age都能合理合法,并在Test.java中调用setAge()方法对变量进行赋值。

这时,如果输入年龄为300,则会报错invaild age number。
//Student.java
public class Student {
private String name;
private int age;
private char gender;
public void setAge(int age){
if (age > 0 && age < 200){
this.age = age;
}else {
System.out.println("invalid age number");
}
}
public int getAge() {
return age;
}
}
//Test.java
public class Test {
public static void main(String[] args) {
Student s1 =new Student();
s1.setAge(30);
System.out.println(s1.getAge());
}
}
封装,即将类的成员变量都设置成private,并为其提供成套的setter和getter方法,已经成为了Java的设计风格,必须遵守。
4.JavaBean(也叫实体类)
JavaBean(或实体类),是一种特殊类,类中要满足如下需求:
- 要求1:类中的成员变量全部私有,并提供public修饰的getter/setter方法
- 要求2:类中需要提供一个无参数构造器,有参数构造器可选
以下即为实例的JavaBean Student类:
//JavaBean(也叫实体类)实例:
public class Student {
//1.私有化成员变量
private String name;
private int age;
private char gender;
//2.提供一个无参构造器
//如果不提供有参构造器 可以不手动提供无参构造器 因为类会自带一个无参构造器 这个构造器即可满足JavaBean要求
public Student(){
}
//3.提供有参构造器
public Student(String name, int age,char gender){
this.name = name;
this.age = age;
this.gender = gender;
}
//4.为每个成员变量提供公开的getter和setter方法。
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
}
实体类有啥应用场景?
实体类对象只负责数据存取,而对数据的业务处理交给其他类的对象来完成,以实现数据和数据业务处理相分离。
例如Student.java类只负责数据存取,而对数据的业务处理交给另外创建的StudentOperator.java类进行处理,实现数据和数据业务的相分离。
例如以下代码,Test.java为程序主入口,Student.java类只负责数据的存取,同时新建一个StudentOperator.java类用以操作数据:
//Test.java
public class Test {
public static void main(String[] args) {
Student s1 = new Student();
s1.setAge(18);
s1.setName("小明");
s1.setGender('男');
s1.setChinese(80);
StudentOperator so1 = new StudentOperator();
//StudentOperator so1 = new StudentOperator(s1);
so1.setS(s1);
so1.printSum();
}
}
//Student.java
//JavaBean(也叫实体类)实例:
public class Student {
//1.私有化成员变量
private String name;
private int age;
private char gender;
private double chinese;
//2.提供一个无参构造器
//如果不提供有参构造器 可以不手动提供无参构造器 因为类会自带一个无参构造器 这个构造器即可满足JavaBean要求
public Student(){
}
//3.提供有参构造器
public Student(String name, int age,char gender){
this.name = name;
this.age = age;
this.gender = gender;
}
//4.为每个成员变量提供公开的getter和setter方法。
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
public double getChinese() {
return chinese;
}
public void setChinese(double chinese) {
this.chinese = chinese;
}
}
//StudentOperator.java
public class StudentOperator {
private Student s;
//public StudentOperator(Student s){
// this.s = s;
//}
public void setS(Student s) {
this.s = s;
}
public void printSum(){
System.out.println(s.getName());
}
}
其中提供了两种将Student对象s1提供给StudentOperator.java类的方法,见红框与绿框(代码段中被注释掉的代码)

5.static-关键字
static关键字叫静态,可以修饰成员变量、成员方法。
(1)static修饰成员变量
成员变量按照有无static修饰,分为两种:
- 静态变量(类变量):
有static修饰,属于类的变量,在计算机内存中只有一份,被类里的所有对象共享
- 实例变量(对象的变量):
没有static修饰,属于每一个对象。
例如如下代码段,name为有static修饰的静态变量(类变量),所以无论有多少对象被创建,name都只有一份(内存中只有一份)。而age变量为没有static修饰的实例变量(对象的变量),每创建一个对象,每个对象的内存中就会为每个对象创建一个age区域,用于存储每个对象的age数据。

//Student.java
public class Student {
//1.静态变量(类变量)
//有static修饰,属于类的变量,在计算机内存中只有一份,被类里的所有对象共享
static String name;
//2.实例变量(对象的变量)
//没有static修饰,属于每一个对象的变量
int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void printName(){
System.out.println(Student.name);
}
public void printAge(){
System.out.println(this.age);
}
}
//Test.java
public class Test {
public static void main(String[] args) {
Student.name = "小明";
System.out.println(Student.name);
Student s1 = new Student();
s1.name = "小红"; //不推荐这样定义静态变量,仅作演示,请使用类名.静态变量名称进行访问和修改
//s1.printName();
Student s2 = new Student();
s2.name = "小黄";
s2.printName(); //结果为小黄
s1.printName(); //结果为小黄
//因为name为静态变量 类中只有一份 内存中也只有一份储存空间 所以修改的是一个东西
s1.age = 18;
s2.age = 20;
s1.printAge();
s2.printAge();
//age为对象的变量 所以每个对象内存中都有一个age内存 所以打印出来不一样
}
}
静态变量的应用场景:
如果某个数据只需要一份,且希望能够被共享(访问、修改),则该数据可以定义成静态变量来记住。
例如,系统启动后,要求用户类可以记住自己创建了多少个用户对象了。那这时我们就可以创建一个静态变量number,每创建一个对象就number++,从而进行记录。

(2)static修饰方法
成员方法的分类
1.静态方法:有static修饰的成员方法,属于类。
2.实例方法:没有static修饰的成员方法,属于每个对象。

示例代码段如下所示:
//Student.java
public class Student {
private double score;
//1.静态方法:有static修饰 属于类本身
public static void printHelloWorld(){
System.out.println("HelloWorld");
System.out.println("HelloWorld");
System.out.println("HelloWorld");
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
//2.实例方法 没有static修饰 属于对象持有
public void printPass(){
System.out.println(score >= 60 ? "pass" : "fail");
}
}
//Test.java
public class Test {
public static void main(String[] args) {
Student.printHelloWorld(); //类名.静态方法名
Student s1 = new Student();
s1.setScore(59.5);
s1.printPass(); //对象名.实例方法
}
}


小结:

(3)静态方法的应用
静态方法的常见应用场景:做工具类。
工具类是什么?
工具类中的方法都是一些静态方法,每个方法用来完成一个功能,以便于供给开发人员使用,进入企业后,企业内部可能有一个上千个方法的utili.java类供给程序员调用。
***多学一招***

因为工具类没有创建对象的需求,那么如果放开创建对象功能,虽然无意义,但程序仍然会在内存中给他分配一个区域,进而占用内存,为避免这种情况,建议将工具类私有化。

(4)static的注意事项
理解完成以下几句话 说明对static的理解程度已经很不错了。

05综合实战-电影信息展示
简易版电影信息展示系统:

Movies.java类文件:
//Movies类只用来存储对象和数据
public class Movies {
private int id;
private String name;
private double price;
private String actor;
public Movies(){
}
public Movies(int id, String name, double price, String actor){
this.id = id;
this.name = name;
this.price = price;
this.actor = actor;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getActor() {
return actor;
}
public void setActor(String actor) {
this.actor = actor;
}
}
MoviesOperator.java
import java.util.Scanner;
//MoviesOperator类用以处理逻辑
public class MoviesOperator {
private Movies[] movies;
public MoviesOperator(Movies[] movies){
this.movies = movies;
}
public void printAll(){
for (int i = 0; i < movies.length; i++) {
System.out.println(movies[i].getId() + "\t" + movies[i].getName() + "\t" + movies[i].getPrice() + "\t" + movies[i].getActor());
}
}
public void printById(){
Scanner sc = new Scanner(System.in);
int id = sc.nextInt();
for (int i = 0; i < movies.length; i++) {
//********关键代码**********
Movies m = movies[i];
//********关键代码**********
if (m.getId() == id){
System.out.println(movies[id-1].getId() + "\t" + movies[id-1].getName() + "\t" + movies[id-1].getPrice() + "\t" + movies[id-1].getActor());
return; //*********结果输出完毕 结束循环********
}
}
System.out.println("wrong movie Id");
}
}
Test.java
public class Test {
public static void main(String[] args) {
Movies[] arr = new Movies[6]; //这里的6是数组长度 因此只有6个对象
arr[0] = new Movies(1,"喜羊羊与灰太狼", 9.5, "喜羊羊、灰太狼");
arr[1] = new Movies(2,"唐顿庄园", 8.5, "唐顿");
arr[2] = new Movies(3,"夏洛特烦恼", 9.5, "沈腾");
arr[3] = new Movies(4,"变形金刚", 9.5, "擎天柱、威震天");
arr[4] = new Movies(5,"熊出没", 9.5, "熊大、熊二、光头强");
arr[5] = new Movies(6,"食贫道", 9.5, "饼叔");
MoviesOperator moviesOperator = new MoviesOperator(arr);
moviesOperator.printAll();
moviesOperator.printById();
}
}

651

被折叠的 条评论
为什么被折叠?



