一.基础
1.类与对象,成员方法,构造器
方法
2.this,super,final,常量
final
常量
作为常量时,一定要将其初始化,即赋值。
3.封装,继承,多态
继承
注意:
调用子类的无参构造器之前,先执行父类的无参构造器,在执行自己的。
class Z{
public Z(){
System.out.println("调用了父类的无参构造器");
}
public Z(String name){
System.out.println("调用了父类的有参构造器");
}
}
class F extends Z{
public F(){
System.out.println("调用了子类的无参构造器");
}
public F(String name){
System.out.println("调用了子类的you参构造器");
}
}
public class String1 {
public static void main(String[] args) {
F f = new F();
}
}
//调用了父类的无参构造器
//调用了子类的无参构造器
调用子类的有参构造器之前,先执行父类的无参构造器,并不执行父类的有参构造器,之后在执行自己的有参。
public class String1 {
public static void main(String[] args) {
F f = new F("郝仁");
}
}
//调用了父类的无参构造器
//调用了子类的you参构造器
原因:子类的构造器中,都默认第一行存在一个super(),它就会去调用父类的无参构造器。
一旦父类写了一个有参构造器,默认的无参构造器没有了,就会报错——解决——在子类构造器中手写出super(),指定去调用父类的有参构造器。如:super("好的");
多态
1.什么是多态
注意:对于 对象和行为 ,编译看左边,运行看右边
对于 变量,编译和运行都看左边
2.多态的好处
1.可以实现解耦合,右边对象可以随时切换,后续的业务不用在变
2.可以使用父类类型的变量作为形参,接受一切子类对象
但是,多态会产生一个问题——>多态下不能使用子类的独有功能
解决:
4.main方法,代码块
代码块
静态代码块指会在类加载阶段执行一次,并且只执行一次,不管你创建不创建对象;
实例代码块意味着,每次new 一个对象就会执行一次
5.枚举,注解
枚举
想要获取枚举类中的枚举项,只需要用类名调用就可以了
public class Test{
public static void main(String[] args){
//获取枚举A类的,枚举项
A a1 = A.X;
A a2 = A.Y;
A a3 = A.Z;
}
}
6.String (不可变 字符串)
java.lang包下的类,作用是字符串类型,可以用来处理字符串数据
String如何创建对象,封装字符串数据呢?
方式一:直接使用“ ....” 的方式得到字符串对象(推荐的方式。)
String name = "黑马";
方式二:通过构造器初始化字符串对象。
String提供了哪些方法,对字符串进行处理?
public class StringDemo2 {
public static void main(String[] args) {
// 目标:快速熟悉String提供的处理字符串的常用方法。
String name = "ab黑马666";
// 1、获取字符串的长度(字符个数)
System.out.println(name.length()); // 7
// 2、提取字符串中某个索引位置处的字符
System.out.println(name.charAt(0));
System.out.println(name.charAt(1));
System.out.println(name.charAt(2));
// 字符串的遍历。
String name2 = "我爱你中国abc";
// 0 1 23 4567
for (int i = 0; i < name2.length(); i++) {
// i = 0 1 2 3 4 5 6 7
char ch = name2.charAt(i);
System.out.println(ch);
}
// 3、把字符串转换成字符数组,再进行遍历
System.out.println("----------------------------------------");
char[] chars = name2.toCharArray();
// chars = [我,爱,你,中,国,a, b, c]
for (int i = 0; i < chars.length; i++) {
char ch = chars[i];
System.out.println(ch);
}
// 4、判断字符串内容,内容一样就返回true
String s1 = "黑马";
String s2 = new String("黑马");
System.out.println(s1 == s2); // 比较地址
System.out.println(s1.equals(s2)); // 比较内容
// 5、忽略大小写比较字符串内容
String s3 = "ab2Fg";
String s4 = "AB2FG";
System.out.println(s3.equals(s4)); // false .精准比较内容
System.out.println(s3.equalsIgnoreCase(s4)); // true .忽略大小写比较字符串内容
// 6、截取字符串内容 (包前不包后的)
String s5 = "Java是最牛逼的编程语言之一";
String result = s5.substring(0,9);
System.out.println(result);
// 7、从当前索引位置一直截取到字符串的末尾
String result2 = s5.substring(5);
System.out.println(result2);
// 8、把字符串中的某个内容替换成新内容,并返回新的字符串对象给我们
String s6 = "这个游戏简直是个垃圾,垃圾游戏!!,好垃圾!!,我打的都很垃圾~~~";
String result3 = s6.replaceAll("垃圾", "**");
System.out.println(result3);
// 9、判断字符串中是否包含某个关键字
String s7 = "黑马Java磊哥";
System.out.println(s7.contains("Java")); // true
System.out.println(s7.contains("java")); // false
System.out.println(s7.contains("黑马Java2")); // false
// 10、判断字符串是否以某个字符串开头。
// startsWith 判断是否以什么内容开头
System.out.println(s7.startsWith("黑马Java")); // true
System.out.println(s7.startsWith("马Java")); // false
// endsWith 判断是否以什么内容结尾
System.out.println(s7.endsWith("磊哥")); // true
System.out.println(s7.endsWith("ava磊哥"));// true
System.out.println(s7.endsWith("磊哥2"));// false
// 11、把字符串按照某个指定内容分割成多个字符串,
// 放到一个字符串数组中返回给我们。
String s8 = "高叶,杨超越,古力娜扎";
String[] names = s8.split(",");
for (int i = 0; i < names.length; i++) {
System.out.println(names[i]);
}
}
}
String的注意事项1:
1. String的对象是不可变字符串对象。
static 2.“...”给出的字符串对象,放在常量池,且相同内容的字符串对象在常量池中只有一份。
3.new 出来的字符串对象,是直接放在堆内存中,每new一次都会产生一个新的字符串对象
String的注意事项2:
对于8种基本数据类型的变量,建议使用 == 进行相等判断
对于两个字符串对象的比较,建议使用equals进行比较,只关心内容一样,就返回true.
7.static关键字
static是静态的意思,可以修饰成员变量,可以修饰成员方法
static修饰成员变量
1. 静态成员变量
有static修饰,属于类,与类一起加载,内存中只有一份,可以被共享访问。
什么时候用呢? 如果信息要被共享,只需要一份就用,比如:系统在线人数。
访问规则:
建议用类名访问:类名.静态成员变量
注意:同一个类中,访问静态成员可以省略类名不写。
还可以这样访问:对象名.静态成员变量(不推荐)
2.实例成员变量
无static修饰,属于对象,每个对象中都存在一份实例成员变量。比如:name age
什么时候用呢?比如:name age,每个对象中都有这些信息,而且信息还不同时,定义成实例成员变量。
访问规则:
只能用:对象名.实例成员变量。
static修饰成员方法
1.静态成员方法
有static修饰,属于类,与类一起加载,可以被共享访问。
什么时候用呢?如果是做一个通用功能。
访问规则:
建议用类名访问:类名.静态方法
注意:同一个类中,访问静态成员可以省略类名不写。
也可以这样访问:对象名.静态成员方法(不推荐)
2. 实例成员方法
无static修饰,属于对象,必须用对象触发访问。
什么时候用呢?如果这个方法属于对象,而且要直接访问对象的实例成员,则申明成实例方法。
访问规则:
只能用:对象名.实例成员方法。
8.方法重载,方法重写
方法重写![](https://img-blog.csdnimg.cn/e73b893c8d8f41388870c2c12d41119f.png)
方法重写的常见应用:
子类重写Object类的toString()方法,以便返回对象的内容。
9.抽象类
- 被abstract修饰的类,就是抽象类
- 被abstract修饰的方法,就是抽象方法(不允许有方法体)
//abstract修饰类,这个类就是抽象类
public abstract class A{
//abstract修饰方法,这个方法就是抽象方法
public abstract void test();
}
类该有的成员(成员变量、成员方法、构造器),抽象类都可以有
抽象类是不能创建对象的,如果抽象类的对象就会报错
抽象类虽然不能创建对象,但是它可以作为父类让子类继承。而且子类继承父类必须重写父类的所有抽象方法。
子类继承父类如果不想重写父类的抽象方法,要想不出错,这个子类也必须是抽象类,这个时候就可以不重写父类的抽象方法
抽象类的好处
父类知道子类都要做某个行为,子类做的情况都不一样,就可以将其弄为抽象方法,让子类去重写实现。(更似于多态)
10.接口
Java提供了一个关键字interface,用这个关键字来定义接口这种特殊结构。格式如下
public interface 接口名{
//成员变量(视为 常量)
//成员方法(视为 抽象方法)
}
public interface A{
//这里public static final可以加,可以不加。
public static final String SCHOOL_NAME = "黑马";
//这里的public abstract可以加,可以不加。
public abstract void test();
}
因为成员方法视为抽象方法,所以接口不能创建对象 。
注意:
-
接口是用来 被类 实现(implements)的,我们称之为实现类。
-
一个类是可以实现多个接口的(接口可以理解成干爹),类实现接口必须重写所有接口的全部抽象方法,否则这个类也必须是抽象类
好处
-
弥补了类单继承的不足,一个类同时可以实现多个接口。
-
让程序可以面向接口编程,这样程序员可以灵活方便的切换各种业务实现。
综合案例:班级学生信息管理模块的开发
学生的信息有:名字,年龄,分数
开发功能:打印全班学生的信息;全班学生的平均成绩
学生类:
package com.zkl.interface1;
public class Student {
private String name;
private double score;
private int age;
public Student() {
}
public Student(String name, double score, int age) {
this.name = name;
this.score = score;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
班级管理类:
package com.zkl.interface1;
import java.util.ArrayList;
public class ClassManager {//班级管理类
private ArrayList<Student> students = new ArrayList<Student>();//集合容器
private Operator operator = new Operatorimpl1();
public ClassManager(){
students.add(new Student("热巴",90,20));
students.add(new Student("丽影",100,18));
students.add(new Student("杨幂",93,25));
students.add(new Student("宋祖儿",94,18));
}
//打印所有信息
public void PrintAllInfo(){
operator.printAllInfo(students);
}
//打印全班学生的平均分
public void PrintScore(){
operator.printScore(students);
}
}
接口:表示学生信息管理系统的两个功能。
package com.zkl.interface1;
import java.util.ArrayList;
public interface Operator {
void printAllInfo(ArrayList<Student> students);
void printScore(ArrayList<Student> students);
}
接口实现类:
package com.zkl.interface1;
import java.util.ArrayList;
public class Operatorimpl1 implements Operator{
@Override
public void printAllInfo(ArrayList<Student> students) {
System.out.println("--------------全班学生信息---------------");
for (int i = 0; i < students.size(); i++) {
Student s = students.get(i);
System.out.println("学生姓名:"+ s.getName()+"分数: " + s.getScore()+ "年龄"+s.getAge());
}
System.out.println("----------------------------------");
}
@Override
public void printScore(ArrayList<Student> students) {
double AllScore = 0.0;
for (int i = 0; i < students.size(); i++) {
Student s = students.get(i);
AllScore += s.getScore();
}
double AverageScore = AllScore / students.size();
System.out.println("平均分=" +AverageScore);
}
}
测试类:
package com.zkl.interface1;
public class Test {
public static void main(String[] args) {
// 目标:完成班级学生信息管理的案例。
ClassManager clazz = new ClassManager();
clazz.PrintAllInfo();
clazz.PrintScore();
}
}
11.内部类
内部类是类中的五大成分之一(成员变量、方法、构造器、内部类、代码块),如果一个类定义在另一个类的内部,这个类就是内部类。
当一个类的内部,包含一个完整的事物,且这个事物没有必要单独设计时,就可以把这个事物设计成内部类。
比如:汽车、的内部有发动机,发动机是包含在汽车内部的一个完整事物,可以把发动机设计成内部类。
public class Car{
//内部类
public class Engine{
}
}
内部类有四种形式,分别是成员内部类、静态内部类、局部内部类、匿名内部类。
1.成员内部类
成员内部类就是类中的一个普通成员,类似于成员变量、成员方法。
public class Outer {
private int age = 99;
public static String a="黑马";
// 成员内部类
public class Inner{
private String name;
private int age = 88;
//在内部类中既可以访问自己类的成员,也可以访问外部类的成员
public void test(){
System.out.println(age); //88
System.out.println(a); //黑马
int age = 77;
System.out.println(age); //77
System.out.println(this.age); //88
System.out.println(Outer.this.age); //99
}
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;
}
}
}
成员内部类如何创建对象
//外部类.内部类 变量名 = new 外部类().new 内部类();
Outer.Inner in = new Outer().new Inner();
//调用内部类的方法
in.test();
总结一下内部类访问成员的特点
-
既可以访问内部类成员、也可以访问外部类成员
-
如果内部类成员和外部类成员同名,可以使用
类名.this.成员
区分
2.匿名内部类
所谓匿名,指的是不需要为这个类声明名字。
new 父类/接口(参数值){
@Override
重写父类/接口的方法;
}
匿名内部类本质上是一个没有名字的子类对象、或者接口的实现类对象
(并没有创建子类对象,但是new后面跟的是其父类,事实上编译后系统会自动为匿名内部类生产字节码 ,类名会继承父类)
作用:简化了创建子类对象、实现类对象的书写格式。
应用场景:只有在调用方法时,当方法的形参是一个接口或者抽象类,为了简化代码书写,而直接传递匿名内部类对象给方法。
3.局部内部类
局部内部类是定义在方法中的类,和局部变量一样,只能在方法中有效。所以局部内部类的局限性很强,一般在开发中是不会使用的。
public class Outer{
public void test(){
//局部内部类
class Inner{
public void show(){
System.out.println("Inner...show");
}
}
//局部内部类只能在方法中创建对象,并使用
Inner in = new Inner();
in.show();
}
}
4.静态内部类
就是在成员内部类的前面加了一个static关键字。
静态内部类属于外部类自己持有,静态内部类创建对象时,需要使用外部类的类名调用。
public class Outer {
private int age = 99;
public static String schoolName="黑马";
// 静态内部类
public static class Inner{
//静态内部类访问外部类的静态变量,是可以的;
//静态内部类访问外部类的实例变量,是不行的
public void test(){
System.out.println(schoolName); //99
//System.out.println(age); //报错
}
}
}
//格式:外部类.内部类 变量名 = new 外部类.内部类();
Outer.Inner in = new Outer.Inner();
in.test();
二.异常
三.常用API
1.1 Object类
Object类是Java中所有类的祖宗类,因此,Java中所有类的对象都可以直接使用Object类中提供的一些方法。
-
4.1.1 toString()方法
public String toString()
调用toString()方法可以返回对象的字符串表示形式。
默认的格式是:“包名.类名@哈希值16进制”
假设有一个学生类如下
public class Student{
private String name;
private int age;
public Student(String name, int age){
this.name=name;
this.age=age;
}
}
再定义一个测试类
public class Test{
public static void main(String[] args){
Student s1 = new Student("赵敏",23);
System.out.println(s1.toString());
}
}
如果,在Student类重写toString()方法,那么我们可以返回对象的属性值,代码如下
public class Student{
private String name;
private int age;
public Student(String name, int age){
this.name=name;
this.age=age;
}
@Override
public String toString(){
return "Student{name=‘"+name+"’, age="+age+"}";
}
}
4.1.2 equals(Object o)方法
public boolean equals(Object o)
判断此对象与参数对象是否"相等"
测试类,测试一下
public class Test{
public static void main(String[] args){
Student s1 = new Student("赵薇",23);
Student s2 = new Student("赵薇",23);
//equals本身也是比较对象的地址,和"=="没有区别
System.out.println(s1.equals(s2)); //false
//"=="比较对象的地址
System.out.println(s1==s2); //false
}
}
但是如果我们在Student类中,把equals方法重写了,就按照对象的属性值进行比较
public class Student{
private String name;
private int age;
public Student(String name, int age){
this.name=name;
this.age=age;
}
@Override
public String toString(){
return "Student{name=‘"+name+"’, age="+age+"}";
}
//重写equals方法,按照对象的属性值进行比较
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if (age != student.age) return false;
return name != null ? name.equals(student.name) : student.name == null;
}
}
总结:
public String toString()
返回对象的字符串表示形式。默认的格式是:“包名.类名@哈希值16进制”
【子类重写后,返回对象的属性值】
public boolean equals(Object o)
判断此对象与参数对象是否"相等"。默认比较对象的地址值,和"=="没有区别
【子类重写后,比较对象的属性值】
4.1.3 clone() 方法
clone()方法,克隆。意思就是某一个对象调用这个方法,这个方法会复制一个一模一样的新对象,并返回。
public Object clone()
克隆当前对象,返回一个新对象
想要调用clone()方法,必须让被克隆的类实现Cloneable接口。如我们准备克隆User类的对象,代码如下
public class User implements Cloneable{
private String id; //编号
private String username; //用户名
private String password; //密码
private double[] scores; //分数
public User() {
}
public User(String id, String username, String password, double[] scores) {
this.id = id;
this.username = username;
this.password = password;
this.scores = scores;
}
//...get和set...方法自己加上
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
接着,我们写一个测试类,克隆User类的对象。并观察打印的结果
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
User u1 = new User(1,"zhangsan","wo666",new double[]{99.0,99.5});
//调用方法克隆得到一个新对象
User u2 = (User) u1.clone();
System.out.println(u2.getId());
System.out.println(u2.getUsername());
System.out.println(u2.getPassword());
System.out.println(u2.getScores());
}
}
我们发现,克隆得到的对象u2它的属性值和原来u1对象的属性值是一样的。
上面演示的克隆方式,是一种浅克隆的方法,浅克隆的意思:拷贝出来的对象封装的数据与原对象封装的数据一模一样(引用类型拷贝的是地址值)。
1.2 Objects类
Objects是一个工具类,提供了一些方法可以对任意对象进行操作。
下面写代码演示一下这几个方法
public class Test{
public static void main(String[] args){
String s1 = null;
String s2 = "itheima";
//这里会出现NullPointerException异常,调用者不能为null
System.out.println(s1.equals(s2));
//此时不会有NullPointerException异常,底层会自动先判断空
System.out.println(Objects.equals(s1,s2));
//判断对象是否为null,等价于==
System.out.println(Objects.isNull(s1)); //true
System.out.println(s1==null); //true
//判断对象是否不为null,等价于!=
System.out.println(Objects.nonNull(s2)); //true
System.out.println(s2!=null); //true
}
}
1.3 基本类型包装类
同学们,接下来我们学习一下包装类。为什么要学习包装类呢?因为在Java中有一句很经典的话,万物皆对象。Java中的8种基本数据类型还不是对象,所以要把它们变成对象,变成对象之后,可以提供一些方法对数据进行操作。
Java中8种基本数据类型都用一个包装类与之对一个,如下图所示
包装类,主要学习两点:
- 创建包装类的对象方式、自动装箱和拆箱的特性;
- 利用包装类提供的方法对字符串和基本类型数据进行相互转换
1.3.1 创建包装类对象
创建包装类对象的方法,以及包装类的一个特性叫自动装箱和自动拆箱。我们以Integer为例,其他的可以自己学,都是类似的。
//1.创建Integer对象,封装基本类型数据10
Integer a = new Integer(10);
//2.使用Integer类的静态方法valueOf(数据)
Integer b = Integer.valueOf(10);
//3.还有一种自动装箱的写法(意思就是自动将基本类型转换为引用类型)
Integer c = 10;
//4.有装箱肯定还有拆箱(意思就是自动将引用类型转换为基本类型)
int d = c;
//5.装箱和拆箱在使用集合时就有体现
ArrayList<Integer> list = new ArrayList<>();
//添加的元素是基本类型,实际上会自动装箱为Integer类型
list.add(100);
//获取元素时,会将Integer类型自动拆箱为int类型
int e = list.get(0);
1.3.2 包装类数据类型转换
在开发中,经常使用包装类对字符串和基本类型数据进行相互转换。
-
把字符串转换为数值型数据:包装类.parseXxx(字符串)
public static int parseInt(String s)
把字符串转换为基本数据类型
-
将数值型数据转换为字符串:包装类.valueOf(数据);
public static String valueOf(int a)
把基本类型数据转换为
-
写一个测试类演示一下
//1.字符串转换为数值型数据
String ageStr = "29";
int age1 = Integer.parseInt(ageStr);
String scoreStr = 3.14;
double score = Double.prarseDouble(scoreStr);
//2.整数转换为字符串,以下几种方式都可以(挑中你喜欢的记一下)
Integer a = 23;
String s1 = Integer.toString(a);
String s2 = a.toString();
String s3 = a+"";
String s4 = String.valueOf(a);
2.1 Math类
Math是数学的意思,该类提供了很多个进行数学运算的方法,如求绝对值,求最大值,四舍五入等,话不多说,直接上代码。
public class MathTest {
public static void main(String[] args) {
// 目标:了解下Math类提供的常见方法。
// 1、public static int abs(int a):取绝对值(拿到的结果一定是正数)
// public static double abs(double a)
System.out.println(Math.abs(-12)); // 12
System.out.println(Math.abs(123)); // 123
System.out.println(Math.abs(-3.14)); // 3.14
// 2、public static double ceil(double a): 向上取整
System.out.println(Math.ceil(4.0000001)); // 5.0
System.out.println(Math.ceil(4.0)); // 4.0
// 3、public static double floor(double a): 向下取整
System.out.println(Math.floor(4.999999)); // 4.0
System.out.println(Math.floor(4.0)); // 4.0
// 4、public static long round(double a):四舍五入
System.out.println(Math.round(3.4999)); // 3
System.out.println(Math.round(3.50001)); // 4
// 5、public static int max(int a, int b):取较大值
// public static int min(int a, int b):取较小值
System.out.println(Math.max(10, 20)); // 20
System.out.println(Math.min(10, 20)); // 10
// 6、 public static double pow(double a, double b):取次方
System.out.println(Math.pow(2, 3)); // 2的3次方 8.0
System.out.println(Math.pow(3, 2)); // 3的2次方 9.0
// 7、public static double random(): 取随机数 [0.0 , 1.0) (包前不包后)
System.out.println(Math.random());
}
}
2.2 System类
接下来,学习一个System类,这是系统类,提供了一些获取获取系统数据的方法。比如获取系统时间。
/**
* 目标:了解下System类的常见方法。
*/
public class SystemTest {
public static void main(String[] args) {
// 1、public static void exit(int status):
// 终止当前运行的Java虚拟机。
// 该参数用作状态代码; 按照惯例,非零状态代码表示异常终止。
System.exit(0); // 人为的终止虚拟机。(不要使用)
// 2、public static long currentTimeMillis():
// 获取当前系统的时间
// 返回的是long类型的时间毫秒值:指的是从1970-1-1 0:0:0开始走到此刻的总的毫秒值,1s = 1000ms
long time = System.currentTimeMillis();
System.out.println(time);
for (int i = 0; i < 1000000; i++) {
System.out.println("输出了:" + i);
}
long time2 = System.currentTimeMillis();
System.out.println((time2 - time) / 1000.0 + "s");
}
}
2.2 Arrays类
2.1.1 Arrays基本使用
我们先认识一下Arrays是干什么用的,Arrays是操作数组的工具类,它可以很方便的对数组中的元素进行遍历、拷贝、排序等操作。
下面我们用代码来演示一下:遍历、拷贝、排序等操作。需要用到的方法如下
/**
* 目标:掌握Arrays类的常用方法。
*/
public class ArraysTest1 {
public static void main(String[] args) {
// 1、public static String toString(类型[] arr): 返回数组的内容
int[] arr = {10, 20, 30, 40, 50, 60};
System.out.println(Arrays.toString(arr));
// 2、public static 类型[] copyOfRange(类型[] arr, 起始索引, 结束索引) :拷贝数组(指定范围,包前不包后)
int[] arr2 = Arrays.copyOfRange(arr, 1, 4);
System.out.println(Arrays.toString(arr2));
// 3、public static copyOf(类型[] arr, int newLength):拷贝数组,可以指定新数组的长度。
int[] arr3 = Arrays.copyOf(arr, 10);
System.out.println(Arrays.toString(arr3));
// 4、public static setAll(double[] array, IntToDoubleFunction generator):把数组中的原数据改为新数据又存进去。
double[] prices = {99.8, 128, 100};
// 0 1 2
// 把所有的价格都打八折,然后又存进去。
Arrays.setAll(prices, new IntToDoubleFunction() {
@Override
public double applyAsDouble(int value) {
// value = 0 1 2
return prices[value] * 0.8;
}
});
System.out.println(Arrays.toString(prices));
// 5、public static void sort(类型[] arr):对数组进行排序(默认是升序排序)
Arrays.sort(prices);
System.out.println(Arrays.toString(prices));
}
}
2.1.2 Arrays操作对象数组
刚才我们使用Arrays操作数组时,数组中存储存储的元素是int类型、double类型,是可以直接排序的,而且默认是升序排列。
如果数组中存储的元素类型是自定义的对象,如何排序呢?接下来,我们就学习一下Arrays如何对对象数组进行排序。
首先我们要准备一个Student类,代码如下:
public class Student implements Comparable<Student>{
private String name;
private double height;
private int age;
public Student(String name, double height, int age) {
this.name = name;
this.height = height;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", height=" + height +
", age=" + age +
'}';
}
}
然后再写一个测试类,往数组中存储4个学生对象,代码如下。此时,运行代码你会发现是会报错的。
public class ArraysTest2 {
public static void main(String[] args) {
// 目标:掌握如何对数组中的对象进行排序。
Student[] students = new Student[4];
students[0] = new Student("蜘蛛精", 169.5, 23);
students[1] = new Student("紫霞", 163.8, 26);
students[2] = new Student("紫霞", 163.8, 26);
students[3] = new Student("至尊宝", 167.5, 24);
// 1、public static void sort(类型[] arr):对数组进行排序。
Arrays.sort(students);
System.out.println(Arrays.toString(students));
}
}
上面的代码为什么会报错呢?因为Arrays根本就不知道按照什么规则进行排序。为了让Arrays知道按照什么规则排序,我们有如下的两种办法。
-
排序方式1:让Student类实现Comparable接口,同时重写compareTo方法。Arrays的sort方法底层会根据compareTo方法的返回值是正数、负数、还是0来确定谁大、谁小、谁相等。代码如下:
public class Student implements Comparable<Student>{
private String name;
private double height;
private int age;
//...get、set、空参数构造方法、有参数构造方法...自己补全
// 指定比较规则
// this o
@Override
public int compareTo(Student o) {
// 约定1:认为左边对象 大于 右边对象 请您返回正整数
// 约定2:认为左边对象 小于 右边对象 请您返回负整数
// 约定3:认为左边对象 等于 右边对象 请您一定返回0
/* if(this.age > o.age){
return 1;
}else if(this.age < o.age){
return -1;
}
return 0;*/
//上面的if语句,也可以简化为下面的一行代码
return this.age - o.age; // 按照年龄升序排列
// return o.age - this.age; // 按照年龄降序排列
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", height=" + height +
", age=" + age +
'}';
}
}
-
排序方式2:在调用
Arrays.sort(数组,Comparator比较器);
时,除了传递数组之外,传递一个Comparator比较器对象。Arrays的sort方法底层会根据Comparator比较器对象的compare方法方法的返回值是正数、负数、还是0来确定谁大、谁小、谁相等。代码如下
public class ArraysTest2 {
public static void main(String[] args) {
// 目标:掌握如何对数组中的对象进行排序。
Student[] students = new Student[4];
students[0] = new Student("蜘蛛精", 169.5, 23);
students[1] = new Student("紫霞", 163.8, 26);
students[2] = new Student("紫霞", 163.8, 26);
students[3] = new Student("至尊宝", 167.5, 24);
// 2、public static <T> void sort(T[] arr, Comparator<? super T> c)
// 参数一:需要排序的数组
// 参数二:Comparator比较器对象(用来制定对象的比较规则)
Arrays.sort(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
// 制定比较规则了:左边对象 o1 右边对象 o2
// 约定1:认为左边对象 大于 右边对象 请您返回正整数
// 约定2:认为左边对象 小于 右边对象 请您返回负整数
// 约定3:认为左边对象 等于 右边对象 请您一定返回0
// if(o1.getHeight() > o2.getHeight()){
// return 1;
// }else if(o1.getHeight() < o2.getHeight()){
// return -1;
// }
// return 0; // 升序
return Double.compare(o1.getHeight(), o2.getHeight()); // 升序
// return Double.compare(o2.getHeight(), o1.getHeight()); // 降序
}
});
System.out.println(Arrays.toString(students));
}
}
四.集合
1.特点: 它是一种容器,用来存储数据;
与数组不同,集合大小是可变的
2.学习要点:创建容器对象的方法,
增删改查的 方法
容器的其他特点
1.ArrayList
创建ArrayLlst集合的对象:
ArrayList list = new ArrayList();
增删改查的方法:
总结
五.泛型
六.IO流
- 文件的概念,常用操作
- 原理,分类
- 节点流和处理流
- 输入流
- 输出流
七.线程
- 并发,并行,生命周期
- 线程的两种创建方式
- 线程同步
- 线程通信
- 线程池
- 锁
八.网络通信
-
网络基础
-
InetAddress
-
Socket
-
TCP编程
-
UDP编程