一、面向对象入门
对象是一种特殊的数据结构,可以用来记住一个事物的数据,从而代表该事物。
步骤:
1.先设计对象的模板,也就是对象的设计图:类。
2.通过new关键字,每new一次类就得到一个新的对象。
oop面向对象,object对象
package com.itheima.object;
public class Test {
public static void main(String[] args) {
//目标:学会创建对象。
//创建对象的格式:类名 对象名 = new 类名();
Star s1 = new Star();
s1.name = "王宝强";
s1.age = 38;
s1.gender = "男";
s1.height = 168;
s1.weight = 68;
System.out.println(s1.name);
System.out.println(s1.age);
System.out.println(s1.gender);
System.out.println(s1.height);
System.out.println(s1.weight);
//创建对象,存储宋江的数据
Star s2 = new Star();
s2.name = "宋江";
s2.age = 22;
s2.gender = "男";
s2.height = 178;
s2.weight = 80;
System.out.println(s2.name);
System.out.println(s2.age);
}
}
package com.itheima.object;
//明星类:明星对象的模板。
public class Star {
String name;
int age;
String gender;
double height;
double weight;
}
案例:
请用面向对象编程的方式,存储如下两个学生的信息,并要求打印出每个学生的总成绩和平均成绩
package com.itheima.object;
public class Test2 {
public static void main(String[] args) {
//目标:创建学生对象存储学生数据,并操作学生数据。
Student s1 = new Student();
s1.name = "波妞";
s1.chinese = 100;
s1.math = 100;
s1.printAllScore();
s1.printAverageScore();
Student s2 = new Student();
s2.name = "波仔";
s2.chinese = 66;
s2.math = 96;
s2.printAllScore();
s2.printAverageScore();
}
}
package com.itheima.object;
//学生类
public class Student {
String name;
double chinese;
double math;
public void printAllScore() {
System.out.println(name+"的总成绩是:"+
(chinese + math));
}
public void printAverageScore() {
System.out.println(name+"的平均成绩是:"+
(chinese + math)/2);
}
}
在对象类中使用封装的思想减少代码冗余。
二、对象
对象本质上是一种特殊的数据结构(可以理解成一张表)。对象是用类new出来的,有了类就可以创建处对象。对象class也就是类,也称为对象的设计图(或者对象的模板)。
对象在计算机运行的原理
方法区用于存放类文件;栈内存用于存储main函数;堆内存用于存储对象和类的地址。
面向对象编程:万物皆可对象,谁的数据谁存储。
类在对象那个中只有一个,但可以有千千万万个对象。每new一次就会创建一个对象。
三、类的基本语法
3.1 构造器
构造器:是一种特殊方法,不能写返回值类型,名称必须是类名,就是构造器。
特点:创建对象时,对象会立即自动调用构造器。
应用:
1.对象创建时,我们可以指定对象去调用哪个构造器执行。
2.创建对象时可以立即为对象赋值,构造器常用于完成对象初始化(常见的应用场景是完成对象的成员变量的初始化赋值)
注意:
1.类默认就自带一个无参构造器
2.如果为类定义了有参构造器,类默认的无参数构造器就没有了,此时如果还想用无参数构造器,就必须自己手写一个无参数构造器出来。
3.有参构造器可以重载
4.构造器的常见应用场景可以有效的简化代码。根据构造器的注意事项,在实际应用中,为了避免无参构造器消失,一般要么不用构造器要么使用构造器时无参和有参都写。
名字必须跟类名相同。constructor构造器
package com.itheima.object.constructor;
public class Test {
public static void main(String[] args) {
//目标:认识类,搞清楚其特点和常用场景。
// 构造器的特点:创建对象时,对象会立即自动调用构造器。
Student s1 = new Student();
Student s2 = new Student("西门吹雪");
System.out.println("============");
Student t1 = new Student();
t1.name = "宋江";
t1.age = 22;
t1.sex = '男';
System.out.println(t1.name);
System.out.println(t1.age);
System.out.println(t1.sex);
//对象的一种常见应用场景,创建对象时可以立即为对象赋值
Student t2 = new Student("许凯", 30, '男');
System.out.println(t2.name);
System.out.println(t2.age);
System.out.println(t2.sex);
}
}
package com.itheima.object.constructor;
public class Student {
String name;
int age;
char sex;
//1.无参构造器
//构造器:是一种特殊方法,不能写返回值类型,名称必须是类名,就是构造器。
public Student(){
System.out.println("=====无参构造器执行====");
}
//2.有参数构造器
public Student(String n){
System.out.println("===有参数构造器执行===");
}
public Student(String n, int a, char s){
name = n;
age = a;
sex = s;
}
}
3.2 this
this就是一个变量,可以用在方法中,用来拿到当前对象;哪个对象调用方法,this就指向那个对象,也就是拿到哪个对象。
应用:用来解决对象的成员变量与方法内部变量的名称一样时,导致访问冲突问题的。
注:在编写代码时,变量名一般要求见名知义。
package com.itheima.object.thisdemo;
public class Test {
public static void main(String[] args) {
//目标:认识this关键字,搞清楚this关键字的应用场景。
Student s1 = new Student();
s1.name = "张三";
s1.print();
System.out.println(s1);
System.out.println("==========================================");
Student s2 = new Student();
s2.print();
System.out.println(s2);
System.out.println("==========================================");
Student s3 = new Student();
s3.name = "宋江";
s3.printHobby("唱歌");
}
}
package com.itheima.object.thisdemo;
public class Student {
//成员变量
String name;
public void print(){
//this是一个变量,用在方法中,用于拿到当前对象。
//哪个对象调用这个方法,this就拿到哪个对象。
System.out.println(this);
System.out.println(this.name);
}
public void printHobby(String name){
System.out.println(this.name + "喜欢" + name);
//this.name指对象的名字,name表示局部变量的名字
}
}
标准有参构造器的写法,如下
3.3 封装
面向对象的三大特征:封装、继承、多态
封装:就是用类设计对象处理某一个事物的数据时,应该把要处理的数据,以及处理这些数据的方法,设计到一个对象中去。
类就是一种封装。
封装的设计规范:合理隐藏,合理暴露。
公开成员,可以使用public(公开)进行修饰。
隐藏成员,使用private(私有,隐藏)进行修饰。
capsulation封装
package com.itheima.object.capsulation;
public class Test {
public static void main(String[] args) {
//目标:搞清楚封装的设计思路:合理隐藏合理暴露,学会如何隐藏如何暴露。
Student s1 = new Student();
s1.setAge(-19);//赋值
System.out.println(s1.getAge());//取值
}
}
package com.itheima.object.capsulation;
public class Student {
String name;
//1.如何隐藏:使用private关键字(私有,隐藏)修饰成员变量,就只能在本类中被直接访问。
//其他任何地方不能直接访问。
private int age;
private double chinese;
private double math;
//2.如何暴露(合理暴露):使用public修饰(公开)的get和set方法合理暴露
//成员变量的取值和赋值。
public void setAge(int age) { // 为年龄赋值
if (age > 0 && age < 120) {
this.age = age;
}else{
System.out.println("年龄不合法!");
}
}
public int getAge() { // 获取年龄
return age;
}
public void printAllScore() {
System.out.println(name+"的总成绩是:"+
(chinese + math));
}
public void printAverageScore() {
System.out.println(name+"的平均成绩是:"+
(chinese + math)/2);
}
}
目前java规范:即使以后代码不进行校验(即使毫无意义),也应该把成员变量私有起来,然后使用get和set对外进行暴露,来赋值和取值。
3.4 Javabean
实体类:是一种特殊类,仅仅只是一个用来保存数据的java类,可以用它创建对象,保存某个事物的数据。
实体类中要满足如下需求:
1.类中的成员变量必须全部私有,并提供public修饰的get、set方法(可以中生成,右击鼠标,点击“生成”,选择get和set,确定即可)。
2.类中需要提供一个无参数构造器,有参数构造器可选
应用:实体类对应的是软件开发里现在比较流行的开发方式,数据和数据的业务处理相分离。实体类的对象只负责数据存取,而对数据的业务处理交给其他类的对象来完成,以实现数据和数据业务处理相分离。
package com.itheima.object.javabean;
public class Test {
public static void main(String[] args) {
//目标:搞清楚实体类是啥?搞清楚其基本作用和应用场景。
//实体类的基本作用,创建它的对象,存取数据(封装数据)
Student s1 = new Student();
s1.setName("张三");
s1.setChinese(100);
s1.setMath(90);
System.out.println(s1.getName());
System.out.println(s1.getChinese());
System.out.println(s1.getMath());
Student s2 = new Student("李四", 80, 90);
System.out.println(s2.getName());
System.out.println(s2.getChinese());
System.out.println(s2.getMath());
//实体类在开发中的应用场景。
//创建一个学生的操作对象专门负责对学生对象的数据进行业务处理。
StudentOperator operator = new StudentOperator(s1);
operator.printAverageScore();
operator.printTotalScore();
}
}
package com.itheima.object.javabean;
public class StudentOperator {
//必须拿到要处理的学生对象
private Student s;//用于记住将要操作的学生对象。
public StudentOperator(Student s) {
this.s = s;
}
//提供方法:打印学生对象的总成绩
public void printTotalScore() {
System.out.println(s.getName()+"的总成绩是:"+
(s.getChinese() + s.getMath()));
}
//提供方法:打印学生对象的平均成绩
public void printAverageScore() {
System.out.println(s.getName()+"的平均成绩是:"+
(s.getChinese() + s.getMath())/2);
}
}
package com.itheima.object.javabean;
//实体类
public class Student {
//1.私有成员变量
private String name;
private double chinese;
private double math;
//必须提供无参数构造器
//右击鼠标,点击生成,点击构造器,
// 点击确定按钮右侧“无选择”按钮
public Student() {
}
//提供一个有参数构造器(可选)
//右击鼠标,点击生成,点击构造器,按shift键+鼠标,
// 全选,确定
public Student(String name, double chinese, double math) {
this.name = name;
this.chinese = chinese;
this.math = math;
}
//2.提供公开的getter和setter方法。
//右击鼠标,点击“生成”,选择get和set
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getChinese() {
return chinese;
}
public void setChinese(double chinese) {
this.chinese = chinese;
}
public double getMath() {
return math;
}
public void setMath(double math) {
this.math = math;
}
}
运行流程
3.5 static
3.5.1 static修饰成员变量
static关键字:叫静态,可以修饰成员变量、成员方法。
成员变量按照有无static修饰,分为两种:
静态变量(类变量):有static修饰,属于类,在计算机里只有一份,会被类的全部对象共享。
实例变量(对象的变量):无static修饰,属于每个对象的。
成员变量和成员方法是类中的变量和方法。
static修饰的成员变量叫类变量(静态成员变量)
调用方法:类名.静态变量(推荐);对象名.静态变量(不推荐)
静态成员变量属于类,与类一起加载一次,在内存中只有一份,会被类的所有对象共享。
无static修饰的变量叫实例变量(对象变量)
调用方法:对象.实例变量
实例变量属于对象,每个对象中都有一份,只能用对象访问。
成员变量的执行原理:
staticfield静态变量
package com.itheima.object.staticfield;
public class Test {
public static void main(String[] args) {
//目标:认识static修饰成员变量,特点、访问机制,搞清楚作用。
//1.类名.静态变量(推荐)
Student.name = "宋江";
System.out.println(Student.name);
//2.对象名.静态变量(不推荐)
Student s1 = new Student();
s1.name = "许凯";
Student s2 = new Student();
s2.name = "李昀锐Lin";
System.out.println(s1.name);//李昀锐Lin
System.out.println(Student.name);//李昀锐Lin
//3.对象名.实例变量
s1.age = 22;
s2.age = 28;
System.out.println(s1.age);//22
}
}
package com.itheima.object.staticfield;
public class Student {
//静态变量:有static修饰,属于类,只加载一份,可以被类和类的全部对象共享。
static String name;
//实例变量:没有static修饰《属于对象,每个对象都有一份
int age;
}
两种成员变量的应用场景:
静态变量:数据只需要一份,且需要被共享时(访问、修改)
实例变量:每个对象都要有一份,数据各不同(如:name、score、age)
注:访问自己类中的类变量时,可以省略类名不写。在某个类中访问其他类里的类变量,必须带类名访问。
案例:
系统启动后,要求用户类可以记住自己创建了多少个用户对象了。
package com.itheima.object.staticfield;
public class Test2 {
public static void main(String[] args) {
// 目标:了解静态变量的应用。
new User();
new User();
new User();
new User();
new User();
new User();
System.out.println(User.count);
}
}
package com.itheima.object.staticfield;
public class User {
public static int count = 0;
public User(){
//User.count++;
//注意:同一个类中访问静态成员可以省略类名不写
count++;
}
}
3.5.2 static修饰方法
成员方法的分类:
1.静态方法(类方法):有static修饰的成员方法,属于类,可以直接用类名访问,也可以用对象访问。
调用:类名.静态方法(推荐);对象名.静态方法(不推荐)
2.实例方法(对象的方法):无static修饰的成员方法,属于对象,只能用对象访问。
调用:对象.实例方法
注意:main是静态方法,静态方法调用更快,系统是直接通过调用Test.main()来进行调用的。
staticmethod静态方法
规范:如果这个方法只是为了做一个功能且不需要直接访问对象的数据,这个方法直接定义成静态方法;如果这个方法是对象的行为,需要访问对象的数据,这个方法必须定义成实例方法。
package com.itheima.object.staticmethod;
public class Test {
public static void main(String[] args) {
//目标:认识static修饰和不修饰方法的区别
//1.类名.静态方法(推荐)
Student.printHelloWorld();
//2.对象.静态方法(不推荐)
Student s1 = new Student();
s1.printHelloWorld();
//3.对象名.实例方法
//Student.printPass();//报错
s1.setScore(59.5);
s1.printPass();
//规范:如果这个方法只是为了做一个功能且不需要直接访问对象的数据,这个方法直接定义成静态方法
//如果这个方法是对象的行为,需要访问对象的数据,这个方法必须定义成实例方法。
//Test.printHelloWorld2();
printHelloWorld2();
}
public static void printHelloWorld2(){
System.out.println("Hello World2");
System.out.println("Hello World2");
System.out.println("Hello World2");
System.out.println("Hello World2");
}
}
package com.itheima.object.staticmethod;
public class Student {
private double score;
//静态方法:有static修饰,属于类特有。
public static void printHelloWorld(){
System.out.println("Hello World");
System.out.println("Hello World");
System.out.println("Hello World");
}
//实例方法:没有static修饰,属于对象持有。
public void printPass(){
System.out.println(score >= 60 ? "Pass" : "没通过");
}
public void setScore(double score) {
this.score = score;
}
}
3.5.3 静态方法的应用
静态方法常用于设计工具类。
工具类是:工具类中的方法都是静态方法,每个类方法都是用来完成一个功能的。提高了代码的复用性;调用方便,提高了开发效率。
工具类中的方法要用静态方法,而不用实例方法的原因:实例方法需要创建对象来调用,此时对象只是为了调用方法,对象占内存,这样会浪费内存。静态方法,直接用类名调用即可,调用方便,也能节省内存。
工具类定义时的要求:工具类没有创建对象的需求,建议将工具类的构造器进行私有。将工具类的构造器私有化可以大大提高代码的高级度。
package com.itheima.object.staticmethod;
public class Test2 {
public static void main(String[] args) {
//目标:搞清楚静态方法的应用:可以做工具类。
//登陆界面
//开发一个验证码程序
String code = VerifyCodeUtil.getCode(4);
System.out.println(code);
System.out.println(Math.random());//[0.0-1.0)
}
}
package com.itheima.object.staticmethod;
public class Test3 {
public static void main(String[] args) {
//目标:搞清楚静态方法的应用:可以做工具类。
//注册界面
//开发一个验证码程序
String code = VerifyCodeUtil.getCode(6);
System.out.println(code);
}
}
package com.itheima.object.staticmethod;
public class VerifyCodeUtil {
//工具类没有创建对象的必要性,所以建议私有化构造器
private VerifyCodeUtil(){}
public static String getCode(int n){
//2.定义一个字符串变量用于记录生产的验证码
String code = "";
//3.循环n次,每次生成一个验证码
for (int i = 0; i < n; i++) {
//i=0 1 2 3
//4.为当前位置随机生成一个数字或者大写字母或者小写字母。数字/0 大写/1 小写/2
//随机一个0 或者 1 或者 2 表示当前位置随机的字符类型
int type=(int)(Math.random()*3);//[0,1)*3=>0 1 2
//5.使用swith判断当前位置随机的字符类型
switch(type) {
case 0:
//6.如果当前位置是数字,则随机生成一个数字0-9,然后拼接。
int num=(int)(Math.random()*10);
code +=num;
break;
case 1:
// 7.如果当前位置是大写字母,则随机生成一个大写字母A-Z,然后拼接。'A'65 'Z'90
int num1=(int)(Math.random()*26);//[0,25]
char ch=(char)('A'+num1);//得到大写字母的随机编号,转成大写字母
code += ch;
break;
case 2:
//8.如果当前位置是小写字母,则随机生成一个小写字母a-z,然后拼接。'a'97 'z'122
int num2=(int)(Math.random()*26);//[0,25]
char ch1=(char)(97+num2);
code +=ch1;
break;
}
}
return code;
}
}
3.5.4 static的注意事项
1.静态方法中可以直接访问静态成员,不可以直接访问实例成员。
2.实例方法中既可以直接访问静态成员,也可以直接访问实例成员。
3.实例方法中可以出现this关键字,静态方法中不可以出现this关键字的。
package com.itheima.object.staticmethod;
public class Test4 {
//静态变量
public static int count = 100;
//静态方法
public static void printHello()
{
System.out.println("Hello");
}
//实例变量:属于对象的
public String name;
//实例方法:属于对象的
public void run() {
}
public static void main(String[] args) {
//目标:搞清楚静态方法,实例方法访问的几点注意事项。
printHelloWorld();
}
//1.静态方法中可以直接访问静态成员,不可以直接访问实例成员。
public static void printHelloWorld(){
System.out.println(count);
printHello();
//System.out.println(name);//报错
//run();//报错
//System.out.println(this);//报错。this代表的只能是对象。
}
//2.实例方法中既可以直接访问静态成员,也可以直接访问实例成员。
//3.实例方法中可以出现this关键字,静态方法中不可以出现this关键字的。
public void go(){
System.out.println(count);
printHello();
System.out.println(name);
run();
System.out.println(this);
}
}
四、综合小项目
package com.itheima.object.demo;
public class Test {
public static void main(String[] args) {
//目标:完成面向对象的综合小案例
//1.设计电影Movie,以便创建电影对象,封装电影数据。
//2.封装系统中的全部电影数据。(自己造一些数据)实际中从数据库中导入
//类本质也是一种类型,可以直接使用类进行定义数组
Movie[] movies = new Movie[6];
//movies = [null,null,null,null,null,null]
// 0 1 2 3 4 5
movies[0] = new Movie(1,"星际穿越",20.5,"张艺谋");
movies[1] = new Movie(2,"速度与激情7",30.5,"章子怡");
movies[2] = new Movie(3,"海蒂和爷爷",40.5,"Heidi");
movies[3] = new Movie(4,"何以为家",50.5,"章子怡");
movies[4] = new Movie(5,"怦然心动",60.5,"Flipped");
movies[5] = new Movie(6,"这个杀手不太冷",70.5,"Leon");
//3.创建电影操作对象出来,专门负责电影数据的业务操作。
MovieOperator mo = new MovieOperator(movies);
mo.printAllMovies();//快捷键:Alt+Enter+Enter
mo.searchMovieById();
}
}
package com.itheima.object.demo;
public class Movie {
private int id;//编号
private String name;
private double price;
private String actor;
public Movie(){}
//定义一个有参数构造器
public Movie(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;
}
}
package com.itheima.object.demo;
import java.util.Scanner;
//电影操作类
public class MovieOperator {
private Movie[] movies;//记住一个电影对象的数组
public MovieOperator(Movie[] movies) {
this.movies = movies;
}
//打印全部电影信息
public void printAllMovies() {
System.out.println("编号\t电影名\t价格\t主演");
for (int i = 0; i < movies.length; i++) {
Movie m = movies[i];
System.out.println(m.getId() + "\t" + m.getName() + "\t" + m.getPrice() + "\t" + m.getActor()+"\t");
}
}
//根据id查询电影
public void searchMovieById() {
System.out.println("请输入要查询的电影编号:");
Scanner sc = new Scanner(System.in);
int id = sc.nextInt();
//遍历每个电影对象
for (int i = 0; i < movies.length; i++) {
//拿到当前遍历到的电影对象
Movie m = movies[i];
//判断当前电影对象的id是否是我们正在找的电影id,是则打印出该电影信息并立即结束方法
if (m.getId() == id) {
System.out.println(m.getId() + "\t" + m.getName() + "\t" + m.getPrice() + "\t" + m.getActor()+"\t");
return;
}
}
System.out.println("没有找到该电影!");
}
}