Day10
引用类型作为方法的形参
类名:(匿名对象的时候其实我们已经讲过了)需要的是该类的对象
抽象类:需要的是该抽象的类子类对象
接口:需要的是该接口的实现类对象
//类名作为方法的形式参数
class Student {
public void study() {
System.out.println("Good Good Study,Day Day Up");
}
}
class StudentDemo {
public void method(Student s) { //ss; ss = new Student(); Student s = new Student();
s.study();
}
}
class StudentTest {
public static void main(String[] args) {
//需求:我要测试Student类的study()方法
Student s = new Student(); //创建对象
s.study(); //调用方法
System.out.println("----------------");
//需求2:我要测试StudentDemo类中的method()方法
StudentDemo sd = new StudentDemo();
Student ss = new Student();
sd.method(ss);
System.out.println("----------------");
//匿名对象用法
new StudentDemo().method(new Student());
}
}
//抽象类作为方法的形式参数
abstract class Person {
public abstract void study();
}
class PersonDemo {
public void method(Person p) {//p; p = new Student(); Person p = new Student(); //多态
p.study();
}
}
//定义一个具体的学生类
//抽象类作为方法的形式参数
class Student extends Person {
public void study() {
System.out.println("Good Good Study,Day Day Up");
}
}
class PersonTest {
public static void main(String[] args) {
//目前是没有办法的使用的
//因为抽象类没有对应的具体类
//那么,我们就应该先定义一个具体类
//需求:我要使用PersonDemo类中的method()方法
PersonDemo pd = new PersonDemo();
Person p = new Student();
pd.method(p);
}
}
//接口作为方法的形式参数
interface Love {
public abstract void love();
}
class LoveDemo {
public void method(Love l) { //l; l = new Teacher(); Love l = new Teacher(); 多态
l.love();
}
}
//定义具体类实现接口
class Teacher implements Love {
public void love() {
System.out.println("老师爱学生,爱Java");
}
}
class TeacherTest {
public static void main(String[] args) {
//需求:我要测试LoveDemo类中的love()方法
LoveDemo ld = new LoveDemo();
Love l = new Teacher();
ld.method(l);
}
}
引用类型作为返回值
类:返回的是该类的对象
抽象类:返回的是该抽象类的子类对象
接口:返回的是该接口的实现类的对象
//类最为返回值
class Student {
public void study() {
System.out.println("Good Good Study,Day Day Up");
}
}
class StudentDemo {
public Student getStudent() {
//Student s = new Student();
//Student ss = s;
//Student s = new Student();
//return s;
return new Student();
}
}
class StudentTest2 {
public static void main(String[] args) {
//需求:我要使用Student类中的study()方法
//但是,这一次我的要求是,不要直接创建Student的对象
//让你使用StudentDemo帮你创建对象
StudentDemo sd = new StudentDemo();
Student s = sd.getStudent(); //new Student(); Student s = new Student();
s.study();
}
}
//抽象类作为返回值
abstract class Person {
public abstract void study();
}
class PersonDemo {
public Person getPerson() {
//Person p = new Student();
//return p;
return new Student();
}
}
class Student extends Person {
public void study() {
System.out.println("Good Good Study,Day Day Up");
}
}
class PersonTest2 {
public static void main(String[] args) {
//需求:我要测试Person类中的study()方法
PersonDemo pd = new PersonDemo();
Person p = pd.getPerson(); //new Student(); Person p = new Student(); 多态
p.study();
}
}
//接口作为返回值
interface Love {
public abstract void love();
}
class LoveDemo {
public Love getLove() {
//Love l = new Teacher();
//return l;
return new Teacher();
}
}
//定义具体类实现接口
class Teacher implements Love {
public void love() {
System.out.println("老师爱学生,爱Java");
}
}
class TeacherTest2 {
public static void main(String[] args) {
//如何测试呢?
LoveDemo ld = new LoveDemo();
Love l = ld.getLove(); //new Teacher(); Love l = new Teacher(); 多态
l.love();
}
}
链式编程
每次调用完毕后返回的是一个对象(只有对象才能继续调方法)
class Student {
public void study() {
System.out.println("Good Good Study,Day Day Up");
}
}
class StudentDemo {
public Student getStudent() {
return new Student();
}
}
class StudentTest3 {
public static void main(String[] args) {
//如何调用的呢?
StudentDemo sd = new StudentDemo();
//Student s = sd.getStudent();
//s.study();
//相当于下边的
sd.getStudent().study();
}
}
包
其实就是文件夹
作用
把相同的类名放到不同的包中
对类进行分类管理
举例:
学生:增加,删除,修改,查询
老师:增加,删除,修改,查询
...
方案1:按照功能分
cn.itcast.add
AddStudent
AddTeacher
cn.itcast.delete
DeleteStudent
DeleteTeacher
cn.itcast.update
UpdateStudent
UpdateTeacher
cn.itcast.find
FindStudent
FindTeacher
方案2:按照模块分
cn.itcast.teacher
AddTeacher
DeleteTeacher
UpdateTeacher
FindTeacher
cn.itcast.student
AddStudent
DeleteStudent
UpdateStudent
FindStudent
包的定义
package 包名;
多级包用.分开即可
注意事项:
package语句必须是程序的第一条可执行的代码
package语句在一个java文件中只能有一个
如果没有package,默认表示无包名
带包的编译和运行:
手动式
编写一个带包的java文件
通过javac命令编译该java文件
手动创建包名
把b步骤的class文件放到c步骤的最底层包
回到和包根目录在同一目录的地方,然后运行
带包运行
自动式
编写一个带包的java文件
javac编译的时候带上-d即可
javac -d . HelloWorld.java
回到和包根目录在同一目录的地方,然后运行
带包运行
导包
格式:import 包名;
这种方式导入是到类的名称,注意:我们用谁就导谁
例:import cn.itcast.Demo //Demo为类名
package,import,class的顺序关系
package > import > class
Package:只能有一个
import:可以有多个
class:可以有多个,以后建议是一个
权限修饰符的访问
本类 同一个包下(子类和无关类) 不同包下(子类) 不同包下(无关类)
private Y
默认 Y Y
protected Y Y Y
public Y Y Y Y
protected 受保护的,一般给子类使用
修饰符的分类
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
抽象修饰符:abstract
类可以用的修饰符
权限修饰符:默认修饰符,public
状态修饰符:final
抽象修饰符:abstract
用的最多的就是:public
成员变量可以用的修饰符
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
用的最多的就是:private
构造方法可以用的修饰符
权限修饰符:private,默认的,protected,public
用的最多的就是:public
成员方法可以用的修饰符
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
抽象修饰符:abstract
用的最多的就是:public
除此以外的组合规则:
成员变量:public static final
成员方法:public static
public abstract
public final
内部类
把类定义在其他类的内部,这个类就被称为内部类
举例:在类A中定义了一个类B,类B就是内部类
内部的访问特点
内部类可以直接访问外部类的成员,包括私有
外部类要访问内部类的成员,必须创建对象
内部类的位置
在成员位置(变量处)称为成员内部类
在局部位置(方法体内)称为局部内部类
成员内部类的直接访问
格式: 外部类.内部类 对象名 = 外部类对象.内部类对象
例: Out.In oi = new Out().In;
成员内部类的修饰符
private 为了保证数据的安全性
static 为了方便访问数据
注意:静态内部类访问的外部类数据必须用静态修饰
成员内部类被静态修饰后的访问方式是
格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();
/*案例:我有一个人(人有身体,身体内有心脏)
class Body {
private class Heart {
public void operator() {
System.out.println("心脏搭桥");
}
}
public void method() {
if(如果你是外科医生) {
Heart h = new Heart();
h.operator();
}
}
}
按照我们刚才的讲解,来使用一下
Body.Heart bh = new Body().new Heart();
bh.operator();
//加了private后,就不能被访问了
Body b = new Body();
b.method();
*/
class Outer {
private int num = 10;
private static int num2 = 100;
//内部类用静态修饰是因为内部类可以看出是外部类的成员
public static class Inner {
public void show() {
//System.out.println(num);
System.out.println(num2);
}
public static void show2() {
//System.out.println(num);
System.out.println(num2);
}
}
}
class InnerClassDemo4 {
public static void main(String[] args) {
//使用内部类
// 限定的新静态类
//Outer.Inner oi = new Outer().new Inner();
//oi.show();
//oi.show2();
//成员内部类被静态修饰后的访问方式是:
//格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();
Outer.Inner oi = new Outer.Inner();
oi.show();
oi.show2();
//show2()的另一种调用方式,静态方法和静态成员可以通过类名来访问
Outer.Inner.show2();
}
}
/*面试题:
在三个输出语句中填空分别输出30,20,10
注意:
1:内部类和外部类没有继承关系
2:通过外部类名限定this对象
Outer.this
*/
class Outer {
public int num = 10;
class Inner {
public int num = 20;
public void show() {
int num = 30;
System.out.println(num); //就近原则,输出30
System.out.println(this.num); //当前类的num,及Inner的num,输出20
//System.out.println(new Outer().num);通过对象调用成员变量,可以输出10
System.out.println(Outer.this.num); //通过类名限制this,输出10
}
}
}
class InnerClassTest {
public static void main(String[] args) {
Outer.Inner oi = new Outer().new Inner(); //创建成员内部对象
oi.show();
}
}
局部内部类
可以直接访问外部类的成员
在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能
/*面试题:
局部内部类访问局部变量的注意事项?
A:局部内部类访问局部变量必须用final修饰
B:为什么呢?
局部变量是随着方法的调用而调用,随着调用完毕而消失。
而堆内存的内容并不会立即消失。所以,我们加final修饰。
加入final修饰后,这个变量就成了常量。既然是常量。你消失了。
我在内存中存储的是数据20,所以,我还是有数据在使用。
*/
class Outer {
private int num = 10;
public void method() {
//int num2 = 20;
//final int num2 = 20;
class Inner {
public void show() {
System.out.println(num);
//从内部类中访问本地变量num2; 需要被声明为最终类型
System.out.println(num2);//20
}
}
//System.out.println(num2);
Inner i = new Inner();
i.show();
}
}
class InnerClassDemo5 {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}
匿名内部类
就是内部类的简化写法
前提:存在一个类或者接口
这里的类可以是具体类也可以是抽象类
格式:
new 类名或者接口名(){
重写方法;
}
匿名内部类本质是一个继承了该类或者实现了该接口的子类匿名对象
interface Inter {
public abstract void show();
public abstract void show2();
}
class Outer {
public void method() {
//一个方法的时候
/*
new Inter() {
public void show() {
System.out.println("show");
}
}.show();
*/
//二个方法的时候
/*
new Inter() {
public void show() {
System.out.println("show");
}
public void show2() {
System.out.println("show2");
}
}.show();
new Inter() {
public void show() {
System.out.println("show");
}
public void show2() {
System.out.println("show2");
}
}.show2();
*/
//如果我是很多个方法,就很麻烦了
//那么,我们有没有改进的方案呢?
Inter i = new Inter() { //多态
public void show() {
System.out.println("show");
}
public void show2() {
System.out.println("show2");
}
};
i.show();
i.show2();
}
}
class InnerClassDemo6 {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}
/*
匿名内部类面试题:
按照要求,补齐代码
interface Inter { void show(); }
class Outer { //补齐代码 }
class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
}
}
要求在控制台输出”HelloWorld”
*/
interface Inter {
void show();
//public abstract
}
class Outer {
//补齐代码
public static Inter method() {
//子类对象 -- 子类匿名对象
return new Inter() {
public void show() {
System.out.println("HelloWorld");
}
};
}
}
class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
/*
1:Outer.method()可以看出method()应该是Outer中的一个静态方法。
2:Outer.method().show()可以看出method()方法的返回值是一个对象。
又由于接口Inter中有一个show()方法,所以我认为method()方法的返回值类型是一个接口。
*/
}
}
匿名对象在开发中的使用
/*
匿名内部类在开发中的使用
*/
interface Person {
public abstract void study();
}
class PersonDemo {
//接口名作为形式参数
//其实这里需要的不是接口,而是该接口的实现类的对象
public void method(Person p) {
p.study();
}
}
//实现类
class Student implements Person {
public void study() {
System.out.println("好好学习,天天向上");
}
}
class InnerClassTest2 {
public static void main(String[] args) {
//测试
PersonDemo pd = new PersonDemo();
Person p = new Student();
pd.method(p);
System.out.println("--------------------");
//匿名内部类在开发中的使用
//匿名内部类的本质是继承类或者实现了接口的子类匿名对象
pd.method(new Person(){
public void study() {
System.out.println("好好学习,天天向上");
}
});
}
}
Day11
API
Object类
类 Object 是类层次结构的根类,每个类都使用 Object 作为超类,每个类都直接或者间接的继承自Object类
Object类的方法:
hasnCode()
public int hashCode():返回该对象的哈希码值
注意:哈希值是根据哈希算法计算出来的一个值,这个值和地址值有关,但是不是实际地址值, 你可以理解为地址值
getName()
返回此 Object 的运行时类Class类的方法
public String getName() 以 String 的形式返回此 Class 对象所表示的实体,就是会输出调用对象的包跟类
public class Student extends Object {
}
public class StudentTest {
public static void main(String[] args) {
Student s1 = new Student();
System.out.println(s1.hashCode()); // 11299397
Student s2 = new Student();
System.out.println(s2.hashCode());// 24446859
Student s3 = s1;
System.out.println(s3.hashCode()); // 11299397
System.out.println("-----------");
Student s = new Student();
Class c = s.getClass();
String str = c.getName();
System.out.println(str); // cn.itcast_01.Student
//链式编程
String str2 = s.getClass().getName();
System.out.println(str2);
}
}
toString()
public String toString() 返回该对象的字符串表示,就是返回该类的所有变量值
使用idea会自动生成重写
调用:对象名.toString();
equals
public boolean equals(Object obj) 指示其他某个对象是否与此对象“相等”,默认情况下是比较两个对象的地址值是否相同,使用idea自动生成后可以比较一个类中的两个对象的具体值是否相同
例:学生s1和学生s2的姓名和年龄是否相同
调用:s1.equals(s2) 比较s1和s2的具体值是否相同
finallize
protected void finalize():当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法,用于垃圾回收,但是什么时候回收不确定
Cloneable
此类实现了 Cloneable 接口,以指示 Object.clone() 方法可以合法地对该类实例进行按字段复制
注意:
要在main方法后加throws CloneNotSupportedException
public static void main(String[] args) throws CloneNotSupportedException {}
还要在类后实现接口Cloneable
public class Student implements Cloneable
**instanceof **
判断一个对象该类的一个对象
格式:对象名 instranceof 类名
Day12
Scanner
用于接收键盘录入数据
使用
-导包
-创建对象
-调用方法
System类下有一个静态的字段:
public static final InputStream in; 标准的输入流,对应着键盘录入
InputStream is = System.in;
构造方法:
Scanner(InputStream source)//system.in 就相当于InputStram spurce
基本格式:
public boolean hasNextXxx():判断是否是某种类型的元素
public Xxx nextXxx():获取该元素
举例:用int类型的方法举例
public boolean hasNextInt()
public int nextInt()
注意:InputMismatchException:输入的和你想要的不匹配
先输入一个数值后边跟一个字符串时会出错,因为把换行给了字符串
解决方法:
先获取一个数值后,在创建一个新的键盘录入对象获取字符串
把所有的数据都先按照字符串获取,然后要什么,你就对应的转换为什么
String
字符串:就是由多个字符组成的一串数据,也可以看成是一个字符数组
通过查看API,我们可以知道
字符串字面值"abc"也可以看成是一个字符串对象
字符串是常量,一旦被赋值,就不能被改变
构造方法:
public String():空构造
public String(byte[] bytes):把字节数组转成字符串
public String(byte[] bytes,int index,int length):把字节数组的一部分转成字符串(从索引index开始,一共length长度)
public String(char[] value):把字符数组转成字符串
public String(char[] value,int index,int count):把字符数组的一部分转成字符串
public String(String original):把字符串常量值转成字符串
字符串的方法:
public int length():返回此字符串的长度
//构造方法代码实现
public class StringDemo {
public static void main(String[] args) {
// public String():空构造
String s1 = new String();
System.out.println("s1:" + s1);
System.out.println("s1.length():" + s1.length());
System.out.println("--------------------------");
// public String(byte[] bytes):把字节数组转成字符串
byte[] bys = { 97, 98, 99, 100, 101 };
String s2 = new String(bys);
System.out.println("s2:" + s2);
System.out.println("s2.length():" + s2.length());
System.out.println("--------------------------");
// public String(byte[] bytes,int index,int length):把字节数组的一部分转成字符串
// 我想得到字符串"bcd"
String s3 = new String(bys, 1, 3); //从索引1开始,取三个
System.out.println("s3:" + s3);
System.out.println("s3.length():" + s3.length());
System.out.println("--------------------------");
// public String(char[] value):把字符数组转成字符串
char[] chs = { 'a', 'b', 'c', 'd', 'e', '爱', '学', '习' };
String s4 = new String(chs);
System.out.println("s4:" + s4);
System.out.println("s4.length():" + s4.length());
System.out.println("--------------------------");
// public String(char[] value,int index,int count):把字符数组的一部分转成字符串
String s5 = new String(chs, 2, 4); //从索引2开始,取4个
System.out.println("s5:" + s5);
System.out.println("s5.length():" + s5.length());
System.out.println("--------------------------");
//public String(String original):把字符串常量值转成字符串
String s6 = new String("abcde");
System.out.println("s6:" + s6);
System.out.println("s6.length():" + s6.length());
System.out.println("--------------------------");
//字符串字面值"abc"也可以看成是一个字符串对象
String s7 = "abcde";
System.out.println("s7:"+s7);
System.out.println("s7.length():"+s7.length());
}
}
字符串的特点:一旦被赋值,就不能改变
public class StringDemo {
public static void main(String[] args) {
String s = "hello";
s += "world";
System.out.println("s:" + s); // helloworld,改变的是s,不是hello,hello在方法区里边的值和地址值都没有改变,拼接生成了一个新的地址值存放
}
}
String s = new String(“hello”)和String s = “hello”;的区别,前者会创建2个对象,后者创建1个对象
==:比较引用类型比较的是地址值是否相同
equals:比较引用类型默认也是比较地址值是否相同,而String类重写了equals()方法,比较的是内容是否相同
public class StringDemo2 {
public static void main(String[] args) {
String s1 = new String("hello");
String s2 = "hello";
System.out.println(s1 == s2);// false
System.out.println(s1.equals(s2));// true
}
}
字符串如果是变量相加,先开空间,在拼接
字符串如果是常量相加,是先加,然后在常量池找,如果有就直接返回,否则,就创建
public class StringDemo4 {
public static void main(String[] args) {
String s1 = "hello";
String s2 = "world";
String s3 = "helloworld";
System.out.println(s3 == s1 + s2);// false
System.out.println(s3.equals((s1 + s2)));// true
System.out.println(s3 == "hello" + "world");// false 这个我们错了,应该是true
System.out.println(s3.equals("hello" + "world"));// true
// 通过反编译看源码,我们知道这里已经做好了处理。
// System.out.println(s3 == "helloworld");
// System.out.println(s3.equals("helloworld"));
}
}
String类的判断功能
返回值 方法名 参数
boolean equals(Object obj):比较字符串的内容是否相同,区分大小写
boolean equalsIgnoreCase(String str):比较字符串的内容是否相同,忽略大小写
boolean contains(String str):判断大字符串中是否包含小字符串
boolean startsWith(String str):判断字符串是否以某个指定的字符串开头
boolean endsWith(String str):判断字符串是否以某个指定的字符串结尾
boolean isEmpty():判断字符串是否为空
注意:
字符串内容为空和字符串对象为空
String s = "";
String s = null;
public class StringDemo {
public static void main(String[] args) {
// 创建字符串对象
String s1 = "helloworld";
String s2 = "helloworld";
String s3 = "HelloWorld";
// boolean equals(Object obj):比较字符串的内容是否相同,区分大小写
System.out.println("equals:" + s1.equals(s2));
System.out.println("equals:" + s1.equals(s3));
System.out.println("-----------------------");
// boolean equalsIgnoreCase(String str):比较字符串的内容是否相同,忽略大小写
System.out.println("equals:" + s1.equalsIgnoreCase(s2));
System.out.println("equals:" + s1.equalsIgnoreCase(s3));
System.out.println("-----------------------");
// boolean contains(String str):判断大字符串中是否包含小字符串
System.out.println("contains:" + s1.contains("hello"));
System.out.println("contains:" + s1.contains("hw"));//需要连续的
System.out.println("-----------------------");
// boolean startsWith(String str):判断字符串是否以某个指定的字符串开头
System.out.println("startsWith:" + s1.startsWith("h"));
System.out.println("startsWith:" + s1.startsWith("hello"));
System.out.println("startsWith:" + s1.startsWith("world"));
System.out.println("-----------------------");
//boolean endsWith(String str):判断字符串是否以某个指定的字符串结尾
System.out.println("endsWith:"+s1.endsWith("world"));
System.out.println("endsWith:"+s1.endsWith("rld"));
System.out.println("endsWith:"+s1.endsWith("d"));
System.out.println("-----------------------");
// boolean isEmpty():判断字符串是否为空。
System.out.println("isEmpty:" + s1.isEmpty());
String s4 = "";
String s5 = null;
System.out.println("isEmpty:" + s4.isEmpty());
// NullPointerException
// System.out.println("isEmpty:" + s5.isEmpty());//s5对象都不存在,所以不能调用方法,空指针异常
}
}
//小案例,模拟登录,给三次机会,提示剩余次数,登录成功后可以开始玩猜数字小游戏
/*
* 分析:
* A:定义用户名和密码
* B:键盘录入用户名和密码
* C:比较用户名和密码
* 如果都相同,则登录成功
* 如果有一个不同,则登录失败
* D:给三次机会,用循环改进,最好用for循环
*/
public class StringDemo {
public static void main(String[] args) {
//系统定义用户名和密码
String name = "user1";
String password = "123456";
//用户输入用户名和密码
for (int i = 0; i < 3; i++) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名");
String name2 = sc.nextLine();
System.out.println("请输入密码");
String password2 = sc.nextLine();
if ((name.equals(name2)) &&(password.equals(password2))){
System.out.println("登录成功,开始猜数字小游戏");
CaiShuZi.start(); //定义了一个类来玩猜数字
break;
}else if ((2-i) == 0){
System.out.println("密码锁定,请联系管理员");
}else {
System.out.println("剩余" + (2 - i) + "次机会");
}
}
}
}
//猜数字小游戏类
mport java.util.Random;
import java.util.Scanner;
public class CaiShuZi {
private CaiShuZi(){} //屏蔽无参构造,不能使用对象来玩游戏
public static void start(){
Random r = new Random();
int num = r.nextInt(10)+1;
while(true){
System.out.println("请输入1-10之间的数");
Scanner sc = new Scanner(System.in);
int num1 = sc.nextInt();
if (num1 < num){
System.out.println("猜小了");
}else if (num1 > num){
System.out.println("猜大了");
}else {
System.out.println("猜对了");
break;
}
}
}
}
String类的获取功能
返回值 方法名 参数
int length():获取字符串的长度
char charAt(int index):获取指定索引位置的字符
int indexOf(int ch):返回指定字符在此字符串中第一次出现处的索引,为什么这里是int类型,而不是char类型,因为'a'和97其实都可以代表'a'
int indexOf(String str):返回指定字符串在此字符串中第一次出现处的索引
int indexOf(int ch,int fromIndex):返回指定字符在此字符串中从指定位置后第一次出现处的索引
int indexOf(String str,int fromIndex):返回指定字符串在此字符串中从指定位置后第一次出现处的索引
String substring(int start):从指定位置开始截取字符串,默认到末尾,包含strat这个位置(包左)
String substring(int start,int end):从指定位置开始到指定位置结束截取字符串,包含start但不包含end(包左不包右)
public class StringDemo {
public static void main(String[] args) {
// 定义一个字符串对象
String s = "helloworld";
// int length():获取字符串的长度。
System.out.println("s.length:" + s.length());
System.out.println("----------------------");
// char charAt(int index):获取指定索引位置的字符
System.out.println("charAt:" + s.charAt(7));
System.out.println("----------------------");
// int indexOf(int ch):返回指定字符在此字符串中第一次出现处的索引
System.out.println("indexOf:" + s.indexOf('l'));
System.out.println("----------------------");
// int indexOf(String str):返回指定字符串在此字符串中第一次出现处的索引
System.out.println("indexOf:" + s.indexOf("owo"));
System.out.println("----------------------");
// int indexOf(int ch,int fromIndex):返回指定字符在此字符串中从指定位置后第一次出现处的索引
System.out.println("indexOf:" + s.indexOf('l', 4));
System.out.println("indexOf:" + s.indexOf('k', 4)); // -1
System.out.println("indexOf:" + s.indexOf('l', 40)); // -1 代表错误
System.out.println("----------------------");
// int indexOf(String str,int fromIndex):返回指定字符串在此字符串中从指定位置后第一次出现处的索引
System.out.println("s.indexOf:"+s.indexOf('l',3));
System.out.println("----------------------");
// String substring(int start):从指定位置开始截取字符串,默认到末尾。包含start这个索引
System.out.println("substring:" + s.substring(5));
System.out.println("substring:" + s.substring(0));
System.out.println("----------------------");
// String substring(int start,intend):从指定位置开始到指定位置结束截取字符串,包括start索引但是不包end索引
System.out.println("substring:" + s.substring(3, 8));
System.out.println("substring:" + s.substring(0, s.length()));
}
}
/* 需求:从键盘获取一串字符串,统计该字符串中大写字母字符,小写字母字符,数字字符出现的次数(不考虑其他字符)
*
*分析:键盘录入
* 遍历字符,得到每一个字符
* charAt()和length() 结合得到
* 对大小写数字进行计数
*
**/
public class StringDemo {
public static void main(String[] args) {
//定义三个计数
int bigCount = 0;
int smallCount = 0;
int numCount = 0;
//创建对象
Scanner sc = new Scanner(System.in);
System.out.println("请输入一串包含大小写数字的字符串");
//获取键盘输入的赋值给s
String s = sc.nextLine();
for (int i = 0; i < s.length(); i++) {
//获取字符串的每一个字符
int ch = s.charAt(i);
//进行比较
if ((ch > 'a') && (ch < 'z')){
smallCount++;
}else if ((ch > 'A')&&(ch < 'Z')){
bigCount++;
}else if ((ch > '0')&&(ch < '9')){
numCount++;
}
}
System.out.println("大写字母有"+ bigCount +"个,小写字母有"+ smallCount +"个,数字有"+ numCount +"个");
}
}
String的转换功能
返回值 方法名 参数
byte[] getBytes():把字符串转换为字节数组,输出结果会是对应的ascii码值
char[] toCharArray():把字符串转换为字符数组
static String valueOf(char[] chs):把字符数组转成字符串
static String valueOf(int i):把int类型的数据转成字符串
注意:String类的valueOf方法可以把任意类型的数据转成字符串
String toLowerCase():把字符串转成小写
String toUpperCase():把字符串转成大写
String concat(String str):把字符串拼接
public class StringDemo {
public static void main(String[] args) {
// 定义一个字符串对象
String s = "HelloWorld";
// byte[] getBytes():把字符串转换为字节数组,输出结果会是数字,代表对应的ascii码值
byte[] bys = s.getBytes();
for (int x = 0; x < bys.length; x++) {
System.out.print(bys[x]+" ");
}
System.out.println();
System.out.println("----------------");
// char[] toCharArray():把字符串转换为字符数组
char[] chs = s.toCharArray();
for (int x = 0; x < chs.length; x++) {
System.out.print(chs[x]+" ");
}
System.out.println();
System.out.println("----------------");
// static String valueOf(char[] chs):把字符数组转成字符串
String ss = String.valueOf(chs);
System.out.println(ss);
System.out.println("----------------");
// static String valueOf(int i):把int类型的数据转成字符串
int i = 100;
String sss = String.valueOf(i);
System.out.println(sss);
System.out.println("----------------");
// String toLowerCase():把字符串转成小写,但不会改变原字符串
System.out.println("toLowerCase:" + s.toLowerCase());
System.out.println("s:" + s);
System.out.println("----------------");
// String toUpperCase():把字符串转成大写
System.out.println("toUpperCase:" + s.toUpperCase());
System.out.println("----------------");
// String concat(String str):把字符串拼接
String s1 = "hello";
String s2 = "world";
String s3 = s1 + s2;
String s4 = s1.concat(s2);
System.out.println("s3:"+s3);
System.out.println("s4:"+s4);
}
import java.util.Locale;
import java.util.Scanner;
/*
* 需求:键盘输入一个字符串,把首字母大写,其他字母小写
* 分析:
* 第一步:获取字符串的第一个位置的字符
* 第二步:获取字符串其他位置的字符
* 第三步:把第一步获取的大写
* 第四步:把第二步获取的小写
* 第五步:把第三步第四步拼接
* */
public class StringDemo {
public static void main(String[] args) {
//创建对象
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
String str = sc.nextLine();
//截取字符串
//第一个位置的字符,从0到1,包左不包右
String first = str.substring(0,1);
//从1到末尾
String str1 = str.substring(1);
//变为大写
first = first.toUpperCase(Locale.ROOT);
//变为小写
str1 = str1.toLowerCase(Locale.ROOT);
//拼接
str = first + str1;
System.out.println(str);
}
}
String类的其他功能
替换功能
String replace(char old,char new),用new替换old
String replace(String old,String new)用new替换old
去除字符串两空格
String trim()
按字典顺序比较两个字符串
int compareTo(String str),区分大小写,按位比较,第一位相同就比较第二位,比较处不同后用前边的Ascii码减去后边的Ascii码
int compareToIgnoreCase(String str),不去分大小写,同上
public class StringDemo {
public static void main(String[] args) {
// 替换功能
String s1 = "helloworld";
String s2 = s1.replace('l', 'k');
String s3 = s1.replace("owo", "asdasdasdasd"); //替换不用管是否相同数量
System.out.println("s1:" + s1);
System.out.println("s2:" + s2);
System.out.println("s3:" + s3);
System.out.println("---------------");
// 去除字符串两空格
String s4 = " hello world ";
String s5 = s4.trim();
System.out.println("s4:" + s4 + "---");
System.out.println("s5:" + s5 + "---");
// 按字典顺序比较两个字符串
String s6 = "hello";
String s7 = "hello";
String s8 = "abc";
String s9 = "xyz";
System.out.println(s6.compareTo(s7));// 0代表相同
System.out.println(s6.compareTo(s8));// 7代表Ascii码比s6的小7
System.out.println(s6.compareTo(s9));// -16
}
}
StringBuffer
线程安全的可变字符串
StringBuffer和String的区别
前者长度和内容可变,后者不可变
如果使用前者做字符串的拼接,不会浪费太多的资源
StringBuffer的构造方法:
public StringBuffer():无参构造方法
public StringBuffer(int capacity):指定容量的字符串缓冲区对象
public StringBuffer(String str):指定字符串内容的字符串缓冲区对象
StringBuffer的方法:
public int capacity():返回当前容量 理论值
public int length():返回长度(字符数) 实际值
public class StringBufferDemo {
public static void main(String[] args) {
// public StringBuffer():无参构造方法
StringBuffer sb = new StringBuffer();
System.out.println("sb:" + sb);
System.out.println("sb.capacity():" + sb.capacity());
System.out.println("sb.length():" + sb.length());
System.out.println("--------------------------");
// public StringBuffer(int capacity):指定容量的字符串缓冲区对象
StringBuffer sb2 = new StringBuffer(50);
System.out.println("sb2:" + sb2);
System.out.println("sb2.capacity():" + sb2.capacity());
System.out.println("sb2.length():" + sb2.length());
System.out.println("--------------------------");
// public StringBuffer(String str):指定字符串内容的字符串缓冲区对象
StringBuffer sb3 = new StringBuffer("hello");
System.out.println("sb3:" + sb3);
System.out.println("sb3.capacity():" + sb3.capacity());
System.out.println("sb3.length():" + sb3.length());
}
}
StringBuffer的添加功能
修饰符 返回值 方法名 参数列表
public StringBuffer append(String str) 可以把任意类型数据添加到字符串缓冲区里面,并返回字符串缓冲区本身
public StringBuffer insert(int offset,String str) 在指定位置把任意类型的数据插入到字符串缓冲区里面,并返回字符串缓冲区本身
public class StringBufferDemo {
public static void main(String[] args) {
// 创建字符串缓冲区对象
StringBuffer sb = new StringBuffer();
// public StringBuffer append(String str)
// StringBuffer sb2 = sb.append("hello");
// System.out.println("sb:" + sb);
// System.out.println("sb2:" + sb2); //sb1和sb2返回的结果一样,因为StringBuffer相当于一个杯子,返回字符串缓冲区本身
// System.out.println(sb == sb2); // true
// 一步一步的添加数据
// sb.append("hello");
// sb.append(true);
// sb.append(12);
// sb.append(34.56);
// 链式编程,要求返回的是一个对象,可以继续执行后边的方法
sb.append("hello").append(true).append(12).append(34.56);
System.out.println("sb:" + sb);
// public StringBuffer insert(int offset,Stringstr) 在指定位置把任意类型的数据插入到字符串缓冲区里面,并返回字符串缓冲区本身
sb.insert(5, "world"); //从第五个位置插入,第五个位置的往后移
System.out.println("sb:" + sb);
}
}
StringBuffer的删除功能
修饰符 返回值 方法名 参数列表
public StringBuffer deleteCharAt(int index) 删除指定位置的字符,并返回本身
public StringBuffer delete(int start,int end) 删除从指定位置开始指定位置结束的内容,并返回本身(包含start,不包含end,包左不包右)
public class StringBufferDemo {
public static void main(String[] args) {
// 创建对象
StringBuffer sb = new StringBuffer();
// 添加功能
sb.append("hello").append("world").append("java");
System.out.println("sb:" + sb);
// public StringBuffer deleteCharAt(int index) 删除指定位置的字符,并返回本身
// 需求:我要删除e这个字符
// sb.deleteCharAt(1);
// 需求:我要删除第一个l这个字符
// sb.deleteCharAt(1); //因为返回他本身
// public StringBuffer delete(int start,int end) 删除从指定位置开始指定位置结束的内容,并返回本身
// 需求:我要删除world这个字符串
// sb.delete(5, 10); //包左不包右
// 需求:我要删除所有的数据
sb.delete(0, sb.length()); //包左不包右
System.out.println("sb:" + sb);
}
}
StringBuffer的替换功能
修饰符 返回值 方法名 参数列表
public StringBuffer replace(int start,int end,String str) 从start开始到end用str替换,包左不包右
public class StringBufferDemo {
public static void main(String[] args) {
// 创建字符串缓冲区对象
StringBuffer sb = new StringBuffer();
// 添加数据
sb.append("hello");
sb.append("world");
sb.append("java");
System.out.println("sb:" + sb);
// public StringBuffer replace(int start,int end,String
// str):从start开始到end用str替换
// 需求:我要把world这个数据替换为"节日快乐"
sb.replace(5, 10, "节日快乐");
System.out.println("sb:" + sb);
}
}
StringBuffer的反转功能
修饰符 返回值 方法名
public StringBuffer reverse() 将字符串反转
public class StringBufferDemo {
public static void main(String[] args) {
// 创建字符串缓冲区对象
StringBuffer sb = new StringBuffer();
// 添加数据
sb.append("界世好你");
System.out.println("sb:" + sb);
// public StringBuffer reverse()
sb.reverse();
System.out.println("sb:" + sb);
}
}
StringBuffer的截取功能
修饰符 返回值 方法名 参数列表
public String substring(int start) 截取从start开始到末尾的字符,返回字符串类型
public String substring(int start,int end) 截取从start开始到end结束的字符,返回字符串类型(包左不包右)
注意返回值类型不再是StringBuffer本身了
public class StringBufferDemo {
public static void main(String[] args) {
// 创建字符串缓冲区对象
StringBuffer sb = new StringBuffer();
// 添加元素
sb.append("hello").append("world").append("java");
System.out.println("sb:" + sb);
// 截取功能
// public String substring(int start)
String s = sb.substring(5);
System.out.println("s:" + s);
System.out.println("sb:" + sb);
// public String substring(int start,int end)
String ss = sb.substring(5, 10);
System.out.println("ss:" + ss);
System.out.println("sb:" + sb);
}
}
String和StringBuffer的相互转换
A -- B的转换,我们把A转换为B,其实是为了使用B的功能
B -- A的转换,我们可能要的结果是A类型,所以还得转回来
public class StringBufferTest {
public static void main(String[] args) {
// String -- StringBuffer
String s = "hello";
// 注意:不能把字符串的值直接赋值给StringBuffer
// StringBuffer sb = "hello";
// StringBuffer sb = s;
// 方式1:通过构造方法
StringBuffer sb = new StringBuffer(s);
// 方式2:通过append()方法
StringBuffer sb2 = new StringBuffer();
sb2.append(s);
System.out.println("sb:" + sb);
System.out.println("sb2:" + sb2);
System.out.println("---------------");
// StringBuffer -- String
StringBuffer buffer = new StringBuffer("java");
// String(StringBuffer buffer)
// 方式1:通过构造方法
String str = new String(buffer);
// 方式2:通过toString()方法
String str2 = buffer.toString();
System.out.println("str:" + str);
System.out.println("str2:" + str2);
}
}
/*
* 把数组拼接成一个字符串
*/
public class StringBufferTest2 {
public static void main(String[] args) {
// 定义一个数组
int[] arr = { 44, 33, 55, 11, 22 };
// 定义功能
// 方式1:用String做拼接的方式
String s1 = arrayToString(arr);
System.out.println("s1:" + s1);
// 方式2:用StringBuffer做拼接的方式
String s2 = arrayToString2(arr);
System.out.println("s2:" + s2);
}
// 用StringBuffer做拼接的方式
public static String arrayToString2(int[] arr) {
StringBuffer sb = new StringBuffer();
sb.append("[");
for (int x = 0; x < arr.length; x++) {
if (x == arr.length - 1) {
sb.append(arr[x]);
} else {
sb.append(arr[x]).append(", ");
}
}
sb.append("]");
return sb.toString();
}
// 用String做拼接的方式,会在方法区生成多个内存空间存储,浪费空间效率不高,用StringBuffer改进
public static String arrayToString(int[] arr) {
String s = "";
s += "[";
for (int x = 0; x < arr.length; x++) {
if (x == arr.length - 1) {
s += arr[x];
} else {
s += arr[x];
s += ", ";
}
}
s += "]";
return s;
}
}
public class StringBufferDemo {
/*
* 需求:反转字符串
* 分析:对字符串进行反转,但是StringBuffer中有反转功能
* 先将字符串转换为StringBuffer
* 再将StringBuffer反转
* 最后将StringBuffer转换为字符串
* */
public static void main(String[] args) {
//定义一个需要反转的字符串
String str = "123456";
//将字符串转换为StringBuffer
StringBuffer sb = new StringBuffer();
sb.append(str);
sb.reverse();
//再将StringBuffer转换为String
str = sb.toString();
System.out.println(str);
}
}
import java.util.Scanner;
public class StringBufferDemo {
/*
* 需求:判断字符串是否对称,例:abc不对称,abba,aba对称
*分析:利用StringBuffer的反转功能,看是否和之前的一样
*
* */
public static void main(String[] args) {
//创建键盘输入对象
Scanner sc = new Scanner(System.in);
System.out.println("情输入待判断的字符串");
String str = sc.nextLine();
System.out.println(isSame(str));
System.out.println(isSame2(str));
}
//定义判断方法
public static boolean isSame(String str){
StringBuffer sb = new StringBuffer();
//将字符串转为StringBuffer
sb.append(str);
//将StringBuffer反转
sb.reverse();
//再将StringBuffer转换为字符串
String sb1 = sb.toString();
//再将反转后的与源字符串进行比较
boolean flag = sb1.equals(str);
return flag;
}
public static boolean isSame2(String str){
//相当于isSame,链式编程
return new StringBuffer(str).reverse().toString().equals(str);
}
}
StringBuilder
是非同步,一般用于单线程,速度就比StringBuffer快
和StringBuffer用法一样
String,StringBuffer,StringBuilder的区别
String是内容不可变的,而StringBuffer,StringBuilder都是内容可变的
StringBuffer是同步的,数据安全,效率低;StringBuilder是不同步的,数据不安全,效率高
StringBuffer和数组的区别
二者都可以看出是一个容器,装其他的数据,但是StringBuffer的数据最终是一个字符串数据,而数组可以放置多种数据,但必须是同一种数据类型的
String和StringBuffer作为形式参数问题
形式参数:
基本类型:形式参数的改变不影响实际参数
引用类型:形式参数的改变直接影响实际参数
注意:
String作为参数传递,效果和基本类型作为参数传递是一样的
Day13
数组的排序和查找
冒泡排序
相邻元素两两比较,大的往后放,第一次完毕,最大值出现在了最大索引处
public class ArrayDemo {
public static void main(String[] args) {
// 定义一个数组
int[] arr = { 24, 69, 80, 57, 13 };
System.out.println("排序前:");
printArray(arr);
/*for (int x = 0; x < arr.length - 1; x++) {
for (int y = 0; y < arr.length - 1 - x; y++) {
if (arr[y] > arr[y + 1]) {
int temp = arr[y];
arr[y] = arr[y + 1];
arr[y + 1] = temp;
}
}
}
System.out.println("排序后:");
printArray(arr);
*/
//由于我可能有多个数组要排序,所以我要写成方法
bubbleSort(arr);
System.out.println("排序后:");
printArray(arr);
}
//冒泡排序代码
public static void bubbleSort(int[] arr){
for (int x = 0; x < arr.length - 1; x++) {
for (int y = 0; y < arr.length - 1 - x; y++) {
if (arr[y] > arr[y + 1]) {
int temp = arr[y];
arr[y] = arr[y + 1];
arr[y + 1] = temp;
}
}
}
}
// 遍历功能
public static void printArray(int[] arr) {
System.out.print("[");
for (int x = 0; x < arr.length; x++) {
if (x == arr.length - 1) {
System.out.print(arr[x]);
} else {
System.out.print(arr[x] + ", ");
}
}
System.out.println("]");
}
}
选择排序
从0索引开始,依次和后面元素比较,小的往前放,第一次完毕,最小值出现在了最小索引处
public class ArrayDemo {
public static void main(String[] args) {
// 定义一个数组
int[] arr = { 24, 69, 80, 57, 13 };
System.out.println("排序前:");
printArray(arr);
/*
//通过观察发现代码的重复度太高,所以用循环改进
for(int x=0; x<arr.length-1; x++){
for(int y=x+1; y<arr.length; y++){
if(arr[y] <arr[x]){
int temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
}
}
System.out.println("排序后:");
printArray(arr);
*/
//用方法改进
selectSort(arr);
System.out.println("排序后:");
printArray(arr);
}
public static void selectSort(int[] arr){
for(int x=0; x<arr.length-1; x++){
for(int y=x+1; y<arr.length; y++){
if(arr[y] <arr[x]){
int temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
}
}
}
// 遍历功能
public static void printArray(int[] arr) {
System.out.print("[");
for (int x = 0; x < arr.length; x++) {
if (x == arr.length - 1) {
System.out.print(arr[x]);
} else {
System.out.print(arr[x] + ", ");
}
}
System.out.println("]");
}
}
二分查找
查找:
基本查找:数组元素无序(从头找到尾)
二分查找(折半查找):数组元素有序
/*
* 需求:键盘获取一个整型数组,进行二分查找
* 分析:
* 进行二分查找的前提是有序数组,先对数组进行排序,在进行查找
* */
public class ArrDemo {
public static void main(String[] args) {
System.out.println("请输入八个整数");
Scanner sc = new Scanner(System.in);
int[] arr = new int[8];
for (int i = 0; i < arr.length; i++) {
arr[i] = sc.nextInt();
}
print(arr);
arr = maoPao(arr);
print(arr);
System.out.println("请输入你想找的数");
int num =sc.nextInt();
int index = erFen(arr,num);
System.out.println("索引是"+index);
}
//遍历数组的方法
public static void print(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
//对数组进行排序
public static int[] maoPao(int[] arr) {
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length - 1; j++) {
if (arr[j] > arr[j + 1]) {
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
return arr;
}
//二分查找
public static int erFen(int[] arr, int num) {
int max = arr.length - 1;
int min = 0;
int mid = (max + min) / 2;
while (arr[mid] != num) {
if (arr[mid] > num) {
max = mid - 1;
} else if (arr[mid] < num) {
min = mid + 1;
}
mid = (max + min) / 2;
if (min > max){
return -1;
}
}
return mid;
}
}
注意:上面这种做法是有问题的
因为数组本身是无序的,所以这种情况下的查找不能使用二分查找,所以你先排序了,但是你排序的时候已经改变了我最原始的元素索引
Arrays
针对数组操作的工具类:比如排序和查找
修饰符 返回值 方法名 参数列表(static修饰,静态的,通过类名调用)
public static String toString(int[] a) 把任意类型数组数组转成字符串,以int举例
public static void sort(int[] a) 对任意类型数组进行排序
public static int binarySearch(int[] a,int key) 二分查找
public class ArraysDemo {
public static void main(String[] args) {
// 定义一个数组
int[] arr = { 24, 69, 80, 57, 13 };
// public static String toString(int[] a) 把数组转成字符串
System.out.println("排序前:" + Arrays.toString(arr));
// public static void sort(int[] a) 对数组进行排序
Arrays.sort(arr);
System.out.println("排序后:" + Arrays.toString(arr));
// [13, 24, 57, 69, 80]
// public static int binarySearch(int[] a,int key) 二分查找
System.out.println("binarySearch:" + Arrays.binarySearch(arr, 57));
System.out.println("binarySearch:" + Arrays.binarySearch(arr, 577));
}
}
Integer
修饰符 返回值 方法名 参数列表(静态的,通过类名直接调用)
public static String toBinaryString(int i) 将十进制转换为二进制
public static String toOctalString(int i) 将十进制转换为八进制
public static String toHexString(int i) 将十进制转换为十六进制
十进制到其他进制
public static String toString(int i,int radix)进制的范围:2-36
其他进制到十进制
public static int parseInt(String s,int radix)
public static final int MAX_VALUE Int的最大范围
public static final int MIN_VALUE Int的最小范围
包装类类型
为了对基本数据类型进行更多的操作,更方便的操作,Java就针对每一种基本数据类型提供了对应的类类型,包装类类型
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean
Integer类的构造方法
public Integer(int i)
public Integer(String s)
注意:这个字符串必须是由数字字符组成
public class IntegerDemo {
public static void main(String[] args) {
// 方式1
int i = 100;
Integer ii = new Integer(i);
System.out.println("ii:" + ii);
// 方式2
String s = "100";
// NumberFormatException
// String s = "abc";
Integer iii = new Integer(s);
System.out.println("iii:" + iii);
}
}
int类型和String类型的相互转换
int类型和String类型的相互转换
int -- String
String.valueOf(int i) 将int类型的转换成String类型
String -- int
Integer.parseInt(String s) 将String类型转换成Int类型
要想将字符串类型转换成基本数据类型,就去找基本类型的包装类里的parselnt
public class IntegerDemo {
public static void main(String[] args) {
// int -- String
int number = 100;
// 方式1,直接拼接
String s1 = "" + number;
System.out.println("s1:" + s1);
// 方式2,调用String类的valueOf方法
String s2 = String.valueOf(number);
System.out.println("s2:" + s2);
// 方式3
// int -- Integer -- String
Integer i = new Integer(number);
String s3 = i.toString();
System.out.println("s3:" + s3);
// 方式4
// public static String toString(int i)
String s4 = Integer.toString(number);
System.out.println("s4:" + s4);
System.out.println("-----------------");
// String -- int
String s = "100";
// 方式1
// String -- Integer -- int
Integer ii = new Integer(s);
// public int intValue()
int x = ii.intValue();
System.out.println("x:" + x);
//方式2
//public static int parseInt(String s)
int y = Integer.parseInt(s);
System.out.println("y:"+y);
}
}
JDK5的新特性
自动装箱:把基本类型转换为包装类类型
自动拆箱:把包装类类型转换为基本类型
注意一个小问题:
在使用时,Integer x = null;代码就会出现NullPointerException空指针异常,建议先判断是否为null,然后再使用
public class IntegerDemo {
public static void main(String[] args) {
// 定义了一个int类型的包装类类型变量i
// Integer i = new Integer(100);
Integer ii = 100;
ii += 200;
System.out.println("ii:" + ii);
// 通过反编译后的代码
// Integer ii = Integer.valueOf(100); //自动装箱
// ii = Integer.valueOf(ii.intValue() + 200); //自动拆箱,再自动装箱
// System.out.println((new StringBuilder("ii:")).append(ii).toString());
Integer iii = null;
// NullPointerException
if (iii != null) {
iii += 1000;
System.out.println(iii);
}
}
}
Character 类
在对象中包装一个基本类型 char 的值,此外,该类提供了几种方法,以确定字符的类别(小写字母,数字,等等),并将字符从大写转换成小写,反之亦然
构造方法:
Character(char value)
成员方法:
public static boolean isUpperCase(char ch):判断给定的字符是否是大写字符
public static boolean isLowerCase(char ch):判断给定的字符是否是小写字符
public static boolean isDigit(char ch):判断给定的字符是否是数字字符
public static char toUpperCase(char ch):把给定的字符转换为大写字符
public static char toLowerCase(char ch):把给定的字符转换为小写字符
* 统计一个字符串中大写字母字符,小写字母字符,数字字符出现的次数(不考虑其他字符)
/*
* 分析:
* A:定义三个统计变量。
* int bigCont=0;
* int smalCount=0;
* int numberCount=0;
* B:键盘录入一个字符串。
* C:把字符串转换为字符数组。
* D:遍历字符数组获取到每一个字符
* E:判断该字符是
* 大写 bigCount++;
* 小写 smalCount++;
* 数字 numberCount++;
* F:输出结果即可
*/
public class CharacterTest {
public static void main(String[] args) {
// 定义三个统计变量。
int bigCount = 0;
int smallCount = 0;
int numberCount = 0;
// 键盘录入一个字符串。
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String line = sc.nextLine();
// 把字符串转换为字符数组。
char[] chs = line.toCharArray();
// 历字符数组获取到每一个字符
for (int x = 0; x < chs.length; x++) {
char ch = chs[x];
// 判断该字符
if (Character.isUpperCase(ch)) {
bigCount++;
} else if (Character.isLowerCase(ch)) {
smallCount++;
} else if (Character.isDigit(ch)) {
numberCount++;
}
}
// 输出结果即可
System.out.println("大写字母:" + bigCount + "个");
System.out.println("小写字母:" + smallCount + "个");
System.out.println("数字字符:" + numberCount + "个");
}
}
Day14
对数字进行校验
/*
* 需求:检验数字,长度在5-15之间,且不能以0开头的一串数字
* 分析:
* 键盘获取一串数字
* 判断长度是否是5-15之间
* 判断是否以0开头
* 判断整体是不是数字
* */
public class Checkdigit {
public static void main(String[] args) {
//创建对象
Scanner sc = new Scanner(System.in);
String num = sc.nextLine();
boolean falg = checkNum(num);
if (falg){
System.out.println("输入正确");
}else
System.out.println("输入有误");
}
//定义方法判断
public static boolean checkNum(String num){
//定义判断位
boolean flag = true;
//判断长度是不是在5-15之间
if ((num.length()>= 5) && (num.length()<= 15)){
//判断首字符是否为0
if (!(num.startsWith("0"))){
//判断输入的是否全是数字
for (int i = 0; i < num.length(); i++) {
//获取每一位的字符
char ch = num.charAt(i);
//判断字符是否为数字
flag = Character.isDigit(ch);
break;
}
}else
flag = false;
}else
flag = false;
return flag;
}
}
正则表达式
格式:String regex = " "; 双引号里边的是规则
字符
x 字符 x,举例:'a'表示字符a
\ 反斜线字符 反斜杠代表转义,再来一个反斜杠代表反斜杠
\n 新行(换行)符 ('\u000A')
\r 回车符 ('\u000D')
字符类
[abc] a、b 或 c(简单类) 表示是a或是b或是c,三个选一个
[^abc] 任何字符,除了 a、b 或 c(否定)
[a-zA-Z] a到 z 或 A到 Z,两头的字母包括在内(范围)所有的大小写字符
[0-9] 0到9的字符都包括
预定义字符类
. 任何字符, .转义一下表示字符.
\d 数字:[0-9]
\w 单词字符:[a-zA-Z_0-9],在正则表达式里面组成单词的东西必须有这些东西组成
边界匹配器
^ 行的开头
$ 行的结尾
\b 单词边界,就是不是单词字符的地方
举例:hello world?haha;xixi(空格 ?;表示单词边界)
Greedy 数量词
X? X,一次或一次也没有,零次或一次
X* X,零次或多次,包括一次
X+ X,一次或多次,至少一次
X{n} X,恰好 n 次
X{n,} X,至少 n 次
X{n,m} X,至少 n 次,但是不超过 m 次
用正则表达式改进数字校验案例
/*
* 需求:检验数字,长度在5-15之间,且不能以0开头的一串数字
* 分析:
* 键盘获取一串数字
* 判断长度是否是5-15之间
* 判断是否以0开头
* 判断整体是不是数字
* */
public class Checkdigit {
public static void main(String[] args) {
//创建对象
Scanner sc = new Scanner(System.in);
String num = sc.nextLine();
boolean falg = checkNum(num);
if (falg){
System.out.println("输入正确");
}else
System.out.println("输入有误");
}
//定义方法判断
public static boolean checkNum(String num){
//定义判断位
boolean flag = true;
flag = num.matches("[1-9][0-9]{4,14}");
//[1-9]表示第一位从1-9
//[0-9]表示除了第一位其他的是0-9的数字
//{4,14}表示0-9的范围是4~14之间,[1-9]没有跟表示长度的,默认1位,4~14 + 1 5~15的范围
return flag;
//可以在改进,matches返回的是一个布尔值的类型,可以直接return返回
//return num.matches("[1-9][0-9]{4,14}");
}
}
正则表达式的应用
判断功能
String类的public boolean matches(String regex)判断字符串是否满足正则表达式(regex规则)的规则,返回布尔值类型
/*
*
* 需求:
* 判断手机号码是否满足要求?
*
* 分析:
* A:键盘录入手机号码
* B:定义手机号码的规则
* 13436975980
* 13688886868
* 13866668888
* 13456789012
* 13123456789
* 18912345678
* 18886867878
* 18638833883
* C:调用功能,判断即可
* D:输出结果
*/
public class RegexDemo {
public static void main(String[] args) {
//键盘录入手机号码
Scanner sc = new Scanner(System.in);
System.out.println("请输入你的手机号码:");
String phone = sc.nextLine();
//定义手机号码的规则
String regex = "1[38]\\d{9}";
//调用功能,判断即可
boolean flag = phone.matches(regex);
//输出结果
System.out.println("flag:"+flag);
}
}
分割功能
String类的public String[] split(String regex),根据给定正则表达式(regex规则)的匹配拆分此字符串
/*
* 分割功能练习
*/
public class RegexDemo2 {
public static void main(String[] args) {
// 定义一个字符串
String s1 = "aa,bb,cc";
// 直接分割
String[] str1Array = s1.split(",");
for (int x = 0; x < str1Array.length; x++) {
System.out.println(str1Array[x]);
}
System.out.println("---------------------");
String s2 = "aa.bb.cc";
String[] str2Array = s2.split("\\."); //.代表所有字符,所以需要转义
for (int x = 0; x < str2Array.length; x++) {
System.out.println(str2Array[x]);
}
System.out.println("---------------------");
String s3 = "aa bb cc";
String[] str3Array = s3.split(" +"); //表示一个及以上的空格
for (int x = 0; x < str3Array.length; x++) {
System.out.println(str3Array[x]);
}
System.out.println("---------------------");
//硬盘上的路径,我们应该用\\替代\
String s4 = "E:\\JavaSE\\day14\\avi";
String[] str4Array = s4.split("\\\\");// s4里边的\\需要用\\\\代替
for (int x = 0; x < str4Array.length; x++) {
System.out.println(str4Array[x]);
}
System.out.println("---------------------");
}
}
/*
* 需求:我有一个字符串“97 28 63 12 88”
* 想要输出为“12 28 63 88 97”
* 分析:输出的是排序后的,但是不能对字符串进行排序,所以要将字符串转换为整型数组
* 可以用分割得到每一个位置的数存放到数组中
* 在进行排序
* 在组装成字符串
* 输出
* */
public class RegexTest {
public static void main(String[] args) {
//定义字符串
String str = "97 28 63 12 88";
//定义规则
String regex = " ";
//分割字符串String类的public String[] split(String regex)
String [] strings = str.split(regex);
//定义整型数组接收字符串数组的值,用字符串的长度定义整型数组的长度
int [] arr = new int[strings.length];
for (int i = 0; i < strings.length; i++) {
//Integer.parseInt(String s)将String转换成int类型
arr[i] = Integer.parseInt(strings[i]);
}
//对数组arr进行排序
//冒泡排序
/*for (int i = 0; i < arr.length-1; i++) {
for (int j = 0; j < arr.length-1-i; j++) {
if (arr[j] > arr[j+1]){
int tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
}*/
Arrays.sort(arr); //对数组进行排序,底层逻辑是快速排序
//将int转成String
/*String s = "";
for (int i = 0; i < arr.length; i++) {
s += arr[i]+" ";
}*/
StringBuilder sb = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
//先添加数在添加空格
sb.append(arr[i]).append(" ");
}
//将sb转成string在去除空格
String s = sb.toString().trim();
System.out.println(s);
}
}
替换功能
String类的public String replaceAll(String regex,String replacement),使用给定的 replacement 替换此字符串所有匹配给定的正则表达式(regex规则)的子字符串
/*
*需求:定义一个字符串,不允许出现数字,出现的话用*替换
*/
public class RegexDemo {
public static void main(String[] args) {
// 定义一个字符串
String s = "helloqq12345worldkh622112345678java";
// 我要去除所有的数字,用*给替换掉
// String regex = "\\d+"; //一个或多个数字用一个*代替
// String regex = "\\d"; //每一个数字用*代替
//String ss = "*"; //用*代替数字
// 直接把数字去掉
String regex = "\\d+";
String ss = "";
String result = s.replaceAll(regex, ss); //将字符串s中符合regex规则的替换成ss
System.out.println(result);
}
}
获取功能
Pattern(模式)和Matcher(匹配器)类的使用
模式和匹配器的基本使用顺序
// 把正则表达式("ab")编译成模式对象
Pattern p = Pattern.compile("ab");
// 通过模式对象得到匹配器对象,这个时候需要的是被匹配的字符串("aaaaab")
Matcher m = p.matcher("aaaaab");
// 调用匹配器对象的功能
boolean b = m.matches();
System.out.println(b);
/*
* 获取下面这个字符串中由三个字符组成的单词
* da jia ting wo shuo,jin tian yao xia yu,bu shang wan zi xi,gao xing bu?
*/
public class RegexDemo2 {
public static void main(String[] args) {
// 定义字符串
String s = "da jia ting wo shuo,jin tian yao xia yu,bu shang wan zi xi,gao xing bu?";
// 规则,三个字符的长度,左右都是单词边界
String regex = "\\b\\w{3}\\b";
// 把规则编译成模式对象
Pattern p = Pattern.compile(regex);
// 通过模式对象得到匹配器对象
Matcher m = p.matcher(s);
// 调用匹配器对象的功能
// 通过find方法就是查找有没有满足条件的子串
// public boolean find()
// boolean flag = m.find();
// System.out.println(flag);
// // 如何得到值呢?
// // public String group()
// String ss = m.group();
// System.out.println(ss);
//
// // 再来一次
// flag = m.find();
// System.out.println(flag);
// ss = m.group();
// System.out.println(ss);
while (m.find()) {
System.out.println(m.group());
}
// 注意:一定要先find(),然后才能group()
// IllegalStateException: No match found
// String ss = m.group();
// System.out.println(ss);
}
}
Math类
用于数学运算的类
成员变量:
public static final double PI 圆周率
public static final double E 自然对数
成员方法:
public static int abs(int a):绝对值
public static double ceil(double a):向上取整就是有小数部分的去掉小数,整数加一,例12.34 和12.56都是13.0
public static double floor(double a):向下取整就是有小数部分的去掉小数,例12.34 和12.56都是12.0
public static int max(int a,int b):最大值
public static int max(int a,int b):最小值
public static double pow(double a,double b):a的b次幂
public static double random():随机数 (0.0,1.0),包左不包右
public static int round(float a) 对float四舍五入,返回int
public static long round(double a) 对double四舍五入,返回long
public static double sqrt(double a):正平方根
public class MathDemo {
public static void main(String[] args) {
// public static final double PI
System.out.println("PI:" + Math.PI);
// public static final double E
System.out.println("E:" + Math.E);
System.out.println("--------------");
// public static int abs(int a):绝对值
System.out.println("abs:" + Math.abs(10));
System.out.println("abs:" + Math.abs(-10));
System.out.println("--------------");
// public static double ceil(double a):向上取整
System.out.println("ceil:" + Math.ceil(12.34));
System.out.println("ceil:" + Math.ceil(12.56));
System.out.println("--------------");
// public static double floor(double a):向下取整
System.out.println("floor:" + Math.floor(12.34));
System.out.println("floor:" + Math.floor(12.56));
System.out.println("--------------");
// public static int max(int a,int b):最大值
System.out.println("max:" + Math.max(12, 23));
// 需求:我要获取三个数据中的最大值
// 方法的嵌套调用
System.out.println("max:" + Math.max(Math.max(12, 23), 18));
// 需求:我要获取四个数据中的最大值
System.out.println("max:"
+ Math.max(Math.max(12, 78), Math.max(34, 56)));
System.out.println("--------------");
// public static double pow(double a,double b):a的b次幂
System.out.println("pow:" + Math.pow(2, 3));
System.out.println("--------------");
// public static double random():随机数 [0.0,1.0)
System.out.println("random:" + Math.random());
// 获取一个1-100之间的随机数
System.out.println("random:" + ((int) (Math.random() * 100) + 1));
System.out.println("--------------");
// public static int round(float a) 四舍五入(参数为double的自学)
System.out.println("round:" + Math.round(12.34f));
System.out.println("round:" + Math.round(12.56f));
System.out.println("--------------");
//public static double sqrt(double a):正平方根
System.out.println("sqrt:"+Math.sqrt(4));
}
}
获取指定范围内的随机数
import java.util.Random;
import java.util.Scanner;
/*
* 需求:获取指定范围内的随机数,例获取100-200之间的随机数
* 分析:键盘获取开始和结束的范围
* 定义一个方法找到开始和结束范围内的随机数
* 输出随机数
* */
public class RandomTest {
public static void main(String[] args) {
//键盘获取开始和结束的范围
Scanner sc = new Scanner(System.in);
System.out.println("请输入开始的范围");
int start = sc.nextInt();
System.out.println("请输入结束的范围");
int end = sc.nextInt();
//多调用几次看是否在范围内
for (int i = 0; i < 100; i++) {
System.out.println(RandowNum(start, end));
}
}
//定义方法,明确返回值类型int,明确参数列表start,end
public static int RandowNum(int start, int end) {
Random r = new Random();
//结束位置减去开始位置在加上开始的位置加一
//例:100-300 300-100 + 100
//就是 0-200之间 +100 就是100 - 300
int i = r.nextInt(end - start) + start + 1;
return i;
}
}
Random类
产生随机数的类
构造方法:
public Random():没有给种子,用的是默认种子,是当前时间的毫秒值
public Random(long seed):给出指定的种子
注意给定种子后,每次得到的随机数是相同的
成员方法:
public int nextInt():返回的是int范围内的随机数
public int nextInt(int n):返回的是[0,n)范围的内随机数
System类
包含一些有用的类字段和方法,它不能被实例化。
方法:
public static void gc():运行垃圾回收器
public static void exit(int status)终止当前正在运行的 Java 虚拟机。参数用作状态码;根据惯例,非 0 的状态码表示异常终止
public static long currentTimeMillis()返回以毫秒为单位的当前时间,可以用来统计程序运行多少秒
public static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length)从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束(从原数组src的srcPos位置开始,复制到目标数组dest的destPos位置.复制length个,会覆盖目标数组位置的数)
//统计程序运行时间
long start = System.currentTimeMillis();
for (int x = 0; x < 100000; x++) {
System.out.println("hello" + x);
}
long end = System.currentTimeMillis();
System.out.println("共耗时:" + (end - start) + "毫秒");
BigInteger类
可以让超过Integer范围(-2147483648 至 2147483647)内的数据进行运算
构造方法:
BigInteger(String val)
BigInteger bi = new BigInteger("2147483648"); //超过Integer范围
System.out.println("bi:" + bi);
成员方法
public BigInteger add(BigInteger val):加
public BigInteger subtract(BigInteger val):减
public BigInteger multiply(BigInteger val):乘
public BigInteger divide(BigInteger val):除
public BigInteger[] divideAndRemainder(BigInteger val):返回商和余数的数组
public class BigIntegerDemo {
public static void main(String[] args) {
BigInteger bi1 = new BigInteger("100");
BigInteger bi2 = new BigInteger("50");
// public BigInteger add(BigInteger val):加
System.out.println("add:" + bi1.add(bi2));
// public BigInteger subtract(BigInteger val):加
System.out.println("subtract:" + bi1.subtract(bi2));
// public BigInteger multiply(BigInteger val):加
System.out.println("multiply:" + bi1.multiply(bi2));
// public BigInteger divide(BigInteger val):加
System.out.println("divide:" + bi1.divide(bi2));
// public BigInteger[] divideAndRemainder(BigInteger val):返回商和余数的数组
BigInteger[] bis = bi1.divideAndRemainder(bi2);
System.out.println("商:" + bis[0]);
System.out.println("余数:" + bis[1]);
}
}
BigDecimal类
不可变的、任意精度的有符号十进制数,可以解决数据丢失问题
由于在运算的时候,float类型和double很容易丢失精度,所以,为了能精确的表示、计算浮点数,Java提供了BigDecimal
构造方法:
public BigDecimal(String val)
成员方法:
public BigDecimal add(BigDecimal augend)加
public BigDecimal subtract(BigDecimal subtrahend)减
public BigDecimal multiply(BigDecimal multiplicand)乘
public BigDecimal divide(BigDecimal divisor)除
public BigDecimal divide(BigDecimal divisor,int scale,int roundingMode):divisor商,scale保留几位小数,roundingMode如何舍取,其中ROUND_HALF_UP最接近四舍五入
public class BigDecimalDemo {
public static void main(String[] args) {
// System.out.println(0.09 + 0.01);
// System.out.println(1.0 - 0.32);
// System.out.println(1.015 * 100);
// System.out.println(1.301 / 100);
BigDecimal bd1 = new BigDecimal("0.09");
BigDecimal bd2 = new BigDecimal("0.01");
System.out.println("add:" + bd1.add(bd2));
System.out.println("-------------------");
BigDecimal bd3 = new BigDecimal("1.0");
BigDecimal bd4 = new BigDecimal("0.32");
System.out.println("subtract:" + bd3.subtract(bd4));
System.out.println("-------------------");
BigDecimal bd5 = new BigDecimal("1.015");
BigDecimal bd6 = new BigDecimal("100");
System.out.println("multiply:" + bd5.multiply(bd6));
System.out.println("-------------------");
BigDecimal bd7 = new BigDecimal("1.301");
BigDecimal bd8 = new BigDecimal("100");
System.out.println("divide:" + bd7.divide(bd8));
System.out.println("divide:"
+ bd7.divide(bd8, 3, BigDecimal.ROUND_HALF_UP));
System.out.println("divide:"
+ bd7.divide(bd8, 8, BigDecimal.ROUND_HALF_UP));
}
}
Date类
表示特定的瞬间,精确到毫秒
构造方法:
Date():根据当前的默认毫秒值创建日期对象
Date(long date):根据给定的毫秒值创建日期对象
public class DateDemo {
public static void main(String[] args) {
// 创建对象
Date d = new Date();
System.out.println("d:" + d);
// 创建对象
// long time = System.currentTimeMillis(); //获取当前程序运行时的时间
long time = 1000 * 60 * 60; // 1小时+东八区的8小时
Date d2 = new Date(time);
System.out.println("d2:" + d2);
}
}
成员方法
public long getTime():获取时间,以毫秒为单位
public void setTime(long time):设置时间
从Date得到一个毫秒值
getTime()
把一个毫秒值转换为Date
构造方法
setTime(long time)
public class DateDemo {
public static void main(String[] args) {
// 创建对象
Date d = new Date();
// 获取时间
long time = d.getTime();
System.out.println(time);
// System.out.println(System.currentTimeMillis());
System.out.println("d:" + d);
// 设置时间
d.setTime(1000);
System.out.println("d:" + d);
}
}
Date --String(格式化)
public final String format(Date date)
String -- Date(解析)
public Date parse(String source)
DateForamt:可以进行日期和字符串的格式化和解析,但是由于是抽象类,所以使用具体子类SimpleDateFormat
SimpleDateFormat
SimpleDateFormat的构造方法:
SimpleDateFormat():默认模式
SimpleDateFormat(String pattern):给定的模式
这个模式字符串该如何写呢?
通过查看API,我们就找到了对应的模式
年 y
月 M
日 d
时 H
分 m
秒 s
public class DateFormatDemo {
public static void main(String[] args) throws ParseException {
// Date -- String
// 创建日期对象
Date d = new Date();
// 创建格式化对象
// SimpleDateFormat sdf = new SimpleDateFormat();
// 给定模式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
// public final String format(Date date)
String s = sdf.format(d);
System.out.println(s);
//String -- Date
String str = "2022-03-14 16:48:02";
//在把一个字符串解析为日期的时候,请注意格式必须和给定的字符串格式匹配
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date dd = sdf2.parse(str);
System.out.println(dd);
}
}
计算你出生多少天了
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
/*
* 需求:算出你来到这个世界多少天
* 分析:首先键盘输入自己的出生年月
* 将出生年月换成毫秒 String -- Date
* 获取系统当前时间
* 用当前时间减去出生时的毫秒值
* 对毫秒值计算得出天数
* */
public class dateToString {
public static void main(String[] args) throws ParseException {
//首先键盘输入自己的出生年月
Scanner sc = new Scanner(System.in);
System.out.println("请输入自己的出生年月日,用-隔开");
String birthDay = sc.nextLine();
//将出生年月换成毫秒 String -- Date
//创建格式化对象
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd");
//把该字符串转换为一个日期
Date birth = sd.parse(birthDay);
//再把日期转换为毫秒
long myTime = birth.getTime();
//获取系统当前时间
Date d = new Date();
long dateTime = d.getTime();
//用当前时间减去出生时的毫秒值
myTime = dateTime - myTime;
//在对毫秒值进行运算得出多少天
int day = (int)(myTime/1000/60/60/24);
System.out.println("你出生了"+day+"天");
}
}
Calendar
它为特定瞬间与一组诸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等 日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法
public int get(int field):返回给定日历字段的值,日历类中的每个日历字段都是静态的成员变量,并且是int类型
//获取当前时间的年月日
public class CalendarDemo {
public static void main(String[] args) {
// 其日历字段已由当前日期和时间初始化:
Calendar rightNow = Calendar.getInstance(); // 子类对象,多态
// 获取年
int year = rightNow.get(Calendar.YEAR);
// 获取月
int month = rightNow.get(Calendar.MONTH);
// 获取日
int date = rightNow.get(Calendar.DATE);
System.out.println(year + "年" + (month + 1) + "月" + date + "日");
}
}
成员方法
public void add(int field,int amount):根据给定的日历字段和对应的时间,来对当前的日历进行操作
public final void set(int year,int month,int date):设置当前日历的年月日
public class CalendarDemo {
public static void main(String[] args) {
// 获取当前的日历时间
Calendar c = Calendar.getInstance();
// 获取年
int year = c.get(Calendar.YEAR);
// 获取月
int month = c.get(Calendar.MONTH);
// 获取日
int date = c.get(Calendar.DATE);
System.out.println(year + "年" + (month + 1) + "月" + date + "日");
// // 三年前的今天
// c.add(Calendar.YEAR, -3);
// // 获取年
// year = c.get(Calendar.YEAR);
// // 获取月
// month = c.get(Calendar.MONTH);
// // 获取日
// date = c.get(Calendar.DATE);
// System.out.println(year + "年" + (month + 1) + "月" + date + "日");
// 5年后的10天前
c.add(Calendar.YEAR, 5);
c.add(Calendar.DATE, -10);
// 获取年
year = c.get(Calendar.YEAR);
// 获取月
month = c.get(Calendar.MONTH);
// 获取日
date = c.get(Calendar.DATE);
System.out.println(year + "年" + (month + 1) + "月" + date + "日");
System.out.println("--------------");
c.set(2011, 11, 11);
// 获取年
year = c.get(Calendar.YEAR);
// 获取月
month = c.get(Calendar.MONTH);
// 获取日
date = c.get(Calendar.DATE);
System.out.println(year + "年" + (month + 1) + "月" + date + "日");
}
}
/*
* 获取任意一年的二月有多少天
*
* 分析:
* A:键盘录入任意的年份
* B:设置日历对象的年月日
* 年就是A输入的数据
* 月是2
* 日是1
* C:把时间往前推一天,就是2月的最后一天
* D:获取这一天输出即可
*/
public class CalendarTest {
public static void main(String[] args) {
// 键盘录入任意的年份
Scanner sc = new Scanner(System.in);
System.out.println("请输入年份:");
int year = sc.nextInt();
// 设置日历对象的年月日
Calendar c = Calendar.getInstance();
c.set(year, 2, 1); // 其实是这一年的3月1日
// 把时间往前推一天,就是2月的最后一天
c.add(Calendar.DATE, -1);
// 获取这一天输出即可
System.out.println(c.get(Calendar.DATE));
}
}
package Array;
/*
* 需求:我有五个学生,把五个学生的信息存储到数组中,并进行遍历数组
* 分析: 有五个学生,肯定要定义一个学生类
* 创建五个学生对象
* 要有一个学生数组
* 把五个对象存放到学生数组中
* 遍历数组
* */
public class StudentDemo {
public static void main(String[] args) {
//创建学生对象并赋值
Student s1 = new Student("张三",18);
Student s2 = new Student("李四",16);
Student s3 = new Student("王五",19);
Student s4 = new Student("赵六",15);
Student s5 = new Student("周七",20);
//要有一个学生数组
Student [] students = new Student[5];
//把五个对象存放到学生数组中,不可以用for循环
students [0] = s1;
students [1] = s2;
students [2] = s3;
students [3] = s4;
students [4] = s5;
//遍历数组
for (int i = 0; i < students.length; i++) {
System.out.println(students[i]); //因为学生类中重写了toString方法,可以直接输出
Student s = students[i];//也可以通过创建对象调用get输出
System.out.println(s.getName()+s.getAge());
}
}
}
package Array;
public class Student {
//成员变量姓名年龄
private String name;
private int age;
//构造方法
public Student() {
}
public Student(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;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Day15
集合
只用于存储对象,可以存储不同类型的对象,长度可以变化
集合和数组的区别
长度区别
数组的长度固定
集合长度可变
内容不同
数组存储的是同一种类型的元素
而集合可以存储不同类型的元素
元素的数据类型问题
数组可以存储基本数据类型,也可以存储引用数据类型
集合只能存储引用类型
Collection
Collection
List Set
ArrayList Vector LinkedList HashSet TreeSet
是集合的顶层接口,它的子体系有重复的,有唯一的,有有序的,有无序的
Collection的功能概述:
添加功能
boolean add(Object obj):添加一个元素
boolean addAll(Collection c):添加一个集合的元素
删除功能
void clear():移除所有元素
boolean remove(Object o):移除一个元素
boolean removeAll(Collection c):移除一个集合的元素,移除一个就是移除
判断功能
boolean contains(Object o):判断集合中是否包含指定的元素
boolean containsAll(Collection c):判断集合中是否包含指定的集合元素,只有包含所有的元素才叫包含
boolean isEmpty():判断集合是否为空
获取功能
Iterator<E> iterator()(重点)
长度功能
int size():元素的个数
交集功能
boolean retainAll(Collection c):两个集合都有的元素,例A集合调用方法对B集合做交集,最终的结果放在A集合中,B不变,返回的布尔值代表集合A是否发生改变
把集合转换为数组
Object[] toArray()
面试题:数组有没有length()方法呢?字符串有没有length()方法呢?集合有没有length()方法呢?
数组没有length()方法,有length属性,String有length()方法,集合的是size()方法表示元素个数
public class CollectionDemo {
public static void main(String[] args) {
// 测试不带All的方法
// 创建集合对象
// Collection c = new Collection(); //错误,因为接口不能实例化
Collection c = new ArrayList();
// boolean add(Object obj):添加一个元素
// System.out.println("add:"+c.add("hello"));
c.add("hello");
c.add("world");
c.add("java");
// void clear():移除所有元素
// c.clear();
// boolean remove(Object o):移除一个元素
// System.out.println("remove:" + c.remove("hello"));
// System.out.println("remove:" + c.remove("javaee"));
// boolean contains(Object o):判断集合中是否包含指定的元素
// System.out.println("contains:"+c.contains("hello"));
// System.out.println("contains:"+c.contains("android"));
// boolean isEmpty():判断集合是否为空
// System.out.println("isEmpty:"+c.isEmpty());
//int size():元素的个数
System.out.println("size:"+c.size());
System.out.println("c:" + c);
}
}
Object[] toArray()集合的遍历
/*遍历集合。以及输出每个元素的长度
* */
import java.util.ArrayList;
import java.util.Collection;
public class CollectionDemo{
public static void main(String[] args) {
//创建集合对象
Collection c = new ArrayList();
//添加元素
c.add("hello");
c.add("world");
c.add("世界,你好");
//不会集合的遍历,但是集合有个功能Object[] toArray()将集合转换为字符串
Object[] obj = c.toArray();
//对数组obj进行遍历
for (int i = 0; i < obj.length; i++) {
//System.out.println(obj[i]+" ");
//每个元素的长度,就是字符串的长度,length,但是obj没有length方法,所以向下转型
String s = (String) (obj[i]);
System.out.println(s+"-----"+s.length());
}
}
}
Iterator iterator():迭代器,集合的专用遍历方式
Object next():获取元素,并移动到下一个位置
NoSuchElementException:没有这样的元素,因为你已经找到最后了
boolean hasNext():如果仍有元素可以迭代,则返回 true
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionDemo{
public static void main(String[] args) {
//创建集合对象
Collection c1 = new ArrayList();
//创建学生对象
Student s1 = new Student("张三",15);
Student s2 = new Student("李四",15);
Student s3 = new Student("王六",14);
//添加元素
c1.add(s1);
c1.add(s2);
c1.add(s3);
//Iterator iterator():迭代器,集合的专用遍历方式
Iterator it = c1.iterator();
//Object next():获取元素,并移动到下一个位置
System.out.println(it.next());
System.out.println(it.next());
System.out.println(it.next());
//System.out.println(it.next());
// NoSuchElementException没有这样的元素异常,因为就三个元素,不能输出第四个
// boolean hasNext():如果仍有元素可以迭代,则返回 true
while(it.hasNext()){
//System.out.println(it.next());
String s = (String) it.next();
System.out.println(s);
}
//while循环可以用for改进,把创建迭代器对象放在第一条语句中,条件是it.hasNext(),省略第三句,
//只判断第二句是否成立,这样的好处是for运行完Iterator对象it就是垃圾,可以被回收,提高了效率
for (Iterator it = c1.iterator();it.hasNext();) {
Student s = (Student) it.next();
System.out.println(s.getName()+s.getAge());
}
}
}
集合的使用步骤
创建集合对象
Collection c1 = new ArrayList();
创建元素对象
Student s1 = new Student("张三", 15);//以学生类为例
把元素添加到集合
c1.add(s1);
遍历集合
通过集合对象获取迭代器对象
Iterator it = c1.iterator();
通过迭代器对象的hasNext()方法判断是否有元素
it.hasNext();//返回布尔值,有下一个元素就是true
通过迭代器对象的next()方法获取元素并移动到下一个位置
Student s = (Student) it.next();//一般是向下转型成为学生类对象
System.out.println(s.getName()+s.getAge());//调用学生类的方法输出,可以单独输出
List接口
有序的 collection(也称为序列),此接口的用户可以对列表中每个元素的插入位置进行精确地控制,用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素,与 set 不同,列表通常允许重复的元素
List集合
特点:有序(存储和取出的元素一致),可重复的
public class ListDemo2 {
public static void main(String[] args) {
// 创建集合对象
List list = new ArrayList();
// 存储元素
list.add("hello");
list.add("world");
list.add("java");
list.add("javaee");
list.add("android");
list.add("javaee"); //可重复的
list.add("android");
// 遍历集合
Iterator it = list.iterator();
while (it.hasNext()) {
String s = (String) it.next();
System.out.println(s); //输出顺序跟定义顺序一致
}
}
}
List集合的特有功能:
添加功能
void add(int index,Object element):在指定位置添加元素
获取功能
Object get(int index):获取指定位置的元素
列表迭代器
ListIterator listIterator():List集合特有的迭代器
删除功能
Object remove(int index):根据索引删除元素,返回被删除的元素
修改功能
Object set(int index,Object element):根据索引修改元素,返回被修饰的元素
List集合特有的遍历方法(通过size()和gat()结合)
import java.util.ArrayList;
import java.util.List;
public class CollectionDemo {
public static void main(String[] args) {
//创建集合对象
List li = new ArrayList();
//创建学生对象
Student s1 = new Student("张三",15);
Student s2 = new Student("李四",15);
Student s3 = new Student("王五",16);
//将学生对象添加到集合中
li.add(s1);
li.add(s2);
li.add(s3);
//遍历集合
for (int i = 0; i < li.size(); i++) {
//System.out.println(li.get(i)); //可以遍历但不推荐,需要重写toString方法且不灵活
Student s = (Student) li.get(i);
System.out.println(s.getName()+s.getAge());
}
}
}
列表迭代器:
ListIterator listIterator():List集合特有的迭代器,该迭代器继承了Iterator迭代器,所以,就可以直接使用hasNext()和next()方法
特有功能:
Object previous():获取上一个元素
boolean hasPrevious():判断是否有元素
注意:ListIterator可以实现逆向遍历,但是必须先正向遍历,才能逆向遍历,所以一般无意义,不使用
public class ListIteratorDemo {
public static void main(String[] args) {
// 创建List集合对象
List list = new ArrayList();
list.add("hello");
list.add("world");
list.add("java");
// ListIterator listIterator()
ListIterator lit = list.listIterator(); // 子类对象
// while (lit.hasNext()) {
// String s = (String) lit.next();
// System.out.println(s);
// }
// System.out.println("-----------------");
// System.out.println(lit.previous());
// System.out.println(lit.previous());
// System.out.println(lit.previous());
// NoSuchElementException
// System.out.println(lit.previous());
while (lit.hasPrevious()) {
String s = (String) lit.previous();
System.out.println(s);
}
System.out.println("-----------------");
// 迭代器
Iterator it = list.iterator();
while (it.hasNext()) {
String s = (String) it.next();
System.out.println(s);
}
System.out.println("-----------------");
}
}
ConcurrentModificationException
当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常
产生的原因:
迭代器是依赖于集合而存在的,在判断成功后,集合的中新添加了元素,而迭代器却不知道,所以就报错了,这个错叫并发修改异常
解决方法
迭代器迭代元素,迭代器修改元素,元素是跟在刚才迭代的元素后面的
// 方式1:迭代器迭代元素,迭代器修改元素
// 而Iterator迭代器却没有添加功能,所以我们使用其子接口ListIterator
ListIterator lit = list.listIterator();
while (lit.hasNext()) {
String s = (String) lit.next();
if ("world".equals(s)) {
lit.add("javaee");
}
}
集合遍历元素,集合修改元素(普通for),元素在最后添加的
// 方式2:集合遍历元素,集合修改元素(普通for)
for (int x = 0; x < list.size(); x++) {
String s = (String) list.get(x);
if ("world".equals(s)) {
ist.add("javaee");
}
}
常见的数据结构
栈:先进后出 例:子弹夹
队列:先进先出 例:超市排队结账
数组:存储同一种类型多个元素的容器,有索引,方便获取,特点:查询快,增删慢
链表:由一个链子把多个结点连接起来组成的数据,结点由数据和地址组成,特点:查询慢,增删快
List子类的特点
ArrayList:
底层数据结构是数组,查询快,增删慢
线程不安全,效率高
Vector:
底层数据结构是数组,查询快,增删慢
线程安全,效率低
LinkedList:
底层数据结构是链表,查询慢,增删快
线程不安全,效率高
List的三个子类要用哪一个
要安全吗
要:Vector(即使要安全,也不用这个了,后面有替代的)
不要:ArrayList或者LinkedList
查询多:ArrayList
增删多:LinkedList