Java基础知识点杂谈(一)——类与对象

简介: Java基础知识点杂谈(一)——类与对象

前言

我现在虽然学了很多Java知识,包括框架,分布式架构之类的,但是基础部分较为薄弱。


恰逢Java作业要写实验报告,我趁此机会复习下Java基础部分,顺便以此博客为记,当作复习之用。


一、实验内容

1.模拟人开车的问题:请同学们各自讨论,独立完成。


w2.png

模拟人开车:

1.根据模拟开车这问题,给出所需的类;

2.模拟中人如何作用于车对象?

3.模拟中车加速等细节代码,用类似打印“车加速中…”的简易代码。


实验报告至少涉及以下知识点的测试案例


1.为什么说构造方法是一种特殊的方法?特殊在哪里?构造方法什么时候执行?被谁调用?

2.创建类的实例时,是构造方法先运行还是成员变量的初始化先处理? 3.重载? 4.this的应用?

5.private所修饰的变量和方法使用有啥限制?另一对象如何使用另一对象的private变量? 6.如何统计一个类创建的对象数?

7.如果一个类里定义的构造方法都是私有的,如何创建该类的对象?


二、类图/类关系图


w1.png

思路解析:

无论是奔驰车和奥迪车都有个父类Car,Car中抽象出两个子类的公共部分,包括加速、减速、按喇叭等方法。同时Car和驾驶员Person类存在关系:Car关联了Person,用于模拟人坐进车的情景;Person又依赖于Car,这体现在方法参数的传递上,用来模拟人与车的关系。当Person使用某种方法时,其方法内部会调用Car的对应方法,虽然这在程序设计上有些问题,但是这很好地模拟了人操作车这么一个情景。

另外,对于类的创建上,AudiCar,BenzCar类都重写了父类的构造方法,在原先的基础上会输出相应的语句以示区别。同时AudiCar采用了单例模式——构造方法私有,但是内部维护了一个静态instance属性,当要获取该类示例时,只需调用getInstance方法即可。

至于统计车的数量,这里采用在父类Car中维护一个静态属性的方法记录数据,每当创建一个Car实例时该属性都会自增1,变相达到目的,但是需要注意的是,此属性只是记录创建了多少个Car对象,而不是记录当前内存中存在多少个Car对象,因为有些无用的Car对象会被GC回收,这是我们无法操控的。


三、程序与测试

1.代码部分

Car类

package com.dreamchaser.work2;
public class Car {
    private int speed=0;
    private String status;
    //创建的对象数
    public static int number=0;
    //全部汽车摁喇叭的次数
    public static int horn=0;
    //车内驾驶员
    private Person person=null;
    public Car() {
        System.out.println("创建了辆小车!");
        number++;
    }
    public void setPerson(Person person) {
        this.person = person;
    }
    public void accelerate(int s){
        status="车正在加速中...";
        speed+=s;
        System.out.println(status+"速度飙到"+speed+"迈了!");
    }
    public void slow(int s){
        status="车正在减速中...";
        speed-=s;
        if (speed<0){
            status="小车正在倒车...";
        }else if (speed==0){
            status="小车停了!";
        }else{
            System.out.println("小车正在缓慢前进    ");
        }
        System.out.println(status+"速度减到"+speed+"迈了!");
    }
    public void honkHorn(){
        System.out.println("车喇叭滴了一声...");
        horn++;
    }
    public int getSpeed() {
        return speed;
    }
    public String getStatus() {
        return status;
    }
    public static int getNumber() {
        return number;
    }
    public static int getHorn() {
        return horn;
    }
}

AudiCar类

package com.dreamchaser.work2;
public class AudiCar extends Car{
    String Logos="奥迪";
    //全球首发,仅限一辆(单例模式)
    private static AudiCar instance=new AudiCar();
    //私有构造函数
    private AudiCar(){
        System.out.println("再加个奥迪车标!");
    }
    public static AudiCar getInstance(){
        return instance;
    }
    public void showLogos(){
        System.out.println("奥迪车标!!!");
    }
}


BenzCar类

