java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java类和对象

Java类和对象全面解析

作者:01_ice

本文介绍了Java面向对象编程的核心概念,文章通过具体代码示例,帮助读者理解Java面向对象编程的基本原理和实践方法,感兴趣的朋友跟随小编一起看看吧

1,面向对象的初步认识

Java是⼀⻔纯⾯向对象的语⾔(ObjectOrientedProgram,简称OOP),在⾯向对象的世界⾥,⼀切皆为对象。⾯向对象是解决问题的⼀种思想,主要依靠对象之间的交互完成⼀件事情。⽤⾯向对象的思想来设计程序,更符合⼈们对事物的认知,对于⼤型程序的设计、扩展以及维护都⾮常友好。

相比于面向过程,面向对象更好维护

个人认为面向对象是把有关对象的所有事物写在类里面

2, 类

类的格式

class ClassName{
    field;//字段(属性)或者成员变量
    method;// ⾏为或者成员⽅法
}

class为类定义的关键字,Classname为类名,{}里是类的主体

类中包含的内容称为类的成员。属性主要是⽤来描述类的,称之为类的成员属性或者类成员变量。⽅法主要说明类具有哪些功能,称为类的成员⽅法

以豌豆射手为例

class PeaShooter {
        //类的成员变量
        public int HP;  //生命值
        public int cost;  //费用
        public int ATK;   //攻击
        public double firingInterval; //射击间隔
        //类的成员方法
        public void attackTheZombies() {  //攻击僵尸
            System.out.println("攻击僵尸");
        }
}

注意

  1. 一个文件当中只定义一个类
  2. public修饰的类必须要和文件名相同
  3. 不要轻易去修改public修饰的类的名称,如果要修改,通过开发⼯具修改

类的实例化

定义了⼀个类,就相当于在计算机中定义了⼀种新的类型,⽤类类型创建对象的过程,称为类的实例化,在java中采⽤new关键字,配合类名来实例化对象。说白了就是创建一个类。

public static void main(String[] args) {
        PeaShooter bob = new PeaShooter();
        PeaShooter dave = new PeaShooter();
}

访问对象中的成员

PeaShooter bob = new PeaShooter();  //new实例化
bob.HP = 300;
bob.cost = 100;
bob.ATK = 20;
bob.firingInterval = 1.4;
bob.AttackTheZombies();

3, 对象

this关键字

为什么要有this引⽤?

如下代码定义了⼀个Date类,Date类中包含3个属性分别是year,month,day。分别使⽤setDay和 printDate对进⾏设置和打印⽇期

public class Date {
        public int year;
        public int month;
        public int day;
        public void setDay(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) {
            //构造三个⽇期类型的对象d1 d2 d3
            Date d1 = new Date();
            Date d2 = new Date();
            Date d3 = new Date();
            //对d1,d2,d3的⽇期设置
            d1.setDay(2026,5,15);
            d2.setDay(2026,5,16);
            d3.setDay(2026,5,17);
            //打印⽇期中的内容
            d1.printDate();
            d2.printDate();
            d3.printDate();
        }
}

如果形参名和成员变量名相同会发生什么?

public void setDay(int year, int month, int day){
        year = year;
        month = month;
        day = day;
}

结果是year = 0,month = 0,day = 0,局部优先,所有year = year都是形参,成员变量就会使用默认值0。

三个对象都在调⽤setDate和printDate函数,但是这两个函数中没有任何有关对象的说明, setDate和printDate函数如何知道打印的是那个对象的数据呢?

this引⽤指向当前对象(成员⽅法运⾏时调⽤该成员⽅法的对象),在成员⽅法中所有成员变量的操作, 都是通过该引⽤去访问。只不过所有的操作对⽤⼾是透明的,即用户不需要来传递,编译器⾃动完成。

