JAVA基本程序设计结构与类

JAVA基本程序设计结构与类

这学期计网、数据库都安排上了,这两门课最好还是在认真学习课本的基础上多做一些实践吧,所以就决定来学学JAVA(正好大创项目中也能用得到,后面也有计网课设,感觉还是很有必要的),这里主要的学习资料是书籍:《JAVA核心技术 卷Ⅰ》

注:作为一名c++选手,这里主要是总结了一些JAVA和C++不同的一些东西或者JAVA非常重要的一些东西,主要就是一个个人笔记吧~

1. 基本程序设计结构

1.1 整型

整形数据主要分为四种

类型 存储需求
byte 1字节
short 2字节
int 4字节
long 8字节

比cpp少了不少,不区分有符号和无符号类型,而且各种类型的大小也与机器无关(java程序致力于保证程序在所有机器上的运行结果相同,尽管这一点在浮点数可能回存在偏差)

长整型long需要添加了lL,后缀,并且可以配合 _ 给数组做分隔,便于阅读;十六进制前缀: 0x,0X , 八进制前缀: 0 ,二进制前缀: 0b, 0B 。可以通过下面代码快速熟悉一下!

public class helloworld {
    
    
    public static void main(String[] args) {
    
    
        long a = 4_000_000_000_000_000L;        // 长整型需要加 l 或 L 后缀,并且可以配合 _ 辅助阅读
        int b = 0xff;       // 十六进制
        int c = 010;        // 八进制
        int d = 0b1111;     // 二进制
        System.out.println("a=" + a);
        System.out.println("b=" + b);
        System.out.println("c=" + c);
        System.out.println("d=" + d);
    }
}

输出结果:

a=4000000000000000
b=255
c=8
d=15

1.2 char类型

和cpp不同,一个char类型是2个字节,由于JAVA采用的UTF-16编码,所有有的字符只需要一个char类型变量就能表示,有的就需要用两个char类型变量!

1.3 常量

JAVA使用关键字 final 指示常量(只能被赋值一次,不能再次修改!)

public class helloworld {
    
    
    public static void main(String[] args) {
    
    
        final double PI;
        PI = 3.14;      // 常量只能被赋值一次
        System.out.println(PI);
    }
}

1.4 数值类型之间的转换

我们有时候就会有这样数值转换的需求,可以参考下图(来自JAVA核心技术),其中实线代表无信息丢失转换,虚线代表有信息丢失转化(值得注意的是int转float会有信息丢失)

0npm6K.png

1.5 数组

JAVA的数组和cpp的数组有所不同,直接来看吧。

首先从一维数组开始,一般定义都是使用 int[] a(当然也可以使用int a[]),可以选择初始化或者不初始化,还有一种匿名数组的形式(感觉类似于对象)

public class helloworld {
    
    
    public static void main(String[] args) {
    
    
        int[] a = new int[100];     // 创建一个数组
        int[] b = {
    
    1, 2, 3, 4, 5};  // 初始化
        int[] c;
        c = new int[] {
    
    6, 7, 8, 9, 10};     // 匿名数组
        System.out.println(a.length);
        System.out.println(b.length);
        System.out.println(c.length);
    }
}

输出结果:

100
5
5

对于多维数组也是类似的,但是JAVA存在不规则数组,直接看样例代码吧,比较好懂

public class helloworld {
    
    
    public static void main(String[] args) {
    
    
        int[][] square = {
    
          // 二维数组
                {
    
    1, 2, 3, 4},
                {
    
    5, 6, 7, 8},
                {
    
    9, 10, 11, 12},
                {
    
    13, 14, 15, 16}
        };
        System.out.println(Arrays.deepToString(square));    // 快读打印二维数组

        int count = 1;
        int[][] irregularSquare = new int[4][];     // 不规则二维数组
        for(int i = 0; i < 4; i++){
    
    
            irregularSquare[i] = new int[i+1];
            for(int j = 0; j < i+1; j++){
    
    
                irregularSquare[i][j] = count;
                count++;
            }
        }
        System.out.println(Arrays.deepToString(irregularSquare));
    }
}

输出结果:

[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]
[[1], [2, 3], [4, 5, 6], [7, 8, 9, 10]]

1.6 其他

其他的一些条件控制基本上和C++是相同的(if, for, for each等等都差不多),switch可能有些区别,每一个case之后的语句无需用 {} 括起来,这里就不赘述了!

2. 类

我们首先简单的定义一个简单的employee类,方面后面一些东西的说明

import java.time.LocalDate;

