行业知识
JAVA头歌实训 Java面向对象 - 常用类
第1关:Object类
任务描述
本关任务:掌握Object类及Object类的一些常用方法。
相关知识
为了完成本关任务,你需要掌握:
1.什么是Object类;
2.Object类的方法;
3.Java对象克隆。
什么是Object类
Java中有一个比较特殊的类,就是 Object 类,它是所有类的父类,如果一个类没有使用extends关键字明确标识继承另外一个类,那么这个类就默认继承 Object 类。因此,Object 类是 Java 类层中的最高层类,是所有类的超类。换句话说,Java 中任何一个类都是它的子类。由于所有的类都是由 Object 类衍生出来的,所以 Object 类中的方法适用于所有类。
- public class Person //当没有指定父类时,会默认 Object 类为其父类
- {
- ...
- }
上面的程序等价于:
- public class Person extends Object
- {
- ...
- }
如果想引用你不知道的类型的对象,使用Object类是没有错的。请注意,父类引用变量可以引用子类对象,称为向上转换。下面举一个例子,有一个getObject()方法返回一个对象,但它可以是任何类型,如:Employee,Student等这样的类,我们可以使用Object类引用来引用该对象。 例如:
- Object obj=getObject();//we don't know what object will be returned from this method
Object类为所有对象提供了一些常见的行为,如对象可以进行比较,对象可以克隆,对象可以通知等。
Object类的方法
Object类提供了许多方法。 它们如下:
Object类的常用方法有: toString()和equals()方法。
1.关于toString()方法
-
在Object类里面定义toString()方法的时候返回的对象的哈希code码(对象地址字符串);
-
可以通过重写toString()方法表示出对象的属性。
此方法是在打印对象时被调用的,下面有两个范例,一个是没复写toString()方法,另一个是复写了 toString()方法,读者可比较两者的区别。
- package educoder;
- public class TestToStringDemo1 {
- public static void main(String[] args) {
- Person p = new Person();
- System.out.println(p);
- }
- }
- class Person extends Object {
- String name = "张三";
- int age = 18;
- }
输出结果: educoder.Person@7852e922
从上面的程序中可以发现,在打印对象p的时候实际上打印出的是一些无序的字符串,这样的字符串很少有人能看懂什么意思,之后可以再观察下面的范例,下面的范例复写了Object类中的 toString()方法。
- package educoder;
- public class TestToStringDemo2 {
- public static void main(String[] args) {
- Person p = new Person();
- System.out.println(p);
- }
- }
- class Person extends Object {
- String name = "张三";
- int age = 18;
- // 复写Object类中的toString()方法
- public String toString() {
- return "我是:" + this.name + ",今年:" + this.age + "岁";
- }
- }
输出结果: 我是:张三,今年:18岁
与 TestToStringDemo1.java 程序相比,程序TestToStringDemo2.java 在 Person 类中明确复写了 toString()方法,这样在打印对象p的时候,实际上是去调用了 toString()方法,只是并没有明显的指明调用 toString()方法而已,此时第 6 行相当于:
- System.out.println(p.toString());
2.关于equals()方法
比较的是对象的引用是否指向同一块内存地址,一般情况下,比较两个对象时是比较它的值是否一致,那如何解决呢?思路也比较简单,重写equals()方法。
在不重写的情况下,我们先看下程序执行情况,创建两个相同类型的对象,并判断对象是否相等。
- package educoder;
- public class test {
- public static void main(String[] args) {
- Dog dog = new Dog();
- dog.name = "jack";
- Dog dog1 = new Dog();
- dog1.name = "jack";
- System.out.println(dog);
- System.out.println(dog1);
- if (dog.equals(dog1)) {
- System.out.println("两个对象是相同的");
- } else {
- System.out.println("两个对象是不相同的");
- }
- }
- }
- class Animal {
- }
- class Dog extends Animal {
- int age = 20;
- String name = "rose";
- public String toString() {
- return "Dog [age=" + age + ", name=" + name + "]";
- }
- }
输出结果: Dog [age=20, name=jack] Dog [age=20, name=jack] 两个对象是不相同的
分析下 : 两个对象分别new了一次,开辟了两个不同内存空间,内存地址不同。object提供的equals()是用来比较的是对象的引用是否指向同一块内存地址。很显然,内存地址不一样,所以是不相等的,跟属性值是否一样完全没有任何关系。
一般情况下,我们是需要判断对象的属性值相等的,那么如何重写 equals()方法呢?通过Eclipse(集成开发环境)提供的快捷键,Dog类中出现如下方法,方法的解释也放在代码中一并进行解释如下:
- package educoder;
- public class test {
- public static void main(String[] args) {
- Dog dog = new Dog();
- dog.name = "jack";
- Dog dog1 = new Dog();
- dog1.name = "jack";
- System.out.println(dog);
- System.out.println(dog1);
- if (dog.equals(dog1)) {
- System.out.println("两个对象是相同的");
- } else {
- System.out.println("两个对象是不相同的");
- }
- }
- }
- class Animal {
- }
- class Dog extends Animal {
- int age = 20;
- String name = "rose";
- public String toString() {
- return "Dog [age=" + age + ", name=" + name + "]";
- }
- /* getClass() 得到的是一个类对象 */
- @Override
- public boolean equals(Object obj) {
- if (this == obj)// 两个对象的引用是否相同,如果相同,说明两个对象就是同一个
- return true;
- if (obj == null)// 如果比较对象为空,不需要比较,肯定不相等
- return false;
- if (getClass() != obj.getClass())// 比较两个对象的类型是否相同,如果不同,肯定不相同
- return false;
- Dog other = (Dog) obj;// 转化成相同类型后,判断属性值是否相同
- if (name == null) {
- if (other.name != null)
- return false;
- } else if (!name.equals(other.name))
- return false;
- return true;
- }
- }
输出结果: Dog [age=20, name=jack] Dog [age=20, name=jack] 两个对象是相同的
equals() 和 == 的区别:
- 在Java中,任何类型的数据都可以用 “==”进行比较是不是相等,一般用于基本数据类型的比较,比较器存储的值是否相等。但是如果用于引用类型的比较,则是比较所指向对象的地址是否相等,在这点上,跟object类提供的equals()方法的作用是一致的。
- 对于equals()方法
-
首先,不能用于基本数据类型的变量之间的比较相等;
-
如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;
-
诸如String、Date等类都对equals方法进行了重写,比较的是所指向的对象的内容。
Java对象克隆
对象克隆是一种创建对象的精确副本的方法。 Object类的clone()方法用于克隆对象。java.lang.Cloneable接口必须由我们要创建其对象克隆的类实现。如果我们不实现Cloneable接口,clone()方法将生成CloneNotSupportedException。
clone()方法在Object类中定义。 clone()方法的语法如下:
- protected Object clone() throws CloneNotSupportedException
为什么要使用clone()方法?
clone()方法保存用于创建对象的精确副本的额外处理任务。 如果我们使用new关键字执行它,它将需要执行大量的处理,这就是为什么我们使用对象克隆。 对象克隆的优点:
- 少处理任务。
clone()方法示例(对象克隆)
- package educoder;
- public class Student implements Cloneable {
- int rollno;
- String name;
- Student(int rollno, String name) {
- this.rollno = rollno;
- this.name = name;
- }
- public Object clone() throws CloneNotSupportedException {
- return super.clone();
- }
- public static void main(String args[]) {
- try {
- Student s1 = new Student(101, "amit");
- Student s2 = (Student) s1.clone();
- System.out.println(s1.rollno + " " + s1.name);
- System.out.println(s2.rollno + " " + s2.name);
- } catch (CloneNotSupportedException c) {
- }
- }
- }
输出结果: 101 amit 101 amit
从上面的例子可以看出,两个引用变量都有相同的值。 因此,clone()将对象的值复制到另一个对象。 因此,在实际应用中我们不需要编写显式代码将对象的值复制到另一个对象。如果通过new关键字创建另一个对象并将另一个对象的值赋给这个对象,则需要对该对象进行大量处理。 所以为了节省额外的处理任务,我们使用clone()方法。
编程要求
请仔细阅读右侧代码,根据方法内的提示,在Begin - End区域内进行代码补充,具体任务如下:
-
Demo类和Person类已经写好,在测试类中创建Demo类对象d1,传入输入值num1, d1调用toString方法并打印输出该值;
-
创建Demo类对象d2,同样传入输入值num1,打印判断d1和d2是否相等(实际是比较地址);
-
创建Person类对象p,传入输入值num2,打印判断d1和p是否相等(实际是比较地址);
测试说明
补充完代码后,点击测评,平台会对你编写的代码进行测试,当你的结果与预期输出一致时,即为通过。
测试输入: 100 100
预期输出: Demo:100 true false
开始你的任务吧,祝你成功!
package case1;import java.util.Scanner;public class ObjectTest {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int num1 = sc.nextInt();int num2 = sc.nextInt();// 在测试类中创建Demo类对象d1,传入输入值num1, d1调用toString方法并打印输出该值// 创建Demo类对象d2,同样传入输入值num1,打印判断d1和d2是否相等(实际是比较地址)/********* Begin *********/ Demo d1=new Demo(num1); System.out.println(d1.toString()); Demo d2=new Demo(num1); if(d1.equals(d2)){System.out.println("true"); }else{ System.out.println("false"); }/********* End *********/// 创建Person类对象p,传入输入值num2,打印判断d1和p是否相等(实际是比较地址)/********* Begin *********/ Person p=new Person(num2); if(d1.equals(p)){ System.out.println("true"); }else{ System.out.println("false"); }/********* End *********/}}第2关:JAVA基础类型包装类-练习
任务描述
通过所学知识,完成本关任务。
相关知识
略
编程要求
请仔细阅读右侧代码,根据方法内的提示,在Begin - End区域内进行代码补充,具体任务如下:
编写测试类,输入int型值aa传递给Integer类对象a,String型值bb传递给Integer类对象b,输入int型值c,aa、bb、c对应的数值相等;
输入String型值str11传递给String类对象str1,输入String型值str22传递给String类对象str2,str1和str2对应的内容相同;
打印输出a == b、a == c、b == c、a.equals(b);
打印输出str1 == str2、str1.equals(str2)。
测试说明
补充完代码后,点击测评,平台会对你编写的代码进行测试,当你的结果与预期输出一致时,即为通过。
测试输入:
100
100
100
educoder
educoder
预期输出:
false
true
true
true
false
true
开始你的任务吧,祝你成功!
package case2;import java.util.Scanner;public class WrapperTest {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int aa = sc.nextInt();String bb = sc.next();int c = sc.nextInt();String str11 = sc.next();String str22 = sc.next(); // 包装类中“==”与equals的用法比较// 值得注意的是,包装类中的equals方法和String类一样,都是重写了Object类中的equals方法,因此比较的是内容而不是地址,// 而“==”比较的依然是引用变量的地址,只是当包装类型和与之相对应的基本类型进行“==”比较时会先做自动拆箱处理。/********* Begin *********/ Integer a=new Integer(aa);Integer b=Integer.parseInt(bb);String str1=new String(str11);String str2=new String(str22);System.out.println(a==b);System.out.println(a==c);System.out.println(b==c);System.out.println(a.equals(b));System.out.println(str1==str2);System.out.println(str1.equals(str2)); /********* End *********/}}第3关:String&StringBuilder&StringBuffer类-练习
任务描述
通过所学知识,完成本关任务。
相关知识
略
编程要求
请仔细阅读右侧代码,根据方法内的提示,在Begin - End区域内进行代码补充,具体任务如下:
编写测试类,输入一个标准的网址,输出其域名的主体;
将该主体转换为大写,打印输出;
具体输出要求请看测试说明。
测试说明
补充完代码后,点击测评,平台会对你编写的代码进行测试,当你的结果与预期输出一致时,即为通过。
测试输入:
https://www.educoder.net/
预期输出:
educoder
EDUCODER
开始你的任务吧,祝你成功!
package case3;import java.util.Scanner;public class StringTest {public static void main(String[] args) {Scanner sc = new Scanner(System.in);String str = sc.next();// String substring(int start,int end) // 截取字符串,传入的两个参数分别为要截取边界的下标 // 在java api 中,通常使用两个数字表示范围时,都是含头不含尾,即包含起始下标对应的内容,但不包含结束下标的处对应的内容 // String toUpperCase() 将当前字符串中的英文部分转换为全大写/********* Begin *********/ String str1=str.substring(12,str.lastIndexOf('.')); if(str1.indexOf('.')>0){str1=str1.substring(0,str1.indexOf('.')); } System.out.println(str1); str1=str1.toUpperCase(); System.out.println(str1);/********* End *********/}}第4关:Random类
任务描述
本关任务:掌握Random类以及Random类的使用。
相关知识
为了完成本关任务,你需要掌握:
1.Random类;
2.Random对象的生成;
3.Random类中的常用方法。
Random类
Random类位于java.util包下,Random类中实现的随机算法是伪随机,也就是有规则的随机。在进行随机时,随机算法的起源数字称为种子数(seed),在种子数的基础上进行一定的变换,从而产生需要的随机数字。
相同种子数的Random对象,相同次数生成的随机数字是完全相同的。也就是说,两个种子数相同的Random对象,第一次生成的随机数字完全相同,第二次生成的随机数字也完全相同。这点在生成多个随机数字时需要特别注意。
Random对象的生成
Random类包含两个构造方法,下面依次进行介绍:
- public Random()
该构造方法使用一个和当前系统时间对应的相对时间有关的数字作为种子数,然后使用这个种子数构造Random对象。
- public Random(long seed)
该构造方法可以通过制定一个种子数进行创建。
示例代码:
- Random r = new Random();
- Random r1 = new Random(10);
再次强调:种子数只是随机算法的起源数字,和生成的随机数字的区间无关。
验证:相同种子数的Random对象,相同次数生成的随机数字是完全相同的。
- package educoder;
- import java.util.Random;
- public class RandomTest {
- public void random() {
- int i = 0;
- int j = 0;
- Random random = new Random(1);
- Random random1 = new Random(1);
- i = random.nextInt();
- j = random1.nextInt();
- System.out.println("i:" + i + "\nj:" + j);
- }
- public static void main(String[] args) {
- RandomTest tt = new RandomTest();
- tt.random();
- }
- }
输出结果: 第一次: i:-1155869325 j:-1155869325
修改一下起源数字,让其等于100。
- Random random = new Random(100);
- Random random1 = new Random(100);
输出结果: i:-1193959466 j:-1193959466
Random类中的常用方法
Random类中的方法比较简单,每个方法的功能也很容易理解。需要说明的是,Random类中各方法生成的随机数字都是均匀分布的,也就是说区间内部的数字生成的几率是均等的。下面对这些方法做一下基本的介绍:
- package educoder;
- import java.util.Random;
- public class RandomTest {
- public static void main(String[] args) {
- Random random = new Random();
- System.out.println("nextInt():" + random.nextInt()); // 随机生成一个整数,这个整数的范围就是int类型的范围-2^31~2^31-1
- System.out.println("nextLong():" + random.nextLong()); // 随机生成long类型范围的整数
- System.out.println("nextFloat():" + random.nextFloat()); // 随机生成[0, 1.0)区间的小数
- System.out.println("nextDouble():" + random.nextDouble()); // 随机生成[0, 1.0)区间的小数
- System.out.println("nextBoolean():"+random.nextBoolean());//随机生成一个boolean值,生成true和false的值几率相等,也就是都是50%的几率
- System.out.println("nextGaussian():"+random.nextGaussian());//随机生成呈高斯(“正态”)分布的 double 值,其平均值是 0.0,标准差是 1.0
- byte[] byteArr = new byte[5];
- random.nextBytes(byteArr); // 随机生成byte,并存放在定义的数组中,生成的个数等于定义的数组的个数
- System.out.print("nextBytes():");
- for (int i = 0; i
- System.out.print(byteArr[i]+"\t");
- }
- System.out.println();
- /**
- * random.nextInt(n)
- * 随机生成一个正整数,整数范围[0,n),包含0而不包含n
- * 如果想生成其他范围的数据,可以在此基础上进行加减
- *
- * 例如:
- * 1. 想生成范围在[0,n]的整数
- * random.nextInt(n+1)
- * 2. 想生成范围在[m,n]的整数, n > m
- * random.nextInt(n-m+1) + m
- * random.nextInt() % (n-m) + m
- * 3. 想生成范围在(m,n)的整数
- * random.nextInt(n-m+1) + m -1
- * random.nextInt() % (n-m) + m - 1
- * ......主要是依靠简单的加减法
- */
- System.out.println("nextInt(10):" + random.nextInt(10)); // 随机生成一个整数,整数范围[0,10)
- for (int i = 0; i
- System.out.println("我生成了一个[3,15)区间的数,它是:" + (random.nextInt(12) + 3));
- }
- /**
- * random.nextDouble()
- * 例如:
- * 1.生成[0,1.0)区间的小数
- * double d1 = random.nextDouble();//直接使用nextDouble方法获得。
- * 2.生成[0,5.0)区间的小数
- * double d2 = random.nextDouble() * 5;//因为扩大5倍即是要求的区间。同理,生成[0,d)区间的随机小数,d为任意正的小数,则只需要将nextDouble方法的返回值乘以d即可。
- * 3.生成[1,2.5)区间的小数
- * double d3 = r.nextDouble() * 1.5 + 1;//生成[1,2.5)区间的随机小数,则只需要首先生成[0,1.5)区间的随机数字,然后将生成的随机数区间加1即可。
- * ......同理,生成任意非从0开始的小数区间[d1,d2)范围的随机数字(其中d1不等于0),则只需要首先生成[0,d2-d1)区间的随机数字,然后将生成的随机数字区间加上d1即可。
- *
- */
- }
- }
输出结果: nextInt():1842341002 nextLong():4006643082448092921 nextFloat():0.88948154 nextDouble():0.5635189241159165 nextBoolean():false nextGaussian():1.3191426544832998 nextBytes():36 100 94 14 -98 nextInt(10):1 我生成了一个[3,15)区间的数,它是:5 我生成了一个[3,15)区间的数,它是:10 我生成了一个[3,15)区间的数,它是:10 我生成了一个[3,15)区间的数,它是:11 我生成了一个[3,15)区间的数,它是:6
JDK1.8新增方法:
- package educoder;
- import java.util.Random;
- public class RandomTest2 {
- /**
- * 测试Random类中 JDK1.8提供的新方法 JDK1.8新增了Stream的概念 在Random中,为double, int,
- * long类型分别增加了对应的生成随机数的方法 鉴于每种数据类型方法原理是一样的,所以,这里以int类型举例说明用法
- */
- public static void main(String[] args) {
- Random random = new Random();
- random.ints(); // 生成无限个int类型范围内的数据,因为是无限个,这里就不打印了,会卡***的......
- random.ints(10, 100); // 生成无限个[10,100)范围内的数据
- /**
- * 这里的toArray 是Stream里提供的方法
- */
- int[] arr = random.ints(5).toArray(); // 生成5个int范围类的整数。
- System.out.println(arr.length);
- for (int i = 0; i
- System.out.println(arr[i]);
- }
- // 生成5个在[10,100)范围内的整数
- arr = random.ints(5, 10, 100).toArray();
- for (int i = 0; i
- System.out.println(arr[i]);
- }
- /**
- * 对于 random.ints(); random.ints(ori, des);
- * 两个生成无限个随机数的方法,我们可以利用Stream里的terminal操作,来截断无限这个操作
- */
- // limit表示限制只要5个,等价于random.ints(5)
- arr = random.ints().limit(5).toArray();
- System.out.println(arr.length);
- for (int i = 0; i
- System.out.println(arr[i]);
- }
- // 等价于random.ints(5, 10, 100)
- arr = random.ints(10, 100).limit(5).toArray();
- for (int i = 0; i
- System.out.println(arr[i]);
- }
- }
- }
输出结果: 5 1801462452 -1812435985 -1073912930 1160255210 -1342018704 80 54 16 67 82 5 -1161610558 283052091 797550518 -275356995 -1661722790 11 27 27 52 54
编程要求
请仔细阅读右侧代码,根据方法内的提示,在Begin - End区域内进行代码补充,具体任务如下:
-
设计一个密码的自动生成器:密码由大写字母/小写字母/数字组成,生成六位随机密码。
-
分别以1、2、3作为种子数创建Random对象,生成六位随机密码进行测试。
-
具体输出要求请看测试说明。
测试说明
补充完代码后,点击测评,平台会对你编写的代码进行测试,当你的结果与预期输出一致时,即为通过。
测试输入: 1 预期输出: NAvZuG
开始你的任务吧,祝你成功!
package case4;//密码的自动生成器:密码由大写字母/小写字母/数字组成,生成六位随机密码import java.util.Random;import java.util.Scanner;public class RandomTest {public static void main(String[] args) {// 定义一个字符型数组char[] pardStore = new char[62];// 把所有的大写字母放进去 把所有的小写字母放进去 把0到9放进去/********* Begin *********/ for(int i=0;i
-
上一篇:javamc怎么查看服务器地址?
下一篇:脚踝这个单词怎么写?