1.代码块
1.1代码块引出
有时我们在使用构造方法时,除了进行属性的初始化外还需要使用一些其他的语句,以便更好的实现程序的功能,比如添加一些输出语句;
1.2 局部代码块
public void show(){
System.out.println("show");
{
System.out.println("代码块");
{
System.out.println("嵌套代码块");
}
}
}
1.3 构造代码块
在每个构造器里面都输出一句话,在构造方法中有多个相同的输出语句,代码显得冗余。
为了加强代码的重用性,我们可以使用代码块进行简化:
{
System.out.printin("此构造方法被调用了“);
}
1.4 静态代码块
static {
System.out.println("静态代码块初始化数据");
}
1.5 代码块调用次数
1:静态代码块:静态代码块随着类的加载被执行,只会被执行一次;
2:普通代码块每创建一个对象就执行一次;
修饰符 | 执行顺序 | 执行次数 | |
---|---|---|---|
静态代码块 | static | 优先执行 | 随着类加载执行一次 |
普通代码块 | 无 | 在静态代码块之后执行 | 每创建一个对象就执行一次 |
1.6 加载时机
静态代码块>构造代码块>普通代码块
2.内部类
我们之前在类中定义了 变量 方法 代码块 那能不能类中定义类呢?
接下来,我们来学习内部类,学完内部类之后,要求大家知道内部类的格式和使用。在讲解内部类之前,我们先对内部类做一个简单的描述。内部类,顾名思义,就是在一个类中定义一个类。我们来看一下格式,这就是内部类的定义格式。讲解完毕格式和和针对格式给出的范例,以及访问特点后,我们到代码中演示一下。
2.1 内部类概念&定义格式&特点
2.1.1 内部类概念
内部类:就是在一个类中定义一个类。举例:在一个类A的内部定义一个类B,类B就被称为内部类
2.1.2 内部类定义格式
public class 类名{ 修饰符 class 类名{ }}
范例:
public class Outer { public class Inner { } }
2.1.3 内部类的访问特点
1.内部类可以直接访问外部类的成员,包括私有
2.外部类要访问内部类的成员,必须创建对象
eg:
public class Outer {
private String OuterName;
public void showOuter(){
System.out.println("外部类");
// System.out.println(InnerName);
}
public class Inner {
private String InnerName;
public void showInner(){
System.out.println("内部类");
System.out.println(OuterName);
}
}
}
2.2 内部类分类
按照内部类在类中定义的位置不同,可以分为如下两种形式
内部类位置:
1.成员内部类:在类里面的成员位置
延伸:静态内部类,用static修饰的成员内部类
2.局部内部类: 在方法里面
延伸:匿名内部类,定义在方法内部用来实现接口或者类名的
2.2.1 成员内部类
成员内部类,外界如何创建对象使用呢?
格式:外部类.内部类 对象名 = new 外部类对象().new 内部类对象();
范例:
Outer.Inner oi = new Outer().new Inner();
eg:
public class Test {
public static void main(String[] args) {
Outer outer = new Outer();
outer.showOuter();
Outer.Inner oi = new Outer().new Inner();
oi.showInner();
}
}
面试题:
注意:在成员内部类中访问所在外部类对象, 格式: 外部类名.this
拓展
成员内部类的访问拓展:
1、成员内部类中是否可以直接访问外部类的静态成员?
可以,外部类的静态成员只有一份可以被共享访问。
2、成员内部类的实例方法中是否可以直接访问外部类的实例成员?
可以的,因为必须先有外部类对象,才能有成员内部类对象,所以可以直接访问外部类对象的实例成员。
2.2.2 静态内部类
有static 修饰的成员内部类
格式:
public class Outer{
// 静态成员内部类
public static class Inner{
}
}
静态内部类创建对象的格式:
格式: 外部类名.内部类名 对象名 = new 外部类构造器.new 内部类构造器();
范例:
Outer.Inner in = new Outer.Inner();
eg:
public class StaticOuter {
public void staticOuter(){
System.out.println("外部类");
}
public static class StaticInner{
public void staticInner(){
System.out.println("静态内部类");
}
}
}
public class StaticInnerTest {
public static void main(String[] args) {
StaticOuter.StaticInner in = new StaticOuter.StaticInner();
in.staticInner();
}
}
拓展
静态内部类的访问拓展:
1、静态内部类中是否可以直接访问外部类的静态成员?
可以,外部类的静态成员只有一份可以被共享访问。
2、静态内部类中是否可以直接访问外部类的实例成员?
不可以的,外部类的实例成员必须用外部类对象访问。
注意:静态内部类开发中实际上用的还是比较少。
2.2.3 局部内部类
局部内部类是在方法中定义的类,所以外界是无法直接使用,需要在方法内部创建对象并使用
该类可以直接访问外部类的成员,也可以访问方法内的局部变量
局部内部类:放在方法、代码块、构造器等执行体中
eg:
public class A {
void say(){
class B {
void sayJuBu(){
System.out.println("局部内部类");
}
}
B b = new B();
b.sayJuBu();
}
public static void main(String[] args) {
A a = new A();
a.say();
}
}
2.2.4 匿名内部类
概述:匿名内部类本质上是一个特殊的局部内部类(定义在方法内部)
前提:存在一个类或者接口,这里的类可以是具体类也可以是抽象类
格式:
new 类名或者接口名() {
重写方法;
};
范例:
AnonymousOuter ao = new AnonymousOuter() {
@Override
public void show() {
System.out.println("匿名内部类");
}
};
ao.show();
本质:是一个继承了该类的子类匿名对象,或者是一个实现了该接口的实现类匿名对象
实现:new 接口(){} 实现接口
补充:new 类(){} 继承类
public abstract class AnonymousOuter {
public abstract void show();
public static void show2(){
AnonymousOuter ao = new AnonymousOuter() {
@Override
public void show() {
System.out.println("匿名内部类");
}
};
ao.show();
}
public void show3(){//多余!
AnonymousOuter ao = new AnonymousOuter() {
@Override
public void show() {
System.out.println("匿名内部类");
}
};
ao.show();
}
public static void main(String[] args) {
AnonymousOuter.show2();
//直接在此位置创建对象 就会创建一个匿名内部类格式
AnonymousOuter ao = new AnonymousOuter() {
@Override
public void show() {
System.out.println("简单方式创建匿名内部类");
}
};
}
}
继承关系中:
public abstract class Animal {
public abstract void showAnimal();
}
public abstract class Dog extends Animal{
public static void main(String[] args) {
Dog dog = new Dog() {
@Override
public void showAnimal() {
System.out.println("重写父类");
}
};
}
}
接口关系中 略
总结:
匿名内部类的作用?
方便创建子类对象,最终目的为了简化代码编写。
匿名内部类的格式?
Animal a = new Animal() {
public void run() {
}
};
a. run();
匿名内部类的特点?
匿名内部类是一个没有名字的内部类。
匿名内部类写出来就会产生一个匿名内部类的对象。
匿名内部类的对象类型相当于是当前new的那个的类型的子类类型。
3.Lambda表达式
3.1 Lambda概述
Lambda表达式是JDK 8开始后的一种新语法形式。
作用:简化匿名内部类的代码写法。
Lambda表达式的格式
(匿名内部类被重写方法的形参列表) -> { 被重写方法的方法体代码。}
注:-> 是语法形式,无实际含义
Lambda表达式的简化格式
()->{}
注意:Lambda表达式只能简化函数式接口的匿名内部类的写法形式
3.2 函数式接口
什么是函数式接口?
首先必须是接口、其次接口中有且仅有一个抽象方法的形式
通常我们会在接口上加一个**@FunctionalInterface**注解,标记该接口必须是满足函数式接口
eg:
@FunctionalInterface//函数式接口
public interface A {
void show();
}
public class AImpl implements A{
@Override
public void show() {
System.out.println("A");
}
public static void main(String[] args) {
A a = () ->{
System.out.println("lambda表达式完成");
};
a.show();
}
}
函数式编程思想概述
在数学中,函数就是有输入量、输出量的一套计算方案,也就是“拿数据做操作”
面向对象思想强调“必须通过对象的形式来做事情”
函数式思想则尽量忽略面向对象的复杂语法:“强调做什么,而不是以什么形式去做”
我们要学习的Lambda表达式就是函数式思想的体现
3.3 Lambda 表达式的省略模式
省略规则:
1.如果参数有且仅有一个,那么小括号可以省略
2.参数类型可以省略。但是有多个参数的情况下,不能只省略一个
3.如果代码块的语句只有一条,可以省略大括号和分号,甚至是return
eg:
public interface B {
void show();
}
@Override
public void show() {
B b = new B() {
@Override
public void show() {
}
};
// B b = ()->{System.out.println();}; //格式1
// B b = ()->System.out.println();//省略大括号和分号 甚至是return
}
有参数
@FunctionalInterface
public interface B {
void eat(int weight,String name);
}
public static void main(String[] args) {
// 一个参数 小括号可以省略
//B b = weight -> System.out.println(weight);
// 多个参数
// B b = (int weight,String name)-> System.out.println(weight+name);
// B b = (int weight,name)-> System.out.println(weight+name);
}
有返回值
@FunctionalInterface
public interface B {
int show();
}
public class BImpl implements B{
@Override
public int show() {
return 0;
}
}
public static void main(String[] args) {
B b = ()->0;
}
}
3.4 Lambda 表达式和匿名内部类的区别
所需类型不同
匿名内部类:可以是接口,也可以是抽象类,还可以是具体类
Lambda表达式:只能是接口
使用限制不同
如果接口中仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类
如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用Lambda表达式
实现原理不同
匿名内部类:编译之后,产生一个单独的.class字节码文件
Lambda表达式:编译之后,你没有看到一个单独的.class字节码文件。对应的字节码会在运行的时候动态生成
3.5 Lambda表达式简化Comparator接口的匿名形式
Arrays.sort(age,(o1,o2)->{
return o1-o2;
});
//省略 return;
Arrays.sort(age,(o1,o2)-> o1-o2);
4.API
在lambda表达式中我们用到了Arrays.sort() 拿着到底是个什么方法? 接下来我们接着对这些api来进行学习。
4.1 Scanner
相同:
next() 和 nextLine() 读取的结果都是 String 类型,返回 string 类型
区别:
next() 不会读取字符前/后的空格/Tab键,只读取字符(忽略空格回车等等),开始读取字符(字符前后不算)直到遇到空格/Tab键/回车截止;( 包括nextInt()、nextDouble()、nextFloat()等 )遇到了空格, 就不再录入数据了 。
结束标记: 空格, tab键。
nextLine() 读取字符前后的空格/Tab键,直到回车键截止。可以将数据完整的接收过来。读取一行,注意到如果是一行的话,空格不作为分隔符,一行一行的取,以回车(换行)结束一次取值
结束标记: 回车换行符。
4.2 String
4.2.1 比较
-
-
boolean equals(Object anObject)
将此字符串与指定对象进行比较。boolean
equalsIgnoreCase(String anotherString)
将此String
与其他String
比较,忽略案例注意事项。
-
案例:
需求:模拟用户登录,一共有三次机会,登陆之后给出相对应的提示
分析:
1.定义两个字符串类型的变量,模拟已经存在的用户名和密码
2.键盘录入用户名和密码
3.比对
equals之前放值,后面放变量。
public static void main(String[] args) {
String username = "zhangsan";
String password = "123456";
for (int i = 0; i < 3; i++) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名:");
String user = sc.next();
System.out.println("请输入密码:");
String pass = sc.next();
if (user.equals(username)) {
if (pass.equals(password)){
System.out.println("登陆成功!");
break;
} else {
System.out.println("密码错误,你还有" + (2 - i) + "次机会");
}
} else {
System.out.println("用户名错误,你还有" + (2 - i) + "次机会");
}
}
}
4.2.2 String字符串的遍历
-
-
char[] toCharArray()
将此字符串转换为新的字符数组。char charAt(int index)
返回char
指定索引处的值。int length()
返回此字符串的长度。
-
String s1 = "aabbccddeeffgg";
char[] chars = s1.toCharArray();
for (int i = 0; i < chars.length; i++){
System.out.println(chars[i]);
}
案例
需求:建兰路入一个字符串,统计该字符串中大写字母字符,小写字母字符,数字字符出现的字数(不考试其他字符)
例如:aAb3&c2B*4CD1
小写字母:3个
大写字母:4个
数字字母:4个
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入要统计的字符串:");
String s = sc.next();
int count1 = 0;
int count2 = 0;
int count3 = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) >= 'A' && s.charAt(i) <= 'Z') {
count1++;
} else if (s.charAt(i) >= 'a' && s.charAt(i) <= 'z') {
count2++;
} else if (s.charAt(i) >= '0' && s.charAt(i) <= '9') {
count3++;
}
}
System.out.println(count1);
System.out.println(count2);
System.out.println(count3);
}
4.3 String字符串的截取方式
-
-
String substring(int beginIndex, int endIndex) 返回一个字符串,该字符串是此字符串的子字符串。 String substring(int beginIndex)返回一个字符串,该字符串是此字符串的子字符串。
-
案例:
需求:以字符串的形式从键盘接收一个手机号,将中间四位号码屏蔽最终效果为:156****1234
分析:
1.键盘录入字符串
2.截取前三位
3.截取后四位
4.前三位 +****+后四位
eg:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String r = sc.next();
String s1 = r.substring(0,3);
String s2 = r.substring(r.length()-4);
System.out.println(s1);
System.out.println(s2);
String s3 = s1 +"****"+s2;
System.out.println(s3);
}
4.4 字符串中常用的方法
public static void main(String[] args) {
String s1 = "7788999";
String replace = s1.replace('7', '9');
System.out.println(replace);
}
public static void main(String[] args) {
String s1 = "a,a,b,b,c,c,d,d,e,e,f,f,g,g";
String s2 = s1.replace(',', '*');
String[] split = s2.split("\\*");
for (int i = 0; i < split.length; i++) {
System.out.println(split[i]);
}
}
//在这里 用 * \ + | 会有问题
//原因:因为+、*、|、\等符号在正则表达示中有相应的不同意义,所以在使用时要进行转义处理
// 解决方法:
// split("\\*")或者split("[*]")
4.3 System
public static void main(String[] args) {
int[]arr = {1,2,3,4,5,6};
int[]arr2 = new int[10];
System.arraycopy(arr,0,arr2,5,5);
for (int i = 0; i < arr2.length; i++) {
System.out.println(arr2[i]);
}
}
4.4 Arrays工具类
我们在之前学习数组的时候,
数组操作工具类,专门用于操作数组元素的。
Arrays类的常用API
方法名 | 说明 |
---|---|
public static String toString(类型[] a) | 返回数组的内容(字符串形式) |
public static void sort(类型[] a) | 对数组进行默认升序排序 |
public static void sort(类型[] a, Comparator<? super T> c) | 使用比较器对象自定义排序 |
public static int binarySearch(int[] a, int key) a - 要搜索的数组 key - 要搜索的值 | 必须对数组进行升序排序(如sort(int[])方法)。 二分搜索数组中的数据,存在返回索引,不存在返回-1,如果存在相同值,则会根据数组的长度发生改变 |
引出算法学习中的二分查找
Arrays类的排序方法
方法名 | 说明 |
---|---|
public static void sort(类型[] a) | 对数组进行默认升序排序 |
public static void sort(类型[] a, Comparator<? super T> c) | 使用比较器对象自定义排序 |
自定义排序规则
设置Comparator接口对应的比较器对象,来定制比较规则。
如果认为左边数据 大于 右边数据 返回正整数
如果认为左边数据 小于 右边数据 返回负整数
如果认为左边数据 等于 右边数据 返回0
public static void main(String[] args) {
Integer[] arr = {1,1, 1, 1, 2, 3, 4, 5, 6, 6, 5, 3, 2, 4, 6, 6, 6, 6, 6};
// System.out.println(Arrays.toString(arr));
// Arrays.sort(arr);
// System.out.println(Arrays.toString(arr));
Arrays.sort(arr, (o1, o2) -> o1 - o2);
// System.out.println(Arrays.toString(arr));
int i = Arrays.binarySearch(arr, 6);
System.out.println(i);
}
4.5 Object
4.5.1 Object 类的概述
每个类都可以将 Object 作为父类。所有类都直接或者间接的继承自该类构造方法:public Object()
回想面向对象中,为什么说子类的构造方法默认访问的是父类的无参构造方法?因为它们的顶级父类只有无参构造方法
4.5.2 Object的toString()
String | toString() 返回对象的字符串表示形式。 |
---|
补充 什么是hash值?
hash值(hashcode)可以理解为唯一编码、摘要值等,具体实现可能是内存地址,在java中可用于识别两个变量是否其实是同个对象。
现在我有两个对象 那我如何比较这两个对象的地址值呢?
4.5.3 equals()方法
==行吗?
public boolean equals(Object obj) {
return (this == obj);
}
底层原理就是 == 号~
4.6 Objects 类的常用方法
方法名 | 说明 |
---|---|
public static String toString(对象) | 返回参数中对象的字符串表示形式,底层会先进行非空判断。 |
public static Boolean equals(对象,对象) | 比较两个对象的,底层会先进行非空判断,从而可以避免空指针异常。再进行equals比较 |
public static Boolean isNull(对象) | 判断对象是否为空 |
public static Boolean nonNull(对象) | 判断对象是否不为空 |
B b = new B();
String s = Objects.toString(b);
System.out.println(s);
String s1 = b.toString();
System.out.println(s1);
1.Objects的toString和Object的toString区别
查看源码
Object的toString
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
Objects的toString
public static String toString(Object o) {
return String.valueOf(o);
}
继续进入valueOf()
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
我们可以看到这里三元运算符做了一个非空判断。
2.同理对比两个的equals方法
Object
public boolean equals(Object obj) {
return (this == obj);
}
Objects
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
Objects的equals做了非空判断
4.7.Math
包含执行基本数字运算的方法
方法名 | 说明 |
---|---|
public static int abs(int a) | 获取参数绝对值 |
public static double ceil(double a) | 向上取整 |
public static double floor(double a) | 向下取整 |
public static int round(float a) | 四舍五入 |
public static int max(int a,int b) | 获取两个int值中的较大值 |
public static double pow(double a,double b) | 返回a的b次幂的值 |
public static double random() | 返回值为double的随机值,返回[0.0,1.0) |
System.out.println(Math.abs(-5));
System.out.println(Math.ceil(5.555));
System.out.println(Math.floor(5.6));
System.out.println(Math.round(5.7));
double random = Math.random();
System.out.println(Math.max(5, 10));
System.out.println(Math.pow(2, 3));
System.out.println(random);
4.8 BigDecimal
为什么要用BigDecimal?
首先看一个现象
System.out.println(0.2+0.1);
System.out.println(0.3-0.1);
System.out.println(0.2*0.1);
System.out.println(0.3/0.1);
可以看到执行结果为
0.30000000000000004
0.19999999999999998
0.020000000000000004
2.9999999999999996
因为不论是float 还是double都是浮点数,而计算机是二进制的,浮点数会失去一定的精确度。
注:根本原因是:十进制值通常没有完全相同的二进制表示形式;十进制数的二进制表示形式可能不精确。只能无限接近于那个值
但是,在项目中,我们不可能让这种情况出现,特别是金融项目,因为涉及金额的计算都必须十分精确,你想想,如果你的支付宝账户余额显示193.99999999999998,那是一种怎么样的体验?
BigDecimal类使用
1.创建对象
构造器 | 描述 |
---|---|
BigDecimal(int) | 创建一个具有参数所指定整数值的对象。 |
BigDecimal(double) | 创建一个具有参数所指定双精度值的对象。 //不推荐使用 |
BigDecimal(long) | 创建一个具有参数所指定长整数值的对象。 |
BigDecimal(String) | 创建一个具有参数所指定以字符串表示的数值的对象。//推荐使用 |
static BigDecimal valueOf(double val) | 代替BigDecimal(double) |
eg:
BigDecimal bd1 = new BigDecimal(1);
BigDecimal bd2 = new BigDecimal(2);
System.out.println(bd1.add(bd2));//3
BigDecimal bd3 = new BigDecimal(10000000000l);
BigDecimal bd4 = new BigDecimal(20000000000l);
System.out.println(bd3.add(bd4));//30000000000
BigDecimal bd5 = new BigDecimal(0.1);
BigDecimal bd6 = new BigDecimal(0.2);
System.out.println(bd5.add(bd6));//0.3000000000000000166533453693773481063544750213623046875
BigDecimal d1 = new BigDecimal("0.2");
BigDecimal d2 = new BigDecimal("0.1");
System.out.println(d1.add(d2));//0.3
BigDecimal b1 = BigDecimal.valueOf(0.1);
BigDecimal b2 = BigDecimal.valueOf(0.2);
System.out.println(b1.add(b2));//0.3
2.常用方法
eg:
BigDecimal bd1 = new BigDecimal(0.1);
BigDecimal bd2 = new BigDecimal(0.2);
System.out.println(bd1.subtract(bd2));
System.out.println(BigDecimal.valueOf(0.1).subtract(BigDecimal.valueOf(0.2)));
System.out.println(new BigDecimal("0.3").subtract(new BigDecimal("0.5")));
System.out.println(BigDecimal.valueOf(0.1).multiply(BigDecimal.valueOf(0.2)));
System.out.println(BigDecimal.valueOf(0.1).divide(BigDecimal.valueOf(0.2)));
BigDecimal类使用
3.divide除法细节
BigDecimal divide = b1.divide(参与运算的对象,小数点后精确到多少位,舍入模式);
参数1:表示参与运算的BigDecimal对象
参数2:表示小数点后精确到多少位
参数3:舍入模式
名词 | 舍入模式 |
---|---|
RoundingMode.CEILING | 向正无穷方向舍入 |
RoundingMode.DOWN | 向零方向舍入 去尾法 |
RoundingMode.FLOOR | 向负无穷方向舍入 |
RoundingMode.HALF_DOW | 向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向下舍入, 例如1.55 保留一位小数结果为1.5 |
RoundingMode.HALF_EVEN | 向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,如果保留位数是奇数,使用ROUND_HALF_UP,如果是偶数,使用ROUND_HALF_DOWN |
RoundingMode.HALF_UP | “四舍五入” |
RoundingMode.UNNECESSARY | 计算结果是精确的,不需要舍入模式 |
RoundingMode.UP | 向远离0的方向舍入,进1法。 |
BigDecimal divide = b1.divide(b2, 10, RoundingMode.FLOOR);
System.out.println(divide);
5.包装类
5.1 为什么需要java包装类?
Java语言是一个面向对象的语言,但是Java中的基本数据类型却是不面向对象的,将每个基本数据类型设计一个对应的类进行代表,这种方式增强了Java面向对象的性质。
5.2 包装类好处
1.包装类的存在弥补了基本数据类型的不足。在集合类中,无法将int 、double等类型放进去,因为集合的容器要求元素是Object类型。
2.包装类还为基本类型添加了属性和方法,丰富了基本类型的操作。
5.3 包装类概述
将基本数据类型 包装成类(变成引用数据类型)
基本数据类型 | 包装类型 |
---|---|
boolean | Boolean |
char | Character |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
5.4 Integer类
将基本数据类手动包装成类。
构造器 | 描述 |
---|---|
Integer(int value) | 构造一个新分配的 Integer 对象,该对象表示指定的 int 值。 |
static Integer valueOf(int i) | 将int类型的i值包装成Integer类型 |
eg:
Integer i1 = new Integer(5);
Integer i3 = 6;
System.out.println(i1);
System.out.println(i3);
Integer i2 = Integer.valueOf(5);
System.out.println(i2);
5.5 手动装箱和自动装箱
装箱:把基本数据类型转换为对应的包装类类型
拆箱:把包装类类型转换为对应的基本数据类型
5.5.1手动装箱
Integer integer = Integer.valueOf(num);
5.5.2.自动装箱
Integer i = 100; // 自动装箱
i += 200; // i = i + 200; i + 200 自动拆箱;i = i + 200; 是自动装箱
5.6 手动拆箱和自动拆箱
5.6.1 手动拆箱
public int intValue() 将 Integer的值作为 int 。
//手动拆箱
Integer num = 5;
int i = num.intValue();
System.out.println(i);
5.6.2 自动拆箱
int num=10;
Integer num2=10;
int i=num+num2;
注意:在使用包装类类型的时候,如果做操作,最好先判断是否为 null
我们推荐的是,只要是对象,在使用前就必须进行不为 null 的判断
5.7 Integer的成员方法
方法名 | 说明 |
---|---|
public static Integer valueOf(String s) | 返回一个 Integer 对象,保存指定的值为 String 。 |
static int parseInt(String s) | 将字符串类型的整数变成int类型的整数 |
Integer i2 = new Integer("123");
System.out.println(i2);
System.out.println(Integer.parseInt("123"));
5.8 int 和 String 的相互转换
基本类型包装类的最常见操作就是:用于基本类型和字符串之间的相互转换
-
int 转换为 String
方式一:加双引号即可
方式二:public static String valueOf(int i):返回 int 参数的字符串表示形式。该方法是 String 类中的方法 -
String 转换为 int
public static int parseInt(String s):将字符串解析为 int 类型。该方法是 Integer 类中的方法
5.9 练习
public static void main(String[] args) {
String s = "10,50,30,20,40";
String[] srr = s.split(",");
Integer[] arr = new Integer[srr.length];
System.out.println(Arrays.toString(srr));
for (int i = 0; i < srr.length; i++) {
Integer i1 = Integer.parseInt(srr[i]);
arr[i] = i1;
}
System.out.println(Arrays.toString(arr));
int max = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i]>max){
max = arr[i];
}
}
System.out.println(max);
}
6.算法
6.1 冒泡排序
-
冒泡排序的思想
从头开始两两比较,把较大的元素与较小的元素进行交换
每轮把当前最大的一个元素存入到数组当前的末尾。 -
冒泡排序的实现步骤。
定义一个外部循环控制总共需要冒几轮(数组的长度-1)
定义一个内部循环,控制每轮依次往后比较几个位置(数组长度-i-1)。
如果当前位置的元素值>后一个位置的元素值,两者交换。
int arr[] = {12, 23, 43, 23, 2, 3, 22};
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 temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + ",");
}
6.2 选择排序
选择排序的思想
每轮选择当前位置,开始找出后面的较小值与该位置交换
选择排序的关键
确定总共需要选择几轮: 数组的长度-1.
控制每轮从以前位置为基准,与后面元素选择几次。
6.3 二分法查找
1、数组的二分查找的实现步骤是什么样的?
定义变量记录左边和右边位置。
使用while循环控制查询(条件是左边位置<=右边位置)
循环内部获取中间元素索引
判断当前要找的元素如果大于中间元素,左边位置=中间索引+1
判断当前要找的元素如果小于中间元素,右边位置=中间索引-1
判断当前要找的元素如果等于中间元素,返回当前中间元素索引。
索引值没有小数 如果/2是小数 比如3.5 那么中位数索引为3
6.4 递归
递归概述:以编程的角度来看,递归指的是方法定义中调用方法本身的现象
递归解决问题的思路:
把一个复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解
递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算
递归解决问题要找到两个内容:
递归出口:否则会出现内存溢出
递归规则:与原问题相似的规模较小的问题
递归概述:以编程的角度来看,递归指的是方法定义中调用方法本身的现象
做一个小案例:
求1-100之间的和
案例:递归求阶乘
需求:
用递归求5的阶乘,并把结果在控制台输出
分析:
阶乘:一个正整数的阶乘是所有小于及等于该数的正整数的积,自然数n的阶乘写作n!
5! = 5*4*3*2*1
递归出口:1! = 1
递归规则:n!=n*(n-1)!
5! = 5*4!
思路:
定义一个方法,用于递归求阶乘,参数为一个int类型的变量
在方法内部判断该变量的值是否是1
是:返回1
不是:返回n*(n-1)!
调用方法
输出结果
t j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + “,”);
}
## 6.2 选择排序
**选择排序的思想**
每轮选择当前位置,开始找出后面的较小值与该位置交换
**选择排序的关键**
确定总共需要选择几轮: 数组的长度-1.
控制每轮从以前位置为基准,与后面元素选择几次。
[外链图片转存中...(img-pPyyzmcE-1715492606387)]
## 6.3 二分法查找
1、数组的二分查找的实现步骤是什么样的?
定义变量记录左边和右边位置。
使用while循环控制查询(条件是左边位置<=右边位置)
循环内部获取中间元素索引
**判断当前要找的元素如果大于中间元素,左边位置=中间索引+1**
**判断当前要找的元素如果小于中间元素,右边位置=中间索引-1**
**判断当前要找的元素如果等于中间元素,返回当前中间元素索引。**
索引值没有小数 如果/2是小数 比如3.5 那么中位数索引为3
## 6.4 递归
递归概述:以编程的角度来看,递归指的是方法定义中调用方法本身的现象
递归解决问题的思路:
把一个复杂的问题层层转化为一个**与原问题相似的规模较小**的问题来求解
递归策略只需**少量的程序**就可描述出解题过程所需要的多次重复计算
递归解决问题要找到两个内容:
递归出口:否则会出现内存溢出
递归规则:与原问题相似的规模较小的问题
递归概述:以编程的角度来看,递归指的是方法定义中调用方法本身的现象
**做一个小案例:**
**求1-100之间的和**
**案例:递归求阶乘**
**需求:**
用递归求5的阶乘,并把结果在控制台输出
**分析:**
阶乘:一个正整数的阶乘是所有小于及等于该数的正整数的积,自然数n的阶乘写作n!
5! = 54321
递归出口:1! = 1
递归规则:n!=n*(n-1)!
5! = 5*4!
**思路:**
定义一个方法,用于递归求阶乘,参数为一个int类型的变量
在方法内部判断该变量的值是否是1
是:返回1
不是:返回n*(n-1)!
调用方法
输出结果