public class employee {
    
    
    private String name;
    private double salary;
    private LocalDate hireDay;

    public employee(String name, double salary, int year, int month, int day){
    
    
        this.name = name;
        this.salary = salary;
        this.hireDay = LocalDate.of(year, month, day);
    }
    public String getName(){
    
    
        return name;
    }
    public double getSalary(){
    
    
        return salary;
    }
    public LocalDate getHireDay(){
    
    
        return hireDay;
    }
    public void raiseSalary(double percent){
    
    
        this.salary = (percent/100 + 1) * this.salary;
    }
    public void show(){
    
    
        System.out.println("name:"+ this.name+"   salary:"+this.salary);
        System.out.println("hireDay:" + this.hireDay);
    }
}

2.1 显式参数和隐式参数

当我们调用一个对象的方法时,比如如下语句:

employee a = new employee("Jack", 2000, 2018, 10, 25);
a.raiseSalary(20);		// 调用

raiseSalary 方法就有两个方法,第一个参数称为隐式(implicit)参数,是出现在方法名前的employee类型对象(即样例中的a),第二个参数是方法名括号中的数值,这是一个显示(explicit)参数(即样例中的20)。所以隐式参数称为方法中的调用者或接收者。

在每一个方法中,关键词 this 指示隐式参数(当然也可以省略!),比如这里的 raiseSalary 函数:

public void raiseSalary(double percent){
    
    
    this.salary = (percent/100 + 1) * this.salary;
}

2.2 关于封装

封装的优点:

  • 提高了数据的安全性 别人不能够通过 变量名.属性名 的方式来修改某个私有的成员属性
  • 操作简单 封装后,多个调用者在使用的时候,只需调用方法即可,调用者不需要再进行判断
  • 隐藏了实现 实现过程对调用者是不可见的,调用者只需调用方法即可,不知道具体实现过程

如何实现封装?比如说想获得以及设置一个实例字段的值,就需要提供以下三项内容:

  • 一个私有的数据字段(数据的安全性)
  • 一个公共的字段访问器方法
  • 一个公共字段的更改器方法

但是值得注意的是,不要编写可变对象的访问器变量,比如我们将上述定义的 employee 类的 hireDay 修改为Date()对象,然后再使用getHireDay()返回,我们就会发现,我们就能直接在外部不调用器更改器方法的情况下修改 hireDay

..
public class employee {
    
    
    ...
    private Date hireDay;

    public employee(String name, double salary, int year, int month, int day){
    
    
        ...
        this.hireDay = new Date(year, month, day);  // 修改为date对象
    }
    ...
    public LocalDate getHireDay(){
    
    
        return hireDay;     // 直接返回date对象
    }
    ...
}
// 然后调用
public class helloworld {
    
    
    public static void main(String[] args) {
    
    
        employee a = new employee("Jack", 2000, 2018, 10, 25);
        a.show();       // 查看初始Date对象
        Date b = a.getHireDay();        // 获取器Date对象
        long oneYearMilliSeconds = 365L * 24L * 60L * 60L * 1000L;
        b.setTime(b.getTime() -  oneYearMilliSeconds);  // 在外部修改Date对象
        a.show();       // 发现Date对象被修改
    }
}

输出结果:

name:Jack   salary:2000.0
hireDay:Mon Nov 25 00:00:00 CST 3918
name:Jack   salary:2000.0
hireDay:Sun Nov 25 00:00:00 CST 3917

可以看到Date对象就被修改了,这样就破环了封装性!,所有不要直接返回对象的引用,可以返回其副本,如下:(之前返回LocalDate类以及String就没问题,因为这两个类都没有修改器方法,因此也就保证了类的封装!)

    ...
    public Date getHireDay(){
    
    
        return (Date)hireDay.clone();     // 直接返回date对象的副本
    }
    ...

输出结果(保证了类的封装性):

name:Jack   salary:2000.0
hireDay:Mon Nov 25 00:00:00 CST 3918
name:Jack   salary:2000.0
hireDay:Mon Nov 25 00:00:00 CST 3918

2.3 类的权限访问

我们首先来看一个栗子

		...
		employee a = new employee("Jack", 2000, 2018, 10, 25);
        employee b = a;
        if(a.equals(b))
            System.out.println("a equals b");
		...

显然程序会输出"a equals b",但是这是如何判断 a 等于 b 的呢?类不是封装好了吗?而且数据字段都设置为了私有鸭!

原因是私有只是对于“外界”来说的,employee类的方法可以访问任何employee对象的私有字段!

