匿名内部类;API;类库;Object类型的 toString 和 equals 方法;Scanner;String (Java Day11)
一,匿名内部类
- 没有名字的内部类【本质是类对象创建的另外一种格式 就是一个对象】
- 匿名内部类的使用前提:
匿名类:继承一个类 【根本就没有书写这个子类】
匿名类:实现一个接口【根本就没有书写这个实现类】
- 格式:
new 父类类名或者接口名() {
父类方法的重写或者是接口方法的重写}【他就是匿名内部类;他就是子类或实现类的对象】 - 本质:
- 创建了一个类的子类对象、接口的实现类对象
- 更强调关系的一种写法【省略了实现类的书写,直接创建了实现类的对象】
- 使用的注意事项:
- 匿名内部类可以单独使用【类似匿名对象】
- 匿名内部类可以赋值给父类类型的变量,重复使用
代码示例
//定义测试类
public class Test01 { public static void main(String[] args) { //匿名内部类 //使用多态形式【把匿名内部类赋值给接口类型的变量】[有快捷键生成] InterfaceA a = new InterfaceA() {
@Override public void show() { System.out.println(123); }
@Override public void print() { System.out.println(456); } }; a.show(); a.print();
//单纯的使用匿名内部类调用其中的方法,[有快捷键生成] new InterfaceA() {
@Overridepublic void show() { System.out.println(123); }
@Override public void print() { System.out.println(456); } }.print(); new InterfaceA() { //[有快捷键生成]
@Override public void show() {
System.out.println(123); }
@Override public void print() {
System.out.println(456);
} }.show(); } }
二,API
- 定义:应用程序接口【application programming interface】
通过查找API中的类,接口,枚举类等信息,能够快速理解其作用的帮助文档。 - 查找方式:
- 索引查找法:知道包名,找对应的类名。
- 名称查找法:不知道包名,但知道类名。
- 接口:用于规定方法名称的规则的集合。定义方法的修饰符、返回值类型、方法的名称、方法的参数列表、方法的功能。
- 实际:应用程序编程接口,也包含了各种实际有实现内容的方法、类型、接口、枚举说明
- 学习jdk的API:内容的使用 比如:属性、成员方法的学习、构造方法的调用学习【使用方式和使用上 效果不关注如何实现的。】
三,类库
- 概述:类的仓库。存放已经写好的类的文件压缩包 jdk的核心类库
- java的源代码编译之后,形成.class的字节码文件,就包含了这个类中的所有内容,在脱离源代码的前提下,这个.class字节码文件,也可以继续用
- Java中可以将.class的字节码文件,打包生成jar包
Jar包就是.class文件的压缩包,是java专用的压缩包,一旦获得了jar包就相当于获得了里面所有的.class文件
jar包的生成:在eclipse中选中要打包的类型(包、工程),右键选择 export----java----jar file----选择生成的jar文件的路径
jar包的使用:将下载好的jar包,拷贝到当前工程中,选择该jar包,右键 build path----add to Build path(将当前jar包中的类型,添加到当前工程的编译路径)
jar包的删除:先把jar文件删掉;将依赖路径也删掉(不要让当前工程继续依赖这个jar包),build path----configure build path----libraries----remove丢失的jar文件
- 类型库:
jar包的内容还是太少,一系列相关的jar包,组成一个类型库,library
一旦导入了类型库,就相当于导入了类库中的所有jar包,相当于是获取了其中的所有.class类型,例如,导入了JUnit类库之后,就可以对方法进行单元测试
添加的方式:
选中工程----右键----build path----add libraries----选择要添加的类型库即可
四,Object类型
- 概述:类
Object
是类层次结构的根类。每个类都使用Object
作为超类。所有对象(包括数组)都实现这个类的方法。 - 个人理解:他是java中所有类的父类,所有的类默认继承这个类,他的方法都被所有类对象来使用
- 构造方法:
- 空参构造:Object():创建一个object对象
- 常用方法:
-
toString方法
1.1 作用:返回该对象的字符串表示。
1.2 字符串表示内容就是:对象的地址值 // getClass().getName() + '@' + Integer.toHexString(hashCode())
1.3 输出语句中输出的是对象名,默认的去使用对象调用了toString方法
代码演示:
//定义测试类
public class Demo_Object {
public static void main(String[] args) {
//创建类的对象
Object object = new Object();
String name = object.toString();
System.out.println(name);//输出的是对象的地址值
Object object1 = new Object();
String name1 = object1.toString();
System.out.println(name1);//输出的是对象的地址值
}
}
- java.lang.Object@70dea4e: 是object类一个对象的地址值【全限定类名+@+十六进制数】
- java.lang是java.language的缩写,Java语言,java.lang包无需导入包使用。
- 全限定类名:就是带包路径的类名
- 十六进制数:创建对象的时候系统为了区分每一个对象,自动给对象生成的一个编号
- 思考:
- 我们打印对象名的时候,想看的是地址值还是对象的属性的值?
- 但是Object类中没有属性,所以Object类中只能显示地址值;但是如果是其他类,想要看的是类中属性的值;其他类可以重写toString方法,显示属性值
- 【子类往往要重写这个toString才能达到查看属性值的效果】
子类重写toString方法代码示例
//定义测试类
public class Demo_Object {
public static void main(String[] args) {
//创建类的对象
Object object = new Object();
String name = object.toString();
System.out.println(name);
Object object1 = new Object();
String name1 = object1.toString();
System.out.println(name1);
Person person = new Person(18, "金莲");
String path = person.toString();
System.out.println(path);
//没重写结果 :com.ujiuye.demo.Person@33909752
//重写结果:Person [age=18, name=金莲]
}
}
//定义Person类
public class Person {
private int age ;
private String name;
//构造方法
public Person(int age, String name) {
super();
this.age = age;
this.name = name;
}
public Person() {
super();
}
//getter/setter方法
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//重写toString方法 快捷键 [alt+shift+s s]
@Override
public String toString() {
return "Person [age=" + age + ", name=" + name + "]";
}
}
2、equals方法
- 作用:用于比较两个引用数据类型的对象的内容值
- 参数:就是Object 的对象 【被比较的对象】
- 返回值: true或false
代码示例
//定义测试类
public class Demo_Object01 {
public static void main(String[] args) {
//创建Object的对象
Object o1 = new Object();
Object o2 = new Object();
boolean b = o1.equals(o2);
System.out.println(b);//false 比较的是o1和o2两个对象的地址值是否一致
System.out.println(o1.equals(o1));//true
System.out.println(o1.equals(null));
//System.out.println(null.equals(o1));//原因equals方法要被对象调用,null不是一个对象
o2 = null;
System.out.println(o2.equals(o1));//报错 NullPointerException
}
}
- 注意事项:在以后的开发中如果一个对象的值有可能会是null值使用equals方法的时候把它放到参数中去,这样避免空指针异常的出现
- 思考:在Object类中比较的是地址值,但是在其他类中穷们需要比较的是地址值还是属性的值?
一般情况下比较属性值,所以需要子类自己对这个equals方法进行重写。重写的快捷键 [alt+shift+s h]
- 总结:在Object中操作的都是地址值;
- 在子类中:
- 重写了对应方法:操作的是属性值
- 没有重写:操作的是对象的地址值
-
== 和 equals 方法的区别【典型的面试题】
- ==:可以比较所有的数据类型
- 基本数据类型:比较的就是数值的大小
- 引用数据类型:比较的对象的地址值得大小【本质比较的还是值的大小】
- 注意:Object类的equals方法底层其实使用的就==比较 ,所以地址值的比较
- equals():只能比较引用数据类型的对象,不能比较基本数据类型
- 类中没有重写equals方法:调用就是父类【Object】中的equals方法比较的是地址值
- 类中重写equals方法:比较的是对象中属性的内容值是否一致
代码示例
public class Demo_Compare {
public static void main(String[] args) {
Person person = new Person(18, "金莲");
Person person1 = new Person(18, "金莲");
boolean c = person.equals(person1);
System.out.println(c);//true 比较的是内容属性值
System.out.println(person == person1);//false比较的地址值不一样
System.out.println(5 == 3);
//System.out.println(5.equals(3));只能比较引用数据类型对象,这里的3是基本数据类型不能进行比较
}
}
- 总结:
- object类的 toString()、equals(Object o)操作的都是地址值
- 其他类要想操作属性值,需要重写 toString 和 equals 方法
- jdk提供的类99%都已经重写了toString方法和equals方法
- 自定义的类根据自己的使用场景决定是否要重写这两个方法 比如:Person
五,Scanner
-
概述
- 一个可以使用正则表达式来解析基本类型和字符串的简单文本扫描器。
- Scanner是一个扫描器【键盘录入只是扫描当中的一种功能,比较常用】
- 构造方法:
3.1 Scanner(File f):扫描指定文件
3.2 Scanner(String path):扫描指定的路径
3.3 Scanner(InputStream is):扫描指定的输入流【键盘录入功能】
- System.in: 是一个InputStream类型的对象
-
录入基本数据类型
- 录入基本数据类型的方法:
nextByte(): 录入一个byte类型的数字到内存
nextShort(): 录入一个short类型的数字到内存
nextInt(): 录入一个int类型的数字到内存
nextLong(): 录入一个long类型的数字到内存
nextBoolean(): 录入一个boolean类型的数字到内存
nextFloat(): 录入一个float类型的数字到内存
nextDouble(): 录入一个double类型的数字到内存
- 总结:nextXxx()【Xxx代表你想要的扫描的数据类型】
- 回顾:
- 导包
- 创建扫描器对象
- 调用对应的功能扫描数据
- 使用数据做事情
代码示例
import java.util.Scanner;
public class Demo_Scanner01 {
public static void main(String[] args) {
//录入基本数据类型的数据
Scanner sc = new Scanner(System.in);
System.out.println("请输入数据:");
byte b = sc.nextByte();
System.out.println(b);
short s = sc.nextShort();
System.out.println(s);
int i = sc.nextInt();
System.out.println(i);
long l = sc.nextLong();
System.out.println(l);
float f = sc.nextFloat();
System.out.println(f);
double d = sc.nextDouble();
System.out.println(d);
boolean c = sc.nextBoolean();
System.out.println(c);
}
}
- 注意事项:录入 long 和 float 类型的数据时不需要加 L 和 f。
-
录入字符串类型
- next():扫描输入流中的字符串,以空格为结束【录入一个不含空格的字符串】
- nextLine():扫描输入流中的字符串,以回车为结束【录入一整行的字符串】
这两个功能使用同一个扫描器对象同时出现顺序不同会造成内容识别交叉的错误。一般不使用同一个对象同时调用这两个方法。【细节】
-
Scanner类型的小问题以及解决
练习:
1、使用nextInt()录入一个数字后,接着调用nextLine()输入一段话
2、使用next()录入一个字符串后,接着调用nextLine方法输入一段话
3、使用nextInt()录入一个数字后,接着调用next方法输入字符串
代码示例:
import java.util.Scanner;
public class Test_Scanner {
public static void main(String[] args) {
//1,使用nextInt()录入一个数字后,接着调用nextLine()输入一段话
Scanner sc = new Scanner(System.in);
//Method01(sc);
//method02(sc);
//3、使用nextInt()录入一个数字后,接着调用next方法输入字符串
System.out.println("请输入一个int类型的数字:");
int num = sc.nextInt();
System.out.println(num);
System.out.println("请输入一段话:");
String line = sc.next();
System.out.println(line);
}
private static void method02(Scanner sc) {
//2、使用next()录入一个字符串后,接着调用nextLine方法输入一段话
System.out.println("请输入一段字符串");
String next = sc.next();
System.out.println(next);
System.out.println("请输入一段字符串");
String next2 = sc.nextLine();
System.out.println(next2);
/**
* 为什么输入了一段话之后再输入一段话的时候我不能输入了呢?
* 输入这段话的时候回车了,数字和回车就全部进入到sc的流中,扫描字符串的时候只把字符串扫描走了,流中还有回车
* 接下来调用nextLine的时候他就扫描到了回车,就直接结束
* */
}
private static void Method01(Scanner sc) {
System.out.println("请输入一个int类型的数字:");
int num = sc.nextInt();
System.out.println(num);
System.out.println("请输入一段话:");
String line = sc.nextLine();
System.out.println(line);
/**
* 为什么输入了数字之后再输入一段话的时候我不能输入了呢?
* 输入数字的时候回车了,数字和回车就全部进入到sc的流中,扫描数字的时候只把数字扫描走了,流中还有回车
* 接下来调用nextLine的时候他就扫描到了回车,就直接结束
* */
}
}
六,String
-
概述
- 是字符串类,描述字符序列;
- 所有的字符串常量都是String的对象;
- 字符串常量存在于方法区的字符串常量池中
- 字符串对象的字面值其实就是一个字符串常量,所以字符串不可变
原因:字符串类只提供对应的构造方法创建对象,而没有提供setter方法,属性被封装的我无法使用方法对属性值进行修改,所以字符串一旦确定下来就不可变了。
-
String类型的构造方法
- String():空参构造 创建一个没有任何字符串内容的字符串对象
- String(byte[] b):把一个字节数组的内容转变成对应的字符串
- String(char[] c): 把一个字符数组转变为字符串
- String (byte[] b , int starIndex,int length): 把字节数组中starIndex角标开始了length个长度的内容转化为字符串
- String (char[] b , int starIndex,int length): 把字符数组中starIndex角标开始了length个长度的内容转化为字符串
- String(String s):创建一个内容为s的字符串对象
- 创建字符串对象的方式有:
- 构造方法创建 比如:String s = new String(“abc”)
- 使用字符串常量进行赋值 比如 String s = “abc”
- 有什么区别?
- 使用构造方法创建的字符串需要在内存空间的堆空间中开辟新的空间把内容值放到这片空间了【键盘录入的字符串就属于new出来的】【指向堆空间】
- 直接赋值定义的字符串不需要在堆空间开辟空间,直接到常量池来取值【指向常量池】
-
String的常用功能
-
String类型的判断功能
1.1、equals(String obj):比较两个字符串内容是否一致
1.2、equalsIgnoreCase(String otherStr):忽略大小写比较字符串内容
1.3、contains(String str):判断调用字符串是否包含参数字符串
1.4、startsWith(String prefix):判断字符串是否以参数字符串开头
1.5、endsWith(String suffix):判断字符串是否以参数字符串结尾
1.6、isEmpty():判断字符串是否有内容
代码示例
public class Demo_StringMethod {
public static void main(String[] args) {
//判断功能
String s = "abcdefg";
String ss = new String(s);
System.out.println(s.equals(ss));//true
System.out.println(s.equalsIgnoreCase("ABCdefG"));//true
System.out.println(ss.endsWith("fg"));//true
System.out.println(ss.startsWith("fg"));//false
System.out.println(ss.contains("mn"));//false
System.out.println(s.isEmpty());//false
}
}
-
判断功能练习
- 模拟用户登录:
- 正确用户名是admin,密码是123
- 键盘录入用户名和密码,一共有三次机会,如果录入错误,前两次提示还有几次机会
- 最后一次提示“登录机会已经用完”
- 录入正确,提示“登录成功”
- 分析:
- 使用变量承载用户名和密码
- 键盘录入对应的用户名和密码
- 在循环内输入,然后比较,用户名和密码同时满足登录成功
- 不满足重新登录,控制登录次数,满三次结束 不满三次继续
代码示例
import java.util.Scanner;
public class String_Test {
public static void main(String[] args) {
String name = "admin";
String word = "123";
Scanner sc = new Scanner(System.in);
for (int i = 1; i <= 3; i++) {
System.out.println("请输入用户名:");
String userName = sc.next();
System.out.println("请输入密码:");
String password = sc.next();
if (name.equals(userName) && word.equals(password)) {
System.out.println("恭喜你登陆成功");
break;
}else {
if (i==3) {
System.out.println("您登录的用户名或密码不对");
System.out.println("对不起您的登录次数已用完");
} else {
System.out.println("您登录的用户名或密码不对请重新登录");
}
}
}
}
}