package com.dreamchaser.work2;
public class BenzCar extends Car {
    public BenzCar() {
        System.out.println("创建小车再加个奔驰车标!");
    }
    //构造函数默认先会调用super(如果没有super的话)
    public BenzCar(int speed, String status) {
        System.out.println("再加个奔驰车标!");
    }
    @Override
    public void honkHorn() {
        System.out.println("奔驰的喇叭就是不一样");
    }
}

Person类

package com.dreamchaser.work2;
public class Person {
    private String name;
    public Person(String name) {
        this.name = name;
    }
    public void accelerate(Car car,int s){
        car.accelerate(s);
    }
    public void slow(Car car,int s){
        car.slow(s);
    }
    public void honkHorn(Car car){
        car.honkHorn();
    }
}


Main类

package com.dreamchaser.work2;
public class Main {
    public static void main(String[] args) {
        //创建小车
        Car car=new Car();
        BenzCar benzCar=new BenzCar();
        AudiCar audiCar=AudiCar.getInstance();
        Person person=new Person("张三");
        Person benzPerson=new Person("李四");
        Person audiPerson=new Person("王五");
        //人上小车
        car.setPerson(person);
        benzCar.setPerson(benzPerson);
        audiCar.setPerson(audiPerson);
        //人对车进行操作
        person.accelerate(car,12);
        person.honkHorn(car);
        person.slow(car,12);
        benzPerson.accelerate(benzCar,70);
        benzPerson.honkHorn(benzCar);
        benzPerson.slow(benzCar,66);
        audiPerson.accelerate(audiCar,70);
        audiPerson.honkHorn(audiCar);
        audiPerson.slow(audiCar,66);
        System.out.println("工厂造了"+Car.number+"辆车!");
        System.out.println("奔驰车:"+"number:"+BenzCar.getNumber()+";born:"+BenzCar.getHorn());
        System.out.println("奥迪车:"+"number:"+AudiCar.getNumber()+";born:"+AudiCar.getHorn());
        System.out.println("普通小车:"+"number:"+Car.getNumber()+";born:"+Car.getHorn());
    }
}


2.测试结果


q5.png

四、本章相关知识点程序与测试

1.为什么说构造方法是一种特殊的方法?特殊在哪里?构造方法什么时候执行?被谁调用?

Java在类里提供了一个特殊的成员函数,叫做构造函数。

一个构造函数是对象被创建时初始对象的成员函数。它具有和它所在的类完全一样的名字。一旦定义好一个构造函数,创建对象时就会自动调用它。构造函数没有返回类型,即使是void类型也没有。这是因为一个类的构造函数的返回值的类型就是这个类本身。构造函数的任务是初始化一个对象的内部状态,所以用new操作符创建一个实例后,立刻就会得到一个清楚、可用的对象。


构造函数一般是在创建对象时执行调用。

由创建对象的程序来调用。


2.创建类的实例时,是构造方法先运行还是成员变量的初始化先处理?

成员变量初始化先处理,由上面代码可以看出最终对象的成员变量是构造函数中处理的值,即构造函数中操作成员变量把原先的赋值给覆盖了。

说明成员变量的初始化先处理,构造方法后行。


实际上,由jvm的运行机制也可以看出——Java把.java文件编译成.class后采取双亲委派机制把类加载进jvm内存中,首先是加载每个类的静态属性和方法,然后当程序要用到或者创建对象时会先初始化成员变量,再执行构造函数方法。


3.重载?

重载,从简单说,就是函数或者方法有相同的名称,但是参数列表不相同的情形,这样的同名不同参数的函数或者方法之间,互相称之为重载函数或者方法。在java中同一个类中的2个或2个以上的方法可以有同一个名字,只要它们的参数声明不同即可。这种情况下,该方法就被称为重载,这个过程称为方法重载 ,通俗的讲就是省了给method命名了.差不多的都用一个.

方法重载的主要好处就是,不用为了对不同的参数类型或参数个数,而写多个函数。多个函数用同一个名字,但参数表,即参数的个数或(和)数据类型可以不同,调用的时候,虽然方法名字相同,但根据参数表可以自动调用对应的函数。


