从零开始的Java开发1-4-1 Java继承:Object类final关键字注解

Posted karshey

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从零开始的Java开发1-4-1 Java继承:Object类final关键字注解相关的知识,希望对你有一定的参考价值。

Object类

API

具体的API文档可以在官网看到:Java™ Platform, Standard Edition 8
API Specification

我们在这里只提几个常用的API,还有别的类中对它的重写。

equals
没有被重写的方法
调用这个方法的引用和它传进去的参数的引用是否指向同一个内存地址。

在String类中重写的方法

判断值是否相同。

举个例子:
Animal类的构造函数如下:

public Animal() 
		//System.out.println("父类-无参构造");
	
	
public Animal(String name,int month) 
	this.name=name;
	this.month=month;
	//System.out.println("父类-双参构造");

测试类:

public static void main(String[] args) 
		// TODO Auto-generated method stub
		
		Animal one=new Animal("A",2);
		Animal two=new Animal("A",2);
		
		//equals:继承Object的equals方法,比较两个引用是否指向同一个对象
		boolean flag1=one.equals(two);
		System.out.println(flag1);
		//输出false		
		System.out.println(one==two);
		//输出false
		
		//String里的equals:比较两个字符串的值是否相等
		String str1=new String("a");
		String str2=new String("a");
		System.out.println(str1.equals(str2));
		//输出true
		System.out.println(str1==str2);
		//输出false	
		
	

输出:

false
false
true
false

重写equals

如果我们只想让equals的功能为:判断两个对象的每个对应参数是否相同。
则我们需要对equals进行重写。

重写equals的代码:

	// 方法重写
	public boolean equals(Object obj) 
		if (obj == null)
			return false;
		Animal temp = (Animal) obj;
		if (this.getName().equals(temp.getName()) && this.getMonth() == temp.getMonth())
			return true;
		else
			return false;
	

	// 针对上面的equals方法进行重载
	public boolean equals(Animal obj) 
		if (obj == null)
			return false;
		if (this.getName().equals(obj.getName()) && this.getMonth() == obj.getMonth())
			return true;
		else
			return false;
	

测试类:

/*equals测试:
* 1.继承Object中的equals方法,比较的是两个引用是否指向同一方向
* 2.子类可以通过重写equals方法的形式改变比较的内容
*/
		
boolean flag1=one.equals(two);
System.out.println(flag1);	
System.out.println(one==two);	

输出:

true
false

重写toString

Object类中的toString:描述一个对象的内存位置。


String类中的toString:输出字符串。
测试ObjecttoString的作用:

Animal one=new Animal("A",2);
				
/**toString测试:
 * 1、输出对象名时,默认会调用类中的toString
 * 2、输出包.类.@内存地址
 */
System.out.println(one.toString());
System.out.println(one);

输出:

com.animal.Animal@1c4af82c
com.animal.Animal@1c4af82c

测试String类中的toString 的作用:

String str1=new String("a");	
System.out.println(str1);
System.out.println(str1.toString());

输出:

a
a

从上面例子可以看出,String类重写了toString方法。实际上,toString方法经常被重写。接下来我们就来重写一下Animal类中的toString方法。

Animal类中重写toString

public String toString() 
		return "昵称"+this.getName()+"     月份"+this.getMonth();
	

测试类:

Animal one=new Animal("A",2);
Animal two=new Animal("A",2);

/*toString测试:
 * 1、输出对象名时,默认会调用类中的toString
 * 2、继承Object中的toString方法时,输出对象的字符串表示形式:类型信息+@+地址信息
 * 3、子类可以通过重写toString方法的形式,改变输出的内容以及表现形式
 */
System.out.println(one.toString());
System.out.println(one);

输出:

昵称A     月份2
昵称A     月份2

到这里,我们就重写了toString 方法。

final关键字

修饰基本数据类型

继承可以提高代码的复用性和灵活性。但有时我们并不希望类中的方法被重写和修改,这时我们就需要用到final关键字。

final关键字修饰类:加在类名前,这样此类就不能有子类。

如:
我们在Animal类前加finalpublic final class Animal
则之前继承了Animal类的Cat,Dog类都会报错:


注意:final和public的位置可以互换,只要都写在class前就行。

一些系统类,如String类,它就是用final修饰的。

final关键字修饰方法:加在返回值前,则此方法不能被重写

如,已知Animal类有一个eat方法,我们现在让它:public final void eat()

则Dog类中的eat类会报错:

final关键字修饰变量:
类中有两种变量:

  1. 成员属性
  2. 方法中的局部变量

在局部变量前加final表示:这个局部变量不允许再被修改。

在成员属性变量前加final:

若在定义此加了final修饰符的成员属性时没有对它进行赋值,则只有在

  1. 构造方法
  2. 构造代码块

中可以对final属性的成员进行赋值。

如果final修饰的成员属性并没有被赋值,则在构造函数处会报错:

总结:

