前言
在计算机编程中,不管是面向对象亦或是面向过程都是解决问题的一种思路。而java作为一种面向对象的语言,自然有其独到之处,接下来我们将详细讲解关于java中的类和对象相关知识点。
一、类的定义
1.1 简单认识类
类是用来对一个对象进行描述的,主要描述该实体具有哪些属性,哪些功能。
1.2 类的定义格式
在java中,定义类时需要使用class关键字。 具体语法如下:
类名注意采用大驼峰定义。
class ClassName{ field; // 字段(属性) 或者 成员变量 method; // 行为 或者 成员方法 }
class为定义类的关键字,ClassName为类的名字,{}中为类的主体。
类中包含的内容称为类的成员。属性主要是用来描述类的,称之为类的成员属性或者类成员变量。方法主要说明类具有哪些功能,称为类的成员方法。
1.3 类的实例化定义
类是用户自定义的一个新的类型,有了这些自定义的类型之后,就可以使用这些类来定义实例(或者称为对象)。
用类类型创建对象的过程,称为类的实例化,在java中采用new关键字,配合类名来实例化对象。
学习注意点:
- 一般一个文件当中只定义一个类。
- main方法所在的类一般要使用public修饰。
- public修饰的类必须和文件名相同。
1.3.1 对象的定义
1、所谓对象,世间万物皆是对象。若想要将现实世界中的对象抽象成具有特定成员变量及成员方法时就需要引进类。所以成员变量是定义在类里面方法外面的,类名采用大驼峰方式取名。
2、Java是一门纯面向对象的语言(Object Oriented Program,简称OOP),在面向对象的世界里,一切皆为对象。面向对象是解决问题的一种思想,主要依靠对象之间的交互完成一件事情。
1.3.2 类的定义代码示例(一)
//定义一个洗衣机类型
class WashMachine{
//成员属性/字段:是定义在类里面方法外面的
public String brand;
public String type;
public double weight;
public double length;
public double width;
public double height;
public String color;
public void washClothes(){
System.out.println("洗衣服");
}
public void dryhClothes(){
System.out.println("脱水功能");
}
public void setTime(){
System.out.println("定时功能");
}
}
1.3.2 类的定义代码示例(二)
//定义一个狗的类型
class petDog{
public String name;
public String sex;
public String color;
public int age;
public void eat(){
Systemout.println("进食");
}
public void barks(){
System.out.println("吠叫");
}
}
1.3.2 类的定义代码示例(三)
//定义一个学生类
class Student{
public String name;
public String gender;
public int age;
public double score;
public void DoClass(){
System.out.println("按时上课,不要迟到,如果迟到,记得请假。";)
}
public void DoHomework(){
System.out.println("课后作业,及时完成,涉及学分,不可懈怠。";)
}
public void Exam(){
System.out.println("考试目的,了解学情,人人关注,注意烦死。";)
}
}
1.3.3 类的实例化代码示例(一)
//实例化一个类
class Dog{
public String name;
public int age;
public String color;
public void eat(){
System.out.println(name + "进食");
}
public void barks(){
System.out.println(name + "吠叫");
}
}
public class Test{
public static void main(String[] args){
Dog petDog = new Dog();
petDog.name = "初一";
petDog.age = 10;
petDog.color = "黄色";
System.out.println(petDog.name);
System.out.println(petDog.age);
System.out.println(petDog.color);
petDog.eat();
petDog.barks();
System.out.println("=====================");
Dog petDog2 = new Dog();
//new关键字用于创建一个对象的实例.
//使用 . 来访问对象中的属性和方法.
//同一个类可以创建多个实例.
petDog2.name = "初二";
petDog2.age = 12;
petDog2.color = "黑色";
System.out.println(petDog2.name);
System.out.println(petDog2.age);
System.out.println(petDog2.color);
petDog2.eat();
petDog2.barks();
}
}
结果如下:
1.3.3 类的实例化代码示例(二)
//实例化一个日期类并输出值
class Date{
public int year;
public int month;
public int day;
public void setDate(int y , int m ,int d){
year = y;
month = m;
day = d;
}
public void printDate(){
System.out.println("年:" + year + " "+ "月:" + month + " " + "日:" + day);
}
public static void main(String[] args) {
Date date = new Date();
date.setDate(2022 , 5 , 20 );
date.printDate();
}
}
结果如下:
1.3.3 类的实例化代码示例(三)
class Student{
//成员变量定义在方法的外面,类的内部。
public String name;
public int age;
public String gender;
public void eat(){
System.out.println(this.name + "正在吃饭");
//这里的this是当前对象的引用,谁调用eat谁就是this。
}
}
public class Test{
public static void main(String[] args) {
Student student = new Student();
student.name = "张三";
student.age = 10;
student.gender = "男";
System.out.println(student.name);
System.out.println(student.age);
System.out.println(student.gender);
student.eat();
System.out.println("=====================");
Student student2 = new Student();
student2.name = "李素";
student2.age = 11;
student2.gender = "女";
System.out.println(student2.name);
System.out.println(student2.age);
System.out.println(student2.gender);
student2.eat();
}
}
结果如下:
1.3.3 类的实例化代码示例(四)
class Student{
public String name;
public int age;
}
public class Test {
public static void main(String[] args) {
Student student = new Student();
System.out.println(student.name);//null
System.out.println(student.age);//0
//当成员变量没有被赋值时编译器不会报错,只会以自己数据类型的零值进行输出。
//引用类型一般为null,基本数据类型为0,char类型为“\u0000”,boolean类型为false。
}
}
结果如下:
1.4 类和对象学习小贴士
- 类只是一个类似模型的存在,用来对一个实体进行描述,限定了类有哪些成员变量及成员方法。
- 类是一种自定义的类型,可以用来定义属性和行为。
- 一个类可以实例化出多个对象,实例化出的对象才真正占用实际的物理空间,存储类成员变量。
1.5 this的使用
1.5.1 什么是this引用?
this引用指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都是通过该引用去访问。
1.5.2 this的使用代码示例(错误示范)
//当局部变量名与对象名冲突时,会产生局部变量优先的问题
class Data{
public int year;
public int month;
public int day;
public void setDay(int year,int month,int day){
year = year;//栈区上的局部变量自己给自己赋值,并不影响到引用所指向的对象的成员变量名。
month = month;//在开辟内存分配的时候,默认值都是0.
day = day;
}
public void printDay(){
System.out.println("年:"+ this.year + " " + "月:" + this.month + " " + "日:"
+ this.day + " ");
}
}
public class Test {
public static void main(String[] args) {
Data date = new Data();
date.setDay(2023 , 7 ,20);
date.printDay();
Data date2 = new Data();
date.setDay(2021 , 1 ,21);
date.printDay();
}
}
结果如下:
1.5.2 this的使用代码示例(正确示范)
class Data{
public int year;
public int month;
public int day;
public void setDay(int year,int month,int day){
this.year = year;
this.month = month;
this.day = day;
}
public void printDay(){
System.out.println("年:"+ this.year + " " + "月:" + this.month + " " + "日:"
+ this.day + " ");
}
}
public class Test {
public static void main(String[] args) {
Data date = new Data();
date.setDay(2023 , 7 ,20);
date.printDay();
Data date2 = new Data();
date.setDay(2021 , 1 ,21);
date.printDay();
}
}
结果如下:
1.5.2 this的使用代码示例(正确示范)
class Data{
public int year;
public int month;
public int day;
public void setDay(int y,int m,int d){
this.year = y;
this.month = m;
this.day = d;
}
public void printDay(){
System.out.println("年:"+ this.year + " " + "月:" + this.month + " " + "日:"
+ this.day + " ");
}
}
public class Test {
public static void main(String[] args) {
Data date = new Data();
date.setDay(2023 , 7 ,20);
date.printDay();
Data date2 = new Data();
date.setDay(2021 , 1 ,21);
date.printDay();
}
}
结果如下:
1.5.3 this学习小贴士
- this的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型
- this只能在"成员方法"中使用
- 在"成员方法"中,this只能引用当前对象,不能再引用其他对象
- this是“成员方法”第一个隐藏的参数,编译器会自动传递,在成员方法执行时,编译器会负责将调用成员方法 对象的引用传递给该成员方法,this负责来接收
二、构造方法
2.1 构造方法的定义
构造方法即构造器,是一个特殊的成员方法。方法名必须与类名保持一致并且不存在返回值,在创建对象时由编译器自动调用,并且在整个对象的生命周期内只调用一次。
当调用完构造方法之后对象才产生。当一个类当中没有出现任何一个构造方法时,java会自动帮你提供一个不带参数的构造方法。但当类中出现过构造方法(无论是否存在参数列表都可),java便不会再自动帮你提供构造方法
构造方法的作用就是对对象中的成员进行初始化,并不负责给对象开辟空间。
完成一个对象的构造:需要先分配空间,然后在调用合适的构造方法。
2.2 构造方法的使用
2.2.0 就地初始化
class Student{
public String name = "初一";
public int age = 12;
public Student(){
}
public Student(String name, int age){
this.name = name;
this.age = age;
System.out.println("带2个参数的构造方法");
}
public void eat(){
System.out.println(name + "正在吃饭");//
}
}
public class Test {
public static void main(String[] args) {
Student student = new Student();
}
}
结果如下
2.2.1 构造方法的错误示范
class Student{
public String name;
public int age;
public Student(String name, int age){
this.name = name;//zhangsan
this.age = age;//22
System.out.println("带2个参数的构造方法");
}
public void eat(){
System.out.println(name + "正在吃饭");//zhangsan正在吃饭
}
}
public class Test {
public static void main(String[] args) {
Student student = new Student();//实例化的对象会自动调用不带参数的构造方法
Student student2 = new Student("zhangsan",22);//实例化的对象会自动调用带参数的构造方法
}
}
结果如下
2.2.2 构造方法的正确示范
class Student{
public String name;
public int age;
public Student(){
System.out.println("不带参数的构造方法");
}
public Student(String name, int age){
this.name = name;//zhangsan
this.age = age;//22
System.out.println("带2个参数的构造方法");
}
public void eat(){
System.out.println(name + "正在吃饭");//zhangsan正在吃饭
}
}
public class Test {
public static void main(String[] args) {
Student student = new Student();//实例化的对象会自动调用不带参数的构造方法
Student student2 = new Student("zhangsan",22);//实例化的对象会自动调用带参数的构造方法
}
}
结果如下
2.2.3 通过构造方法实例化对象
class Student{
public String name;
public int age;
public Student(){
this("张三" , 10);
System.out.println("不带参数的构造方法");
}
public Student(String name,int age){
this.name = name;
this.age = age;
System.out.println("带2个参数的构造方法");
}
public void eat(){
System.out.println(name + "正在吃饭");
}
}
public class Test {
public static void main(String[] args) {
Student student = new Student();
}
}
结果如下
2.2.4 通过this在构造方法中实例化(一)
class Student{
public String name;
public int age;
public Student(){
this("张三" , 20);
//this()调用在一个构造方法中调用当前类的其他构造函数,但只能在构造方法内部使用,且必须是第一行
System.out.println("不带参数的构造方法");
}
public Student(String name, int age){
this.name = name;
this.age = age;
System.out.println("带2个参数的构造方法");
System.out.println(this.name);
System.out.println(this.age);
}
public void eat(){
System.out.println(name + "正在吃饭");
}
}
public class Test{
public static void main(String[] args){
Student student = new Student();
}
}
结果如下
2.2.4 通过this在构造方法中实例化(二)
class Student{
private String name;
private int age;
public void eat(){
System.out.println(this.name + "正在吃饭");
}
public String getName(){
return this.name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return this.age;
}
public void setName(String name){
this.name = name;
}
}
public class Test {
public static void main(String[] args) {
Student student = new Student();
student.setName("张三");
System.out.println(student.getName());
}
}
结果如下
2.2.5 通过构造方法实例化(四)
class Person{
private String name;
private int age;
private String sex;
public Person() {
this("张三",10,"女");
}
public Person(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
System.out.println(this.sex);
System.out.println(this.age);
System.out.println(this.name);
}
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 String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
public class Test {
public static void main(String[] args) {
Person person = new Person();
}
}
结果如下
2.2.5 通过构造方法实例化(五)
class Person{
private String name;
private int age;
private String sex;
public Person() {
}
public Person(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
System.out.println(this.sex);
System.out.println(this.age);
System.out.println(this.name);
}
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 String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
public class Test {
public static void main(String[] args) {
Person person = new Person();
person.setName("张三");
System.out.println(person.getName());
person.setAge(19);
System.out.println(person.getAge());
person.setSex("女");
System.out.println(person.getSex());
}
}
结果如下
三、封装
3.1 封装的定义
面向对象程序三大特性:封装、继承、多态。而类和对象阶段,主要研究的就是封装特性。
所谓封装:就是将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行 交互
3.2 访问限定符
Java中主要通过类和访问权限来实现封装:类可以将数据以及封装数据的方法结合在一起,而访问权限用来控制方法或者字段能否直接在类外使用。
Java中提供了四种访问限定符:public、default、protected、private
3.3 封装的代码示例
class Student{
private String name;
private int age;
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
}
public class Test {
public static void main(String[] args) {
Student student = new Student();
student.setName("张三");
System.out.println(student.getName());
}
}
结果如下
3.4 自动封装的代码示例
class Student{
private String name;
private int age;
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student() {
}
public Student(String name) {
this.name = name;
}
public Student(int age) {
this.age = age;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
}
public class Test {
public static void main(String[] args) {
Student student = new Student();
student.setName("张三");
student.setAge(10);
System.out.println(student.getName());
Student student2 = new Student("李四",14);
}
}
结果如下
四、包
4.1 包的定义
在面向对象体系中,提出了一个软件包的概念,即:为了更好的管理类,把多个类收集在一起成为一组,称为软件包。
在Java中也引入了包,包是对类、接口等的封装机制的体现,是一种对类或者接口等的很好的组织方式。包还有一个重要的作用:在同一个工程中允许存在相同名称的类,只要处在
不同的包中即可。
4.2 包的使用代码示例(一)
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] array = { 1, 2 ,3 ,4 };
System.out.println(Arrays.toString(array));
java.util.Date date = new java.util.Date();
}
}
结果如下
4.2 包的使用代码示例(二)
import java.util.Arrays;
import java.util.Date;
public class Test {
public static void main(String[] args) {
int[] array = { 1, 2 ,3 ,4 };
System.out.println(Arrays.toString(array));
Date date = new Date();
}
}
4.2 包的使用代码示例(三)
import java.util.*;
public class Test {
public static void main(String[] args) {
int[] array = { 1, 2 ,3 ,4 };
System.out.println(Arrays.toString(array));
Date date = new Date();
}
}
结果如下
4.2 包的使用代码示例(四)
class Student{
private String name;
private int age;
public static String classRoom;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
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 class Test {
public static void main(String[] args) {
Student student = new Student("张三",10);
Student student2 = new Student("李四",10);
System.out.println(student.getAge());
System.out.println(student2.getAge());
System.out.println(student.getName());
System.out.println(student2.getName());
Student.classRoom = "109";
System.out.println(Student.classRoom);
}
}
结果如下
4.2 包的使用代码示例(五)
public class Test {
public static void main(String[] args) {
double ret = Math.sqrt(Math.pow(3,2) + Math.pow(7,5));
//double ret = sqrt(pow(3,2) + pow(7,5));
System.out.println(ret);
}
}
结果如下
4.3 自定义包基本规则
- 在文件的最上方加上一个 package 语句指定该代码在哪个包中。
- 包名需要尽量指定成唯一的名字, 通常会用公司的域名的颠倒形式。
- 包名要和代码路径相匹配。
五、static 成员变量的使用
5.1 static修饰成员变量和方法的注意事项
static修饰的成员变量,称为静态成员变量,静态成员变量最大的特性:不属于某个具体的对象,是所有对象所共享的。
- 静态成员变量不属于某个具体的对象,是类的属性,为所有对象共享。不存储在某个对象的空间中,而是单独存储在方法区中。
- 静态成员变量和静态成员方法既可以通过对象访问,也可以通过类名访问,但一般更推荐使用类名访问。
- 静态成员变量的生命周期伴随着类的一生,它随着类的加载创建,随着类的卸载而销毁)。
5.2 static修饰成员变量和方法代码示例
class Student{
//普通成员变量
private String name;
private int age;
//静态成员变量
public static String classRoom;
public static void show(){
System.out.println("测试静态方法调用");
}
public Student() {
}
public Student(String name) {
this.name = name;
}
public Student(int age) {
this.age = age;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
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 class Test {
public static void main(String[] args) {
Student.classRoom = "109";//静态成员变量直接使用类名.即可访问
System.out.println(Student.classRoom);
Student.show();
Student student = new Student();
student.setAge(17);
System.out.println(student.getAge());
student.setName("王五");
System.out.println(student.getName());
}
}
结果如下
5.3 静态方法如何调用非静态方法
class Student{
//普通成员变量
private String name;
private int age;
//静态成员变量
public static String classRoom;
public Student() {
}
public Student(String name) {
this.name = name;
}
public Student(int age) {
this.age = age;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
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 void show(){
System.out.println("姓名:" + name + " 年龄:" + age);
}
public static void func(){
//静态方法中不可以直接调用非静态方法和普通成员变量,需要先实例化生成引用。这也就意味着不能使用this
Student student = new Student();
student.show();
}
}
public class Test {
public static void main(String[] args) {
Student.classRoom = "109";//静态成员变量直接使用类名.即可访问
System.out.println(Student.classRoom);
Student student = new Student();
student.setAge(17);
System.out.println(student.getAge());
student.setName("王五");
System.out.println(student.getName());
student.show();
}
}
结果如下
六、代码块
6.1 普通代码块
使用 { } 定义的一段代码称为代码块。普通代码块是定义在方法中的代码块。
public class Test {
public static void main(String[] args) {
{
int x = 10;
System.out.println(x);
}
System.out.println(x);//error
}
}
结果如下
6.2 构造代码块
构造块:定义在类中的代码块(不加修饰符)。也叫做实例代码块。
构造代码块一般用于初始化实例成员变量。
class Student{
public String name;
public int age;
public static String classRoom = "109";
{
this.name = "小丽";
this.age = 19;
System.out.println("实例代码块");
}
public Student(){
System.out.println("不带参数的构造方法");
}
public void show(){
System.out.println("姓名:" + name + " 年龄:" + age);
}
}
public class Test {
public static void main(String[] args) {
Student student = new Student();
student.show();
}
}
结果如下
6.3 静态代码块
使用static定义的代码块称为静态代码块。一般用于初始化静态成员变量。
class Student{
public String name;
public int age;
public static String classRoom ;
{
this.name = "小丽";
this.age = 19;
System.out.println("实例代码块");//实例化对象时才会执行
}
public Student(){
System.out.println("不带参数的构造方法");
}
static {
classRoom = "中文一班";
System.out.println("静态代码块");
}
public void show(){
System.out.println("姓名:" + name + " 年龄:" + age);
}
}
public class Test {
public static void main(String[] args) {
Student student = new Student();
student.show();
}
}
结果如下
6.4 学习小贴士
class Student{
public String name;
public int age;
public static String classRoom ;
{
this.name = "小丽";
this.age = 19;
System.out.println("实例代码块");
}
public Student(){
System.out.println("不带参数的构造方法");
}
static {
classRoom = "中文一班";
System.out.println("静态代码块");
}
public void show(){
System.out.println("姓名:" + name + " 年龄:" + age);
}
}
public class Test {
public static void main(String[] args) {
Student student = new Student();
student.show();
System.out.println("============");
Student student2 = new Student();
student.show();
}
}
结果如下
1.静态成员变量是类的属性,因此是在JVM加载类时就开辟空间并初始化的,所以静态代码块不管生成多少个对象,都只会执行一次。并且优于实例代码块及构造代码块先执行。
2.如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次合并执行,实例代码块只有在创建对象时才会执行。
六、对象的打印
6.1 对象的打印代码示例
6.1.1 成员变量未被初始化
//未被初始化的类的成员变量
public class Test {
String s;//类的成员变量
public static void main(String[] args) {
Test test = new Test();//实例化类
System.out.println(test.s);//NULL
}
}
结果如下
6.1.2 局部变量未被初始化
//未被初始化的局部变量
public class Test {
public static void main(String[] args) {
String s;
System.out.println(s);//编译不通过,局部变量必须初始化
}
}
结果如下
6.1.3 静态方法的调用
//静态方法的调用
class Student{
public static void hello(){
System.out.println("hello");
}
}
public class Test {
public static void main(String[] args) {
Student student = null;//null表示此时不指向任何对象,因为静态方法不依赖于对象所以可以编译通过
Student.hello();//hello
}
}
结果如下
6.1.4 非静态方法的调用
//非静态方法的调用
class Student{
public void hello(){
System.out.println("hello");
}
}
public class Test {
public static void main(String[] args) {
Student student = null;//空指针异常
student.hello();//hello
}
}
结果如下
6.1.5 静态对象的调用
class Student{
public String name;
public int age;
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 Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Test {
public static void main(String[] args) {
Student student = new Student("王五",12);
System.out.println(student);
}
}
结果如下