文章目录
面向对象高级知识(三)
Object类
利用继承与对象多态性的概念可以解决父类对象和子类对象的自动转型操作
如果想统一开发中的操作类型必须要有可以成为所有类的父类: Object类
基本定义
Object类是所有类的父类
任何一类在定义时没有明确继承一个父类,那么它就是Object类的子类
Object类可以接受全部类的对象,自动向上转型
设计代码时,不确定参数类型就用Object类
Object类有无参构造方法,所以会自动在一切类实例化前调用构造
三种覆写方法
取得对象信息
public String toString()
直接对对象进行println,输出的是对象的编码
String类输出时明确覆写了toString()方法
由于toString定义在Object类中
toString()可以将任意对象变成字符串,所有类都有这样的功能
class Book extends Object{
private String title;
private double price;
public Book(String title, double price){
this.title = title;
this.price = price;
}
public String toString(){
return this.title+this.price;
}
}
对象比较
public boolean equals(Object obj)
默认的Object类中的equals()是比较两个类的内存地址
首先比较两个对象的地址是否相同
然后判断对象是否为空
再判断是否是本类实例
最后逐一比较实例化对象的属性
class Book{
private String title;
private double price;
public Book(String title, double price){
this.title = title;
this.price = price;
}
public boolean equals(Object obj){
if(this == obj){ //首先判断是不是地址相同
return true;
}
if(obj == null){
return false;
}
if(obj instanceof Book){ //判断是否是本类实例
if(this.price == obj.price&&this.title==obj.title){
return true;
}
}
return false;
}
}
取得对象哈希码
public int hashCode()
Object类与引用数据类型
Object是所有类的父类,接受所有类的对象,但是考虑到引用类型的特殊性,object可以接受所有引用类型的数据
包括数组, 接口, 类
tips
关于数组对象打印编码值: 首位是"[",然后是表示数组类型的标记符,如I代表int,而后是编码
虽然接口对象不会继承任何对象,但是由于是引用类型的特性,所以也可以被Object接受
匿名内部类
匿名内部类是没有名字的内部类,必须在抽象类或接口基础上才可以定义
匿名内部类产生的动机:
如果子类只使用一次,没有必要给他设置成一个单独的类,使用匿名内部类来简化代码
interface Message{
public void print();
}
public class Test{
public static void main(String args[]){
fun(new Message(){ //直接实例化接口对象
public void print(){ //匿名内部类中覆写方法
System.out.println("Hello World!");
}
}); //传递匿名内部类实例化
}
public static void fun(Message msg){ //接受接口对象
msg.print();
}
}
内部匿名类简化了接口子类的定义,在调用方法时直接实例化了接口对象,并对接口的抽象方法进行了覆写
虽然节省了子类,但是整个代码结构看起来混乱
基本数据类型的包装类
java设计中,一切皆是对象
一切从操作都要用对象的形式进行描述
存在矛盾:基本类型不是对象
使用基本数据类型包装形式描述
JDK中,java给出了一组包装类
对象型包装类(Object直接子类) :Character,Boolean
数值型包装类(Number直接子类) :Byte,Short,Integer、Long、Float、Double
Number类是一个抽象类,定义了6个操作方法:
intValue(), doubleValue(), flaotValue(), byteValue(), shortValue(), longValue()
装箱和拆箱操作
装箱操作:将基础数据类型变为包装类形式
使用该类的构造方法来接受数据
拆箱操作:从包装类取出被包装的数据
使用xxxValue()获取数值
Integer obj = new Integer(10);
int temp = obj.intValue;
JDK1.5以后,有自动装箱拆箱机制
Integer obj = 10; //自动装箱
int temp = obj; //自动拆箱
如果使用自动装箱的话就会变成一个实例化对象,保留在对象池中可以重复使用
但是如果使用构造方法实例化一个包装类对象则会开辟新堆空间,和自动装箱要区分开
不要用==来判断包装类是否相等,这样会比较编码
要使用equals()方法
至此,Object类可以接受全部类型的数据
Object可以进行参数操作统一
所有引用数据类型都利用Object类来接收
基本类型装箱后接收
Object obj = int 10; //自动装箱后向上转型(此时不能进行数学运算)
int temp = (integer) obj; //向下转型后自动拆箱(要指定类型转换)
tips包装类是一定会用到的概念
使用包装类最大的好处就是有null数据,
在与数据库操作上会很方便
大部分java类使用基本数据类型操作会更方便
数据类型转换
对包装类使用.parseXxx(String S)将String类型转换成基本数据类型
关于Character类, String自带charAt()方法
如果要是转换成数值类型要注意String有没有非数字字符,否则出异常
关于boolean类型,如果不是"true",全部是"false"
基本类型转换String
使用"+“与一个空字符串”"链接即可
实际上,String类型是匿名对象,每次字符串链接都是开辟新的堆然后建立新链接
这样做会产生大量的垃圾空间不建议这样做
或者使用String类提供的方法
public static String valueOf(数据类型 变量)
这样避免了垃圾空间产生
Object对象链表
package Object_Link;
public class Link {
/**
* 内部类Node的定义
*/
private class Node {
private Object data;
private Node next;
public Node(Object data) {
this.data = data;
}
/**
* 设置新的节点
* @param newNode
*/
public void addNode(Node newNode) {
if (this.next == null){
this.next = newNode;
}else{
this.next.addNode(newNode); //递归向后查找,一直到链表尾部
}
}
/**
* 查看是否包含节点
* @param data
* @return
*/
public boolean containNode(Object data){
if (data.equals(this.data)){
return false;
}else{
if (this.next!=null){
return this.containNode(data);
}else
return false;
}
}
/**
* 获取索引对应的节点
* @param index
* @return
*/
public Object getNode(int index){
if (Link.this.foot++ == index){
return this.data;
}else{
return this.next.getNode(index);
}
}
/**
* 设置某一节点
* @param index
* @param data
*/
public void setNode(int index, Object data){
if (Link.this.foot++ == index){
this.data = data;
}else{
this.next.setNode(index,data);
}
}
/**
* 节点的删除
* @param previous //其实是调用时的当前节点,对于.next就是前一节点
* @param data
*/
public void removeNode(Node previous,Object data){
if (this.equals(data)){
previous.next = this;
}else{
this.next.removeNode(this,data);
}
}
/**
* 把链表中的元素逐一取出放到数组中
*/
public void toArrayNode(){
Link.this.retArray[Link.this.foot++] = this.data;
if(this.next!=null){
this.next.toArrayNode();
}
}
}
/****************************************以上为内部类***********************************************/
private Node root;
private int foot = 0;
private int count = 0;
private Object[] retArray;
/**
* 添加新节点
* @param data
*/
public void add(Object data){
if(data==null){
return;
}
Node newNode = new Node(data);
if(root == null){
this.root = newNode;
}else{
this.root.addNode(newNode);
}
count++;
}
/**
* @return 链表长度
*/
public int size(){
return this.count;
}
/**
* 判断是否为空
* @return
*/
public boolean isEmpty(){
return this.count==0;
}
/**
* 查询是否包含
* @param data
* @return
*/
public boolean contains(Object data){
if(data == null||this.root==null){
return false;
}
this.foot = 0;
return root.containNode(data);
}
/**
* 获取节点数据
* @param index
* @return
*/
public Object get(int index){
if(index>this.count||index<0){
return null;
}
this.foot=0;
return root.getNode(index);
}
/**
* 索引设置值
* @param index
* @param data
*/
public void set(int index,Object data){
if(index>this.count||index<0){
return;
}
this.foot = 0;
this.root.setNode(index,data);
}
/**
* 删除节点
* @param data
*/
public void remove(Object data){
if(this.contains(data)){
if(data.equals(this.root.data)){
this.root = this.root.next;
}else {
this.root.next.removeNode(this.root,data);
}
this.count--;
}
}
/**
* 获取数组
* @return
*/
public Object[] toArray(){
if(this.root==null){
return null;
}
this.foot=0;
this.retArray = new Object[this.count];
this.root.toArrayNode();
return this.retArray;
}
/**
* 清空
*/
public void clear(){
this.root=null;
this.count=0;
this.foot=0;
}
}