java学习随笔(1)

文章介绍了Java中var关键字用于局部变量声明,以及如何处理null值,强调了对null参数的检查。讨论了隐式参数、显示参数的概念,推荐使用this关键字增强代码可读性。此外,文章提到了返回可变对象引用的风险和如何保持封装性,强调了静态字段和方法的特性。最后,作者分享了关于方法参数、构造器重载、初始化块以及类设计的最佳实践,包括保证数据私有、优先使用不可变类等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

用 var 声明局部变量

如果可以从变量的初始值推导出它们的类型,name可以用 var 关键字声明局部变量,而无需指定类型.

 var employee = new Employee(name,salary,year,month,day);

注意,不要对数值类型使用var,这样就不会担心 0(int),0L(long),0.0D(double),0.0F(float)的区别了。

var只能用于方法中的局部变量,参数和字段的类型都必须声明。

使用null引用

对象变量要么包含一个对象的引用,要么包含一个null(表示没有引用对象)。如果对null值调用方法,会产生NullPointException异常。问题在于,如果没有捕获这个异常,那么程序就会终止(很严重的问题)。因此,对于某些可能是null值得参数,必须要对其进行检验。方法如下:

把null值转换呈适当的非null值

调用一个Objects类的方法:

public Employee(String name, double salary)
{
	this.name = Objects.requireNonNullElse(name,"unknown");//如果它是非 null ,则返回第一个参数,否则返回第二个参数。
	...
}
直接拒绝null参数

直接抛出一个NullPointException异常:

public Employee(String name, double salary)
{
	this.name = Objects.requireNonNull(name,"cant be null");//检查指定的对象引用是否为null ,如果是,则抛出自定义的NullPointerException 。
	...
}

隐式参数与显示参数

先看如下代码:

 public void RaiseSalary(double byPercent){
        double raise = salary * (byPercent / 100);
        salary += raise;
    }

此方法有两个参数,第一个是Employee类型的对象,称为隐式参数,它没有出现在方法声明中,第二个是位于方法名后方括号中的参数byPercent,称为显示参数,它显示地列在方法声明中。

