你听过这个笑话吗?你有对象吗?没有的话就new一个吧!
但是此对象非彼对象哦~
1.什么是对象?
Java是一门面向对象的语言(OOP),在Java中,有一句话叫:万事万物皆为对象。
我们生活中的每一件东西都可以看作是一个对象,包括我们本身都是一个对象。
这是一种抽象的思想,我们将一件事物提取出特征和行为,将特征定义为属性,将行为封装成方法。
如,一个人,特征有姓名、年龄、性别、职业等等,行为有吃饭、睡觉、学习等等。
2.什么是面向对象?
面向过程:了解面向对象前,先了解面向过程。我们之前所编写的程序都是面向过程的,分析解决问题的步骤,然后按照步骤第一步做什么,第二步做什么......如果将步骤写成了方法,就依次调用方法。适合处理简单的问题。
面向对象:而面向对象是一种抽象的分类的思想,分析解决问题需要从哪几个方面出发,即有哪几个分类,然后对这些分类进行单独的面向过程的思考,每一个分类需要具体的完成什么。用于处理复杂的问题。
例:
面向过程:一个人要喝水,那么他首先就看看杯子里有没有水,有的话就喝水,没有的话,就倒水再喝水。
面向对象:现在要建一栋房子,这就更复杂了,首先需要分为三大类,需要设计人员设计图纸,需要建筑人员建房子,需要装修人员装修;而设计人员怎么设计图纸,建筑人员怎么建造,装修人员怎么装修又是每一个分类的具体细节。
而我们到最后要用Java来完成的东西,肯定是复杂的,所以面向对象思想极其重要。我们主要从以下思考出发:
对象有哪些?对象的特征(属性)和行为(方法)是什么?对象与对象的关系是什么?
3.类与对象的关系
我们知道,不管使用什么思想,Java的代码一定是编写在类中的,所以我们的对象也肯定是在类中的,而上述我们又提到,我们要在类中定义对象的特征(属性)和行为(方法),所以我们可以总结面向对象编程的本质:
面向对象编程的本质:以类的形式组织代码,以对象的形式组织(封装)数据。
那类是对象是什么关系呢?
从认识论的角度来看:我们先确定了对象,再为该对象书写一个类。(我们确定了学生为一个对象,就需要定义一个对应的学生类,在类 中书写学生的特征(属性)和行为(方法));
从代码运行角度来看:我们是先有了类,再使用类创造了对象。(我们代码的运行首先会加载该学生类,再运行该类中的代码,如对象操 作等内容)。
所以,类与对象的关系总结如下:
类是对象的模板。(在类中定义了对象的属性和行为,即提供了对象的基本框架。)
对象是类的实例。(我们通过类来创建对象。)
类是具有共同属性和行为的对象的抽象。(一个学生类,张三是学生,李四也是学生,他们拥有姓名、性别、学号等,也有共同的行为,学习。)
4.类的定义
之前,我们没有具体的探究过类的定义,直接使用的是IDEA中自动生成的模板,我们现在再来看一下这个模板:
package com.dh.oop;
public class OopDemo01 {
}
权限修饰符
自动生成的类中的权限符为最大的public,我们换成其它的修饰符会怎么样呢?
可以看到,只能用public或者是default这两个权限修饰符来修饰类,protected和private是不能用来修饰类的!
其实也不难理解,因为类是Java的最小单位,我们解决问题就是通过一个一个类联合起来的,如果权限符为protected和private了,就有了很大的访问局限,这个类差不多就是个单独的类,和别的类没什么关系,那这个类的意义也就不大了。就像煮饭,菜刀拿来切菜,但是你把菜刀锁进了柜子里,只有拥有那把钥匙的厨师才能使用它,那这菜刀存在的意义就不大了。
那可以定义多个类吗?
我们可以看到,在一个.java文件中,可以定义多个类,但是只能有一个被public修饰。
但是一般不建议在一个java文件中书写多个类,一个java文件一般只书写一个类,不就是多建一个java文件的事嘛,也不麻烦对不对
class
Java使用class关键字来定义一个类。
类名
类名的定义要符合标识符的命名规则,最好见名知意,一般为驼峰命名法,每个单词的首字母都大写。
需要注意的是:在同一个包下的类不允许重名,在不同包下的类允许同名。
注意:
在类体中不能直接出现可执行语句,会直接红色波浪线报错
if、switch、while、do...while、for;
打印语句;
赋值语句;
......
5.对象的声明和使用
首先,我们要在类中定义对象的属性和方法:
package com.dh.oop;
//学生类
public class Student {
//属性和方法是同一级别的
//属性
public String name;
public int age;
public char sex;
public int num;
//方法
public void study(){
System.out.println("学生学习");
}
//程序入口:main方法
public static void main(String[] args) {
}
}
成员变量、局部变量、类变量
之前我们都是将变量直接定义在方法内部的,现在却定义在了方法的外部。这里就涉及到了成员变量和局部变量的概念了。
成员变量:定义在类的内部,方法的外部。具有默认值(整数为0,浮点数为0.0,布尔值为false,char为'',引用为null);
别名:实例变量。
作用域:类中。(本类中可直接使用,其他类也可能可以使用对象调用,具体看是否有权限)
使用方法:对象.变量调用,this.变量名调用,直接调用。
局部变量:定义在方法的内部。没有默认值,必须赋初始值才能使用,否则使用会报错;
作用域:定义的那个方法中。
使用方法:在方法中直接使用。
类变量:被static修饰的变量,也是成员变量的一种。**该变量属于类,凌驾于对象之上,只有一份,给所有的实例对象共享。
别名:静态变量。
作用域:类中。(本类中可直接使用,其他类也可能可以使用对象调用或者类名调用,具体看是否有权限)
注意:只能修饰成员变量,不能修饰局部变量。
使用方法:在static方法中直接使用,可以通过对象.变量名调用,也可以直接使用类名.变量名调用。
(可能有些现在不理解的,会慢慢在后续讲到~)
成员变量和局部变量可重名,重名时遵循就近原则:
package com.dh.oop;
public class Student {
public String name = "张三";
public static void study(String name){
System.out.println(name +"在学习");
}
public static void main(String[] args) {
study("李四");
}
}
局部变量和成员变量都为name,但是输出结果为李四在学习,可以证明,使用的是局部变量:
对象的声明
语法:类名 对象名 ;
Student student;
对象的声明可以在类体中,也可以在方法中。
对象的实例化
语法:对象名 = new 类名();
student = new Stdent();
扩展:在类体中实例化自身而导致的栈溢出问题
针对上述在类体中声明对象,如果该对象是在static方法中实例化的话,注意对象也需要定义成static。如果直接在类体中实例化对象,当其他方法中有实例化对象的操作时,会发生栈溢出错误:
package com.dh.oop;
public class StudentDemo {
public String name;
public int age;
StudentDemo s = new StudentDemo();//栈溢出
public static void main(String[] args) {
StudentDemo studentDemo = new StudentDemo();
}
}
错误原因分析:在main方法中new一个对象的话,会初始化该类的成员变量,变量里又有new操作,又要去初始化成员变量,又有new,然后就一直得在栈里开辟空间,就会导致栈溢出错误。
解决方案:将需要在类中实例化的对象定义成static。
原理:如果是static的话,只在首次new的时候开辟内存,new新对象的时候,再就不会开辟新的内存,直接指向第一个,就不会栈内存不够而溢出了。
边声明边实例化
语法:类名 对象名 = new 类名();
//声明一个student对象
Student student = new Student();
//可声明多个,不可重名
Student student1 = new Student();
//student和student是不同的两个对象
推荐使用这种方法!
对象的赋值和使用
语法:
属性的赋值:对象名.变量名 = 值;
属性的使用:对象名.变量名;
方法的使用:对象名.方法(【参数】);
//属性的使用
student.name = "zhangsan";
student.age = 18;
student.sex = '男';
student.num = 001;
System.out.println(student.name+"\t"+student.age+"\t"+student.sex+"\t"+student.num);
//方法的使用
student.study("李四");
不同的对象可以自定义其自己的属性值
//不同的对象可以有不同的属性
student1.name = "lisi";
student1.age = 19;
student1.sex = '男';
student1.num = 002;
System.out.println(student1.name+"\t"+student1.age+"\t"+student1.sex+"\t"+student1.num);
//不同的对象调用方法
student1.study("lisi");
总代码:
package com.dh.oop;
public class Student {
//可以赋初值,如果不赋值的话也会有默认值
public String name = "张三";
public int age;
public char sex;
public int num;
//成员方法
public void study(String name){
System.out.println(name+"在学习");
}
public static void main(String[] args) {
//声明一个student对象
Student student = new Student();
//可声明多个,但不可重名
Student student1 = new Student();
//属性的使用
student.name = "zhangsan";
student.age = 18;
student.sex = '男';
student.num = 1001;
System.out.println(student.name+"\t"+student.age+"\t"+student.sex+"\t"+student.num);
//方法的使用
//对象可以在static方法中直接调用非static方法(如果直接调用就只能调用static方法,对象的强大性来了!)
student.study("zhangsan");
//不同的对象可以有不同的属性
student1.name = "lisi";
student1.age = 19;
student1.sex = '男';
student1.num = 1002;
System.out.println(student1.name+"\t"+student1.age+"\t"+student1.sex+"\t"+student1.num);
//不同的对象调用方法
student1.study("lisi");
}
}
代码运行结果:
本人水平有限,若有错误望指出~感激不尽!