public class Date {
    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 printDate(){
        System.out.println(this.year + "/" + this.month + "/" + this.day);
    }
    public static void main(String[] args) {
        Date d = new Date();
        d.setDay(2026,5,19);
        d.printDate();
    }
}

this引用当前对象d

this引用的特性

public void setDay(Date this,int year, int month, int day){
        this.year = year;
        this.month = month;
        this.day = day;
    }
public void printDate(Date this){
        System.out.println(this.year + "/" + this.month + "/" + this.day);
}

形参里面的this一般是隐藏的

对象的构造及初始化

在Java⽅法内部定义⼀个局部变量时,必须要初始化,否则会编译失败,那么类对象怎样初始化呢?

1.用方法传值

public static void main(String[] args) {
    Date d = new Date();
    d.printDate();
    d.setDate(2026,5,20);
    d.printDate();
}

每次对象创建好后调⽤SetDate⽅法设置具体⽇期,比较麻烦,那对象该如何初始化?

局部变量必须要初始化才能使⽤,为什么字段声明之后没有给值依然可以使⽤?

默认初始化

对于成员变量来说,如果没有进⾏初始化,会有⼀个对应的默认值

类型

默认值

byte0
short0
int0
long0
float0.0f
double0.0
char/u0000
booleanfalse
referencenull

缺省参数(默认值)初始化

public class Date {
    public int year = 1900;
    public int month = 1;
    public int day = 1;
    public Date(){
    }
    public Date(int year, int month, int day) {
    }
    public static void main(String[] args) {
        Date d1 = new Date(2026,5,20);
        Date d2 = new Date();
    }
}

没有传参数的就用上面的默认值初始化

构造方法初始化

构造⽅法(也称为构造器)是⼀个特殊的成员⽅法,名字必须与类名相同,在创建对象时,由编译器⾃动调⽤,并且在整个对象的⽣命周期内只调⽤⼀次。

public class Date {
    public int year;
    public int month;
    public int day;
    public Date(int year, int month, int day){
        this.year = year;
        this.month = month;
        this.day = day;
        System.out.println("Date(int,int,int)⽅法被调⽤了 ");
    }
    public void printDate(Date this){
        System.out.println(this.year + "/" + this.month + "/" + this.day);
    }
    public static void main(String[] args) {
        //此处创建了⼀个Date类型的对象,并没有显式调⽤构造⽅法
        Date d = new Date(2026,5,20);   //输出Date(int,int,int)⽅法被调⽤了
        d.printDate();    // 2026/5/20
    }
}

注意事项:

  1. 名字必须和类名相同
  2. 没有返回值类型,设置为void也不⾏
  3. 创建对象时由编译器⾃动调⽤,并且在对象的⽣命周期内只调⽤⼀次(相当于⼈的出⽣,每个⼈只能出⽣⼀次)
  4. 构造⽅法可以重载(用户根据⾃⼰的需求提供不同参数的构造⽅法)

根据参数不同调用不同的构造(如果有的话)

public class Date {
    public int year;
    public int month;
    public int day;
    public Date() {
        this.year = 2026;
        this.month = 1;
        this.day = 1;
        System.out.println("Date()⽅法被调⽤了 ");
    }
    public Date(int year, int month, int day){
        this.year = year;
        this.month = month;
        this.day = day;
        System.out.println("Date(int,int,int)⽅法被调⽤了 ");
    }
    public void printDate(Date this){
        System.out.println(this.year + "/" + this.month + "/" + this.day);
    }
    public static void main(String[] args) {
        //此处创建了⼀个Date类型的对象,并没有显式调⽤构造⽅法
        Date d1 = new Date(2026,5,20);   //输出Date(int,int,int)⽅法被调⽤了
        Date d2 = new Date();
        d1.printDate();    // 2026/5/20
        d2.printDate();    // 2026/1/1
    }
}

如果用户没有显式定义,编译器会⽣成⼀份默认的构造⽅法,⽣成的默认构造⽅法⼀定是⽆参的,

