目录
API
1.0 API概念
2.0 Object类的常用API
2.1 Object 中的 tostring() 方法 表示返回对象的字符串表达形式
2.2 Object 中的 equals(Object o) 方法 ,判断两个对象的是否相等
2.2.1深入了解如何重写Object 中的 equals(Object o) 方法
2.2.2 对重写Object 中的 equals(Object o) 方法再深入思考一下
2.3 Object 中的 clone() 方法,当某个对象调用这个方法时,这个方法会返回一模一样的新对象
2.3.1分析代码注意的地方
2.4对Object小结
3.0 Objects类的常用API
3.1 Objects类中的 equals(Object a, Object b) 方法
3.2 Objects类中的 isNull(Object obj) 方法
3.3 Objects类中的 nonNull(Object obj) 方法
4.0 包装类概念
4.1 Integer类中 valueOf(int i) 方法(其他基本数据对应的对象都大致相同,以Integer举例)
4.1.1自动装箱:
4.1.2自动拆箱:
4.1.3具体来应用:
4.2 Integer类中 toString() 方法(其他基本数据对应的对象都大致相同,以Integer举例)
4.3 Integer类中 parseInt(String s) 方法(其他基本数据对应的对象都大致相同,以Integer举例)
4.3.1对 parseXxx() 方法与 valueOf() 方法小结
API中文名为:应用程序编程接口,就是JAVA已经帮我们写好了一些常用的程序,如方法、类等,我们直接拿来用就可以解决一些问题,这样就可以提高开发效率。
Object是所有类的祖宗类,因此,JAVA中所有类的对象都可以直接使用Object类中提供的一些方法。
代码如下:
public class API { public static void main(String[] args) { ToString t = new ToString(); System.out.println(t.toString()); //输出为:ToString@1b6d3586 System.out.println(t); //输出为:ToString@1b6d3586 } } class ToString { private String name; private int age; public ToString() { } public ToString(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
分析以上代码:第一个点,输出的代码为:ToString@1b6d3586 可以简单的理解为这就是代码一个对象的地址,地址以字符串的形式表达出来让我们来看。第二个点,用t.toString()与直接用 t 的效果是一样的,直接用变量名输出会默认调用该子类的父类Object中的toString方法。
一般来说,我们用这个toString()方法输出地址,对我们开发用处不大,所以可以去把这个方法进行重写,对这个重写后的toString()方法是得到对象中的内容。
代码如下:
public class API { public static void main(String[] args) { ToString t = new ToString("lisi",22); System.out.println(t.toString()); //输出:ToString{name='lisi', age=22} System.out.println(t); //输出:ToString{name='lisi', age=22} } } class ToString { private String name; private int age; public ToString() { } public ToString(String name, int age) { this.name = name; this.age = age; } //对toString()进行重写 @Override public String toString() { return "ToString{" + "name='" + name + '\'' + ", age=" + age + '}'; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
运行结果如下:
分析以上代码:现在对象中内容是以字符串的形式输出,通过重写该方法,得到我们想到得到的内容了,所以toString()方法 存在的意义就是为了被子类重写,以便放回对象的具体内容。
简单来说,就是判断两个对象的地址是否相等。
代码如下:
public class API { public static void main(String[] args) { Equals e1 = new Equals(); Equals e2 = new Equals(); Equals e3 = e2; System.out.println(e1.equals(e2)); System.out.println(e1 == e2); System.out.println(e3.equals(e2)); System.out.println(e3 == e2); } } class Equals { private String name; private int age; public Equals() { } public Equals(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
运行结果如下:
对以上代码分析:第一点,首先创建了两个对象,然后用Object 中的 equals(Object o) 方法 来进行两个对象比较,结果肯定是false(因为两个对象都是通过 new 对象的,地址肯定不一样的)。第二点,这个效果跟直接用 == 的效果是一摸一样的,都是通过比较地址是否相同。
所以对这个 equals(Object o)方法 是不满足我们的需求 ,就可以重写这个方法。一般来说,需要是要通过比较对象中的内容(比如名字,年龄)来判断两个对象是否相同。
代码如下:
public class API { public static void main(String[] args) { Equals e1 = new Equals("lisi",22); Equals e2 = new Equals("lisi",22); System.out.println(e1.equals(e2)); System.out.println(e1 == e2); } } class Equals { private String name; private int age; public Equals() { } public Equals(String name, int age) { this.name = name; this.age = age; } //重写 equals(Object o) 方法 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Equals equals = (Equals) o; return age == equals.age && Objects.equals(name, equals.name); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
运行结果如下:
对以上代码进行分析:先通过有参数的构造器构建初识化的对象,然后调用重写 Object 中的 equals(Object o) 方法,从输出结果可以看出来,经过重写的方法,两个对象比较的不是对象的地址了,而是对象的具体内容。
代码如下:
//重写 equals(Object o) @Override public boolean equals(Object o) { //参数是Object,可以传进任何类型的对象 if (this == o) return true; //判断如果是对象自己跟对象自己比较,那肯定一样哇, //就不用比较和后面的具体的内容了 //所以这里比较的是地址,相同的地址肯定是自己本身啦 if (o == null || getClass() != o.getClass()) return false; //判断传进来的对象是否是空的,如果是空的话就没有必要接着后续的比较了 // 或者判断两个对象的类型是否相同, // 如果不相同就没有必要接着后续具体内容比较了,肯定是false。 Equals equals = (Equals) o; //强制类型转化 变量名 o 传进来的类型是 Object,需要强制转化一下。 return age == equals.age && Objects.equals(name, equals.name); //接下来就是进来对象中具体内容的比较了 }
第一点,getClass() 方法也是0bject 类的方法,值得注意的是为什么 既然传进来的是0bject 类型的 o 为啥判断的是Equals呢?
这是因为 getClass() 方法返回的是运行时类的引用,而不是编译时的类型。因此,如果一个对象是通过子类来创建的,那么getClass()方法返回的将是子类的Class对象,而不是父类的Class对象。
因此,getClass()方法的返回值类型是根据原始对象的运行时类型决定的,而不是根据引用类型决定的。
第二点,我们知道字符串String 类型已经重写了equals()方法,为啥要用这个Objects.equals(name, equals.name) 方法 不直接用String类中写好的equals()方法呢?这个下面介绍到 Objects 类会讲到的,具体的原因,接着往下看。
具体使用代码如下:
public class API { public static void main(String[] args) throws CloneNotSupportedException{ Clone clone = new Clone("lisi",22); Clone clone1 = (Clone)clone.clone(); System.out.println(clone1.getAge()); System.out.println(clone1.getName()); System.out.println("--------------------"); System.out.println(clone.getAge()); System.out.println(clone1.getName()); } } class Clone implements Cloneable{ private String name; private int age; public Clone() { } public Clone(String name, int age) { this.name = name; this.age = age; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
1.重写的 clone () 的方法跟之前的有所区别,直接返回去调用父类的clone()方法,这是因为 父类的clone()方法被protected修饰,所以在为子类不同包下去访问,所以可以说这次的重写起到的作用是中介作用,或者起过度转移作用。
2.重写完 clone () 的方法 还需要再接入一个接口 implements Cloneable。(语法规定)
3.调用重写完之后的 clone () 的方法 返回的是Object 类型的对象,需要强制类型转换。
4.因为会报异常,需要加上 throws CloneNotSupportedException 这串代码。
1.toString() 方法 基本作用:返回对象的字符串表达形式。存在的意义是,让子类重写,以便返回对象的内容。
2.equals() 方法 基本作用:比较两个对象的地址是否相同。存在的意义是,让子类重写,以便比较对象之间的具体的内容是否相同。
3.Object 中的 clone() 方法,当某个对象调用这个方法时,这个方法会返回一模一样的新对象。
先做非空判断,再比较两个对象,属于类方法,由类直接调用,返回值是boolean类型。
public static boolean equals(Object a, Object b) { return (a == b) || (a != null && a.equals(b)); //先判断是否自己本身的对象与自己本身的对象进行对比, //或者检查a对象是否为 null //最后再调用字符串String 类中的equals()方法 }
回顾:Objects.equals(name, equals.name) 方法 不直接用String类中写好的equals()方法?
是因为Objects.equals(name, equals.name) 方法比直接使用String类中写好的equals()方法多做了一步,就是判断对象本身是否为null。简单来说,如果不使用Objects.equals(name, equals.name) 这个方法,直接用String类中写好的equals()方法 ,则对象本身是没有判断自己是否为null,而Objects.equals(name, equals.name) 方法补上了这个漏洞,进行对象与对象内容比较之前判断了对象本身是否为null。所以使用Objects.equals(name, equals.name) 方法会更加安全。
判断对象是否为null,如果是就返回true,若不是就false。
代码如下:
public class API { public static void main(String[] args){ IsNull isNull = null; IsNull isNull1 = new IsNull(); System.out.println(Objects.isNull(isNull)); System.out.println(Objects.isNull(isNull1)); } } class IsNull { }
判断对象是否不为null,如果不为null就返回true,若为null就false。
代码如下:
public class API { public static void main(String[] args){ NonNull nonNull1 = null; NonNull nonNull2 = new NonNull(); System.out.println(Objects.nonNull(nonNull1)); System.out.println(Objects.nonNull(nonNull2)); } } class NonNull { }
在JAVA中,万物皆是对象,但是发现基本数据类型不是对象。此时包装类就可以将这些不是对象的基本数据类型包装成对象。而每个基本数据类型都会对应相应对象。
除了两个比较特殊,其他都很容易记住。
valueOf(int i) 方法就是将基本数据类 int 包装成对象。
代码如下:
public class API { public static void main(String[] args){ Integer integer = Integer.valueOf(12); System.out.println(integer); } }
基本数据类型直接会自动装箱成对象。
代码如下:
public class API { public static void main(String[] args){ Integer integer = Integer.valueOf(12); System.out.println(integer); Integer integer1 = 13; System.out.println(integer1); } }
包装类型的对象会自动拆箱成基本数据类型。
代码如下:
public class API { public static void main(String[] args){ Integer integer = Integer.valueOf(12); System.out.println(integer); Integer integer1 = 13; System.out.println(integer1); Integer integer2 = 14; int i = integer2; System.out.println(i); } }
我们知道泛型和集合是只能接受对象的,所以不能接受基本数据类型。
代码如下:
public class API { public static void main(String[] args){ ArrayList
list = new ArrayList<>(); list.add(12);//自动装箱 int i = list.get(0);//自动拆箱 System.out.println(i); }
可以将基本数据类型的数据转化为字符串。
代码如下:
import java.util.ArrayList; import java.util.Objects; public class API { public static void main(String[] args){ Integer integer = 12; String str = integer.toString(); //这个用对象去调用toString()方法 System.out.println(str+1); //输出结果为 121 Integer integer1 = 13; String str2 = Integer.toString(integer1); //这个用类直接去调用toString()方法 //这里的参数既可以直接写13,也可以integer1变量,因为自动拆箱 System.out.println(str2+1); //输出结果为 131 }
可以将字符串转化为基本数据类型。
代码如下:
public class API { public static void main(String[] args) { String str = "23.23"; int i = Integer.parseInt(str); //这个是类去调用方法,将字符串转化为对应的基本数据类型 //需要注意如果用“23.23”类似这种,程序会报错 int ii = Integer.valueOf(str); //而这种是使用valueOf()方法将字符串转换为基本数据类型的包装类对象, // 然后再通过自动拆箱操作获取基本数据类型的值。 System.out.println(i+1); System.out.println(ii+1); //输出 24 String str2 = "23.23"; double d = Double.parseDouble(str2); double dd = Double.valueOf(str2); System.out.println(d+1); System.out.println(dd+1); //输出24.23 }
深入思考为什么可以用 valueOf() 方法将字符串转化为基本数据类型?上面讲到这个方法不是用来接收 int 数据类型,然后转化为包装类对象吗?
在valueOf() 方法参数中不只是只有 int 数据类型,也可以接收String类型,转化为 Integer 包装类。
所以这两中方法都可以将字符串转化为基本数据类型。
总结起来,可以通过parseXxx()方法将字符串转换为基本数据类型,或者通过valueOf()方法将字符串转换为基本数据类型的包装类对象,然后再通过自动拆箱操作获取基本数据类型的值。