4.this的应用?

this实际上是一个指针(尽管Java中没有指针的概念),用于在对象内部调用时指明自身,最常用的场景就是初始化对象内部状态(构造函数)和复杂方法中参数和自身的区分。


5.private所修饰的变量和方法使用有啥限制?另一对象如何使用另一对象的private变量?


q4.png

private修饰的成员变量或方法为私有变量或方法,即其他程序无法直接获取成员变量。


q3.png

此时我们可以通过编写get、set方法来间接让外部获取。


6.如何统计一个类创建的对象数?

首先,明确一个问题,此种情景并不常见,因为Java有内存回收机制,一些不常用的对象会被自动回收,所以统计对象数存在不可靠性。


我们可以通过在类中设置一个静态变量(默认为0),每当调用一次构造函数时,该变量+1(所有对象共享该静态变量,此共享的意思是对象可以操作此静态变量,但是无法通过对象来获取此变量)


q2.png

7.如果一个类里定义的构造方法都是私有的,如何创建该类的对象?


q1.png

如上述代码创建奥迪汽车,构造方法私有,但是该类本身维护一个静态变量instance,当要获取对象时直接调用getInstance()方法获取即可。这样的好处就是程序不用频繁创建对象,节省内存,提高运行效率,同时保证每次获取的对象都是同一个。(单例模式)但其适用场景有限制,对于一些不适用单例的场景,此方法并不适用。


当然也可以采用享元模式,调用clone()方法来返回对象的公共部分,这样返回的对象便是一个独立的对象,但也会耗费少量内存和时间(享元模式)


总结

类和对象是Java语言的核心,理解其运行机制,尤其是理解其内在原理对以后探究深层次问题将会大有裨益。

相关文章
|
10天前
|
存储 缓存 安全
java 中操作字符串都有哪些类,它们之间有什么区别
Java中操作字符串的类主要有String、StringBuilder和StringBuffer。String是不可变的,每次操作都会生成新对象;StringBuilder和StringBuffer都是可变的,但StringBuilder是非线程安全的,而StringBuffer是线程安全的,因此性能略低。
|
1月前
|
安全 Java 编译器
Java对象一定分配在堆上吗?
本文探讨了Java对象的内存分配问题,重点介绍了JVM的逃逸分析技术及其优化策略。逃逸分析能判断对象是否会在作用域外被访问,从而决定对象是否需要分配到堆上。文章详细讲解了栈上分配、标量替换和同步消除三种优化策略,并通过示例代码说明了这些技术的应用场景。
Java对象一定分配在堆上吗?
|
27天前
|
存储 安全 Java
java.util的Collections类
Collections 类位于 java.util 包下,提供了许多有用的对象和方法,来简化java中集合的创建、处理和多线程管理。掌握此类将非常有助于提升开发效率和维护代码的简洁性,同时对于程序的稳定性和安全性有大有帮助。
47 17
|
19天前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
23天前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
76 4
|
24天前
|
Java 编译器 开发者
Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面
本文探讨了Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面,帮助开发者提高代码质量和程序的健壮性。
45 2
|
28天前
|
存储 安全 Java
如何保证 Java 类文件的安全性?
Java类文件的安全性可以通过多种方式保障,如使用数字签名验证类文件的完整性和来源,利用安全管理器和安全策略限制类文件的权限,以及通过加密技术保护类文件在传输过程中的安全。
|
1月前
|
Java 数据格式 索引
使用 Java 字节码工具检查类文件完整性的原理是什么
Java字节码工具通过解析和分析类文件的字节码,检查其结构和内容是否符合Java虚拟机规范,确保类文件的完整性和合法性,防止恶意代码或损坏的类文件影响程序运行。
|
1月前
|
Java API Maven
如何使用 Java 字节码工具检查类文件的完整性
本文介绍如何利用Java字节码工具来检测类文件的完整性和有效性,确保类文件未被篡改或损坏,适用于开发和维护阶段的代码质量控制。
|
1月前
|
存储 Java 编译器
java wrapper是什么类
【10月更文挑战第16天】
35 3