数值全是取的默认值,如果用户显式定义了构造方法就不会调用默认构造

构造⽅法中,可以通过this调⽤其他构造⽅法来简化代码

public Date(){
    this(1900, 1, 1);
}
// 带有三个参数的构造⽅法
public Date(int year, int month, int day) {
    this.year = year;
    this.month = month;
    this.day = day;
}

对象的打印

public class Person {
    String name;
    String gender;
    int age;
    public Person(String name, String gender, int age) {
        this.name = name;
        this.gender = gender;
        this.age = age;
    }
    public static void main(String[] args) {
        Person person = new Person("Jim"," 男 ", 18);
        System.out.println(person);//Person@4eec7777
    }
}

如果我们直接打印对象的引⽤,此时输出的结果为:类路径名@对象的hashcode值

如果想要默认打印对象中的属性该如何处理呢?答案:重写toString⽅法即可

public class Person {
    String name;
    String gender;
    int age;
    public Person(String name, String gender, int age) {
        this.name = name;
        this.gender = gender;
        this.age = age;
}
    @Override
    public String toString() {
        return "[" + name + "," + gender + "," + age + "]";
    }
    public static void main(String[] args) {
        Person person = new Person("Jim","男", 18);
        System.out.println(person);
    }
}

重写会在多态讲到

4,包

4.1 定义

包(Package)是Java中一个组织类的方式,用于防止类名冲突和提高代码的可读性。包允许将类组织在一个层次中,类似于文件系统中的目录。文件夹

包是对类,接口等的封装机制的体现,是一种对类或者接口等的很好的组织方式。

4.2 导入包

Java中提供了很多现成的类供我们使用。例如Date类,可以使用java.util.Date导入java.util这个包中的Date类,指定类的路径

public class Test {
        public static void main(String[] args) {
            java.util.Date date = new java.util.Date();
            //得到⼀个毫秒级别的时间戳
            System.out.println(date.getTime());
        }
}

常用import语句导入包

import java.util.Date;
public class Test {
        public static void main(String[] args) {
            Date date = new Date();
            System.out.println(date.getTime());
        }
}

如果需要使用java.util中的其他类,可以用import java.util.*,*是通配符

import java.util.*;

但是还是显示指定要导入的类名,否则可能会出现冲突的情况

import java.util.*;
import java.sql.*;
public class Test {
    public static void main(String[] args) {
        // util 和 sql 中都存在⼀个 Date 这样的类, 此时就会出现歧义, 编译出错 
        Date date = new Date();
        System.out.println(date.getTime());
    }
}

不同包里如果有相同名字的类就会出错,这种情况就要写出完整的类名

使用import static导入包中静态的方法和字段

import static java.lang.Math.*;
public class Test {
    public static void main(String[] args) {
        double x = 30;
        double y = 40;
        // 静态导⼊的⽅式写起来更⽅便⼀些
        // double result = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
        double result = sqrt(pow(x, 2) + pow(y, 2));
        System.out.println(result);
    }
}

不建议使用这种方法

4.3 自定义包

4.3.1 基本规则

idea中新建包

4.3.2 常见的包

java.lang: 系统常⽤基础类 (String 、 Object), 此包从 JDK1.1 后⾃动导⼊。 java.lang.reflect:java 反射编程包 ;

java.net: 进⾏⽹络编程开发包。

java.sql: 进⾏数据库开发的⽀持包。

java.util: 是 java 提供的⼯具程序包。 ( 集合类等 )

java.io:I/O 编程开发包。

4.4 包的访问权限

如果我们在定⼀个类的时候,如果没有指定成员变量/成员⽅法的访问权限,此时默认的访问权限就是包访问权限

private String cpu;          
private String memory;       
public String screen;       
String brand; 

像brand就是默认权限(包访问权限),在下面访问限定符中会具体讲解

5,封装

5.1 封装的概念

面向对象的三大特性:封装,继承,多态。封装简单来说就是套壳屏蔽细节(封闭包装)