final class:该类没有子类;public final class 和 final public class都可以
final 方法:该方法不允许被子类重写,但可以正常被子类继承使用
final 方法内局部变量:只要在具体被使用之前进行赋值即可,一旦赋值不允许被修改
final 类中成员属性:赋值过程:

  1. 定义的时候直接初始化
  2. 在构造方法/构造代码块中 初始化

修饰引用数据类型

上面写的都是final对基本数据类型的修饰,接下来我们举例说明final修饰符对引用数据类型的修饰。

1、final修饰的引用数据类型是否可以修改引用:不行

2、final修饰的引用数据类型是否可以修改里面的属性:可以

对于一个变量,我们不希望它被修改,同时希望它是全局变量,则可以同时用staticfinal进行修饰。

总结

1、修饰类表示不允许被继承
2、修饰方法表示不允许被子类重写

  • final修饰的方法可以被继承
  • 不能修饰构造方法

3、修饰变量表示不允许修改

  • 方法内部的局部变量——在使用之前被初始化赋值即可
  • 类中成员变量——只能在定义时、构造方法、构造代码块中进行

final修饰后:

  • 基本数据类型的变量——初始赋值后不能更改
  • 引用类型的变量——初始化之后不能再指向另一个对象(引用不能改),但对象的内容是可变的

4、可配合static使用
5、使用final修饰可以提高性能,但会降低可扩展性

注解简介

Window系统下Alt+/ 可以看到在子类中可以重写的所有方法。

我们在其中选择eat,则会自动生成一段代码:

@Override
public void eat() 
	// TODO Auto-generated method stub
	super.eat();

它是满足重写方法的要求的代码。

@Override :标注下面的方法是否是合法的重写方法。是一个注解

注解是什么:

  • JDK1.5版本引入的一个特性。
  • 可以声明在包、类、属性、方法、局部变量、方法参数等的前面,用来对这些元素进行说明、注释。
  • 可以理解成为一种“标记”。

举个例子:我们在一段代码前写上@Override,相当于标记:这段代码针对父类的合法的重写代码。此时编译器就会去检测父类中是否有对应的方法,是否允许在此类重写。

若父类没有对应的方法,则报错,如:

按照运行机制分,注解可分为:

  • 源码注解:注解只在源码阶段保留,在编译阶段会被丢弃(如上例的@Override)
  • 编译时注解:注解在编译时期保留,在虚拟级加载class文件时会被丢弃
  • 运行时注解:在运行阶段还起作用,甚至会影响运行逻辑的注解。

按照来源分,注解可分为:

  • 来自JDK的注解
  • 来自第三方的注解
  • 我们自己定义的注解

元注解:对注解的注解。

再举例子:
我们知道,方法重写的要求之一是:当方法返回值是void或基本数据类型时,必须相同;当返回值是引用类型时,可以是父类或其子类
我们可以用@Override来验证它。

我们在Animal类中添加:

public Animal create() 
		return new Animal();
	

用快捷键在Dog类中生成create的重写方法:

@Override
public Animal create() 
	// TODO Auto-generated method stub
	return super.create();

把它改成返回Dog类的方法:

@Override
public Dog create() 
	// TODO Auto-generated method stub
	return new Dog();


这里并没有报错,说明这个重写方法是合法的。

若在Animal类中的create方法前加final,则Dog类的create方法就报错了。

再举个例子:当父类中有一个静态方法,则子类是不能重写它的

父类:

public static Animal create() 
		return new Animal();
	

子类:

但是,若父类有一个静态方法,子类有一个参数名、方法列表和它一样的静态方法,编译器会认为子类把父类的静态方法隐藏,而并非重写,换言之,编译器认为子类的静态方法是只属于子类的,与父类的没有任何关系,因此不会报错。

如:没有报错。

总结

Object类

  • Object类是所有类的父类
  • Java中的每个类都可以使用Object中定义的方法,如equals()toString()

final

  • 修饰类表示不允许被继承
  • 修饰方法表示不允许被子类重写
  • 修饰变量表示不允许被修改
  • final修饰的方法可以被继承
  • 修饰引用类型的变量时:初始化后不能再指向另一个对象,但指向的对象的内容是可变的
  • 可配合static使用

注解

以上是关于从零开始的Java开发1-4-1 Java继承:Object类final关键字注解的主要内容,如果未能解决你的问题,请参考以下文章

Java开发从零开始!java游戏服务器开发教程

从零开始的Java开发 笔记目录(持续更新)

从零开始的Java开发1-4-4 多态与内部类:接口:定义并测试抽象方法常量默认方法静态方法重名默认方法和重名静态方法的解决方案继承;成员静态方法匿名 内部类

从零开始的Java开发1-4-3 多态:概念实现向上转型向下转型instanceof类型转换抽象类抽象方法

从零开始的Java开发1-6-2 泛型:概述泛型作为方法参数自定义泛型自定义泛型方法

java从零开始之Java StreamFileIO