JAVA的四种访问控制修饰符:

  • private:仅对本类可见
  • public:对外部完全可见
  • protected:对本包和所有子类可见
  • 默认:对本包可见

2.4 final字段

我们可以将实例字段定义为final(之前我们用其定义常量),这样的字段必须在构造对象时初始化,之后不能再修改这个字段!

举个栗子:

public class employee {
    
    
    private final String name;
    ...
}

final修饰符对类型为基本类型或者不可变类型的字段尤其有用(比如这个栗子中的String)

但是对于可变的类,使用final修饰符就会造成混乱!! 看下面这个栗子:

public class employee {
    
    
    ...
    private final Date hireDay;
    ...
    public void changeHireDay(){
    
    
        long oneYearMilliSeconds = 365L * 24L * 60L * 60L * 1000L;
        this.hireDay.setTime(this.hireDay.getTime() -  oneYearMilliSeconds);
    }
    ...

我们将Date类数据字段设置为了final,然后我们有编写了一个方法修改Date类数据字段,接下来我们尝试修改!

public class helloworld {
    
    
        public static void main(String[] args) {
    
    
            employee a = new employee("Jack", 2000, 2018, 10, 25);
            a.show();
            a.changeHireDay();
            a.show();
    }
}

输出结果:

name:Jack   salary:2000.0
hireDay:Mon Nov 25 00:00:00 CST 3918
name:Jack   salary:2000.0
hireDay:Sun Nov 25 00:00:00 CST 3917

修改成功了!!!

final关键字只是表示存储在 hireDay 变量中的对象引用不会在指示另一个不同的Date对象,但是这个对象可以更改!!(所以final字段常用于基本类型以及不可变类字段)

2.5 静态字段

如果将一个字段定义为static,每个类只有一个这样的字段,我们看下面这个栗子:

public class employee {
    
    
    ...
    private int id;
    private static int nextId = 1;
    public employee(String name, double salary, int year, int month, int day){
    
    
        ...
        this.id = this.nextId;
        this.nextId++;
    }
    ...
}
public class helloworld {
    
    
        public static void main(String[] args) {
    
    
            employee a = new employee("Jack", 2000, 2018, 10, 25);
            a.show();
            employee b = new employee("Bob", 3000, 2016, 8, 7);
            b.show();
    }
}

输出结果:

name:Jack   salary:2000.0
hireDay:Mon Nov 25 00:00:00 CST 3918
ID:1
name:Bob   salary:3000.0
hireDay:Thu Sep 07 00:00:00 CST 3916
ID:2

我们可以看到每个人的ID是不同的,说明nextId字段的值改变了!

每一个employee对象都有一个自己的 id 字段,但是这个类的所有实例都将共享一个 nextId 字段,就算即使存在employee对象,静态字段 nextId 字段也存在,它属于类,而不属于任何单个的对象!

2.6 静态常量与静态方法

静态常量

相较于静态变量,静态常量就很常用,比如Math类中的PI,可以直接用类名访问变量!举个栗子

public class employee {
    
    
    ...
    public static final String slogan = "好好学习,天天向上";
    ...
}
public class helloworld {
    
    
        public static void main(String[] args) {
    
    
            System.out.println(employee.slogan);
    }
}

输出自然就是(这里这是了final,所有使用public字段没有关系):

好好学习,天天向上

静态方法

静态方法就是不再对象上执行的方法,比如Math类中的pow方法(Math.pow(x, a)计算x^a),调用时不使用任何的Math对象,也就是说其没有隐式参数,但是静态方法不能访问实例字段,只能访问静态字段!

举个栗子:

public class employee {
    
    
    ...
    public static final String slogan = "好好学习,天天向上";

    public static void ourSlogan(){
    
    
        System.out.println("我们的口号是:"+slogan);
    }
    ...
}
public class helloworld {
    
    
        public static void main(String[] args) {
    
    
            employee.ourSlogan();
    }
}

输出结果:

我们的口号是:好好学习,天天向上

2.7 文档注释

类注释:

/**
 * A object represents a employee's info
 */
public class employee {
    
    
    ....
}

方法注释:

    /**
     * The employee class constructor
     * @param name the name of the employee
     * @param salary the salary of the employee
     * @param year the year of the employee joined the company
     * @param month the month of the employee joined the company
     * @param day the day of the employee joined the company
     */
    public employee(String name, double salary, int year, int month, int day){
    
    
    ...
}

当然还有字段注释,通用注释等等~

猜你喜欢

转载自blog.csdn.net/weixin_44338712/article/details/108902821