封装:将数据和操作数据的⽅法进⾏有机结合,隐藏对象的属性和实现细节,仅对外公开接⼝来和对象进⾏交互

class Student{
    private String name; //使⽤ private  修饰
    private int age; //使⽤ private  修饰
    public void eat() {
        System.out.println(this.name + " 正在吃饭!");
    }
    public void show() {
        System.out.println("name: "+name+" 年龄:"+age);
    }
}
public class Test {
    public static void main(String[] args) {
        Student stu= new Student();
    }
}

上述代码使⽤private修饰之后,在Test类中⽆法通过person引⽤来进⾏访问数据,这⾥封装就起到 了作⽤! 如果要想访问,此时只能⼿动提供get和set⽅法作为公开的接口来进⾏访问。

idea中快速生成get和set方法

  1. 右键点生成

2.会在光标处自动生成

5.2 封装的好处

1.降低代码的耦合性

封装可以降低对象和对象之间的耦合度,当对象内部发⽣变化时,只需要修改对象内部即可,不会影响到外部程序,因为公开的接口是不会发⽣改变的

2.降低代码的复杂性

封装是隐藏了对象内部的实现细节,只提供了公开的接口给外部,使⽤起来更加简单

3.提高安全性

封装可以隐藏对象的具体实现细节,阻⽌外部程序直接访问对象的内部状态,从⽽保护数据不被意外修改或破坏

5.3 访问限定符详解

Java中主要通过类和访问权限来实现封装:类可以将数据以及封装数据的⽅法结合在⼀起,更符合⼈类对事物的认知,⽽访问权限⽤来控制⽅法或者字段能否直接在类外使⽤。Java中提供了四种访问限定符:

编号范围私有(private)默认(default)保护(protected)公有(public)
1同一包中的同一类
2同一包中的不同类
3不同包中的子类
4不同包中的非子类

6,static关键字

6.1 修饰成员变量

class Student{
    private String name; 
    private int age; 
    public static String classRoom = "1-101";
}
public class Test {
    public static void main(String[] args) {
        Student stu1 = new Student();
        Student stu2 = new Student();
        Student stu3 = new Student();
    }
}

被static修饰的成员,称之为静态成员,也可以称为类成员,其不属于某个具体的对象,是所有对象所共享的。

静态成员变量的特性

  1. 不属于某个具体的对象,是类的属性,所有对象共享,不存储在某个对象的空间中,存储在方法区
  2. 既可以通过对象访问,也可以通过类名访问,但⼀般更推荐使⽤类名访问
  3. ⽣命周期伴随类的⼀⽣(随类的加载⽽创建,随类的卸载⽽销毁)

6.2 修饰成员方法

被static修饰的成员方法称为静态成员方法,是类的方法,不是某个对象所特有的。静态成员⼀般是通过静态方法来访问的

public class Student{
    private static String classRoom = "409";
    public static String getClassRoom(){
        return classRoom;
    }
}
public class TestStudent {
    public static void main(String[] args) {
        System.out.println(Student.getClassRoom());
    }
}

静态方法特性

6.3 static成员变量初始化

静态成员变量的初始化分为两种:就地初始化静态代码块初始化

就地初始化

public static String classRoom = "1-101";

7,代码块

7.1 概念

就是{}里面的代码,一共分为4类

  1. 普通代码块
  2. 构造块
  3. 静态块
  4. 同步代码块

7.2 不同代码块的结构

{ //直接使⽤定义,普通⽅法块
       int x = 10 ;
       System.out.println("x1 = " +x);
}
 //实例代码块
{
    this.name = "cyy";
    this.age = 12;
    this.sex = "man";
}
// 静态代码块
 static {
        classRoom = "409";
        System.out.println("I am static init()!");
}

注意

到此这篇关于Java类和对象全面解析的文章就介绍到这了,更多相关Java类和对象内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文