在每一个方法中,关键字this指示隐式参数
可以如下改写上述RaiseSalary方法:

 public void RaiseSalary(double byPercent){
        double raise = this.salary * (byPercent / 100);
        this.salary += raise;

这样写的好处是可以将实例字段与局部变量明显地区分开,建议经常使用。

返回可变对象引用的访问器方法

访问器方法:改变对象状态(set方法)
更改器方法:不改变对象状态(get方法)

不要编写返回可变对象引用的访问器方法,它会破坏封装性。考虑如下代码:

class Employee
{
	private Date hireDay;
	
	public Date getHireDay(){
	return hireDay;
	}
}

Date类有一个更改器方法setTime(),使用这个方法会改变Date对象的状态,这一点破坏了其封装性。考虑如下有问题的代码:

Employee harry = ...;
Date d = harry.getHireDay();
double tenYearsInMilliseconds = 10 *365.25 *24 *60 *60 *1000;
d.setTime(d.getTime() - (long)tenYearsInMilliseconds);

由于d和harry.hireDay引用同一个对象,对d调用更改器方法自然就会改变Employee对象的状态,从而破坏其封装性。

如果要反回一个可变对象的引用,解决方法是:首先对它进行克隆,然后再返回:

class Employee
{
	private Date hireDay;
	
	public Date getHireDay(){
	return hireDay;
	}
}

====================================================================
以下内容其实已经编辑过一次,但是忘记保存了 😦 ,只能重新写了。

静态字段与静态方法

可以认为静态字段和方法属于类而不是单个对象。

考虑以下程序,每一个员工需要分配一个唯一标识:

 private int id = Employee.advancedId();
    private static int nextId = 1;

 public static int advancedId(){
        int r = nextId;
        nextId++;
        return r;
    }

advancedId方法不属于任何对象,只属于Employee类

需要注意的是,对象也可以调用静态方法,但是不建议这样做,可能会带来问题。

方法参数

按引用调用:方法接收的是调用者提供的值。
按值调用:方法接收得是调用者提供的变量位置。

方法可以修改按引用传递的变量的值,而不能修改按值传递的变量的值。

Java总是采用按值调用,也就是说,方法会得到所有参数值的一个副本。

下面的程序要实现将一个参数翻三倍:

 public static int tripleValue(int x){   //将传进来的值翻三倍,实际上无法实现
        x = 3*x;
        return x;
    }
 		int percent = 10;
        Employee.tripleValue(percent);

事实上上述程序并不能实现将percent翻三倍。通过分析执行过程可以明白原因:
① x初始化为percent的一个副本(10)
② x乘以3后等于30,但是percent的值依然为10
③方法结束,参数x不再使用。

因此,一个方法不可能修改基本数据类型的参数。但是对象参数可以:

 public static void tripleValue2(Employee x){
        x.RaiseSalary(200);
    }
    
	Employee.tripleValue2(employee2);

分析过程:
① x初始化为employee2的一个副本,该副本是一个对象引用。
② raiseSalary方法应用于这个对象引用,x和employee2同时引用的那个Employee对象的Salary翻了三倍。
③ 方法结束后,x不再使用,当然,employee2的继续引用那个Salary增至三倍的员工对象。

有些人声称Java对对象采用的是按引用调用,这是错误的,这里举一个反例:
下面编写一个程序用于交换两个Employee对象:

 public static void swap(Employee x,Employee y){ //实现x和y的互换,实际上无法实现
        Employee temp = x;
        y = x;
        x = temp;
    }
 		Employee.swap(employee1,employee2);

实际运行发现并不能交换两个对象,原因是swap方法的参数x和y初始化为两个对象的副本,并交换这两个副本,却并没有交换employee1和employee2。

重载

如果多个方法有相同的方法名但是有不同的参数,就是重载
Java允许重载任何方法,要完整的描述一个方法需要指定方法名以及参数类型,这叫做方法的签名。

构造器

无参数的构造器

由无参数的构造器创建对象时,对象的状态会设为默认值

如果你写的类没有构造器,就会自动提供一个无参数构造器,且其中的所有字段都设为默认值。

注意,仅当类中没有任何构造器时,才会自动生成一个无参构造器,也就是说,如果自己写了一个构造器,要想再构造出无参数的对象,就必须自己创建一个无参数构造器。

调用另一个构造器

如果构造器的第一个语句形如this(…),这个构造器将引用同一个类的另一个构造器。
例子:

public Employee(double s){
	this("Employee:"+ nextId,s);
	nextId++;
}

初始化块

三种初始化方式:
在构造器中设置值;
在声明中赋值;
使用初始化块。

格式:
{

}

文档注释

类注释

位置在import之后,class之前

方法注释

字段注释

通用注释

类注释

包注释

注释提取

类设计技巧

一定要保证数据私有

当数据保持私有时,表示形式的变化不会对类的使用者产生影响,而且也更容易检测bug

一定要初始化数据

应当显式的初始化所有变量,而不是依赖于系统的默认值。

不要再类中使用过多的基本类型

应当使用其他的类,而不是使用多个相关的基本类型。例如可以用一个名为Address的类替换Costomer类中的以下实例字段:

private String streets;
private String city;
private String state;

这样一来,可以很容易的处理地址的变化

不是所有的字段都需要单独的访问器和更改器

有一些字段一旦设置了便不会再更改,比如员工的雇佣日期。

分解有过多职责的类

如果明显的可以将一个复杂的类分解成两个概念上更为简单的类,就应当进行分解。

类名和方法名要能体现它们的职责

变量名应该有一个能够反映其含义的名字,类也是如此。
惯例是:类名应当是一个名词,或是前面有形容词修饰的名词,或是有动名词修饰的名词。

优先使用不可变类

不可变类——没有方法能修改对象的状态。
很多时候不应当改变对象的状态,而是生成一个新的对象。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值