Java入门-类

1.抽象类及抽象方法

1.1 抽象方法
1.1.1 含义

没有代码块并且使用abstract修饰的方法

1.1.2 注意

抽象方法必须在抽象类中

1.1.3 应用场景

​ 该类里的某个方法不太好实现并且该方法又应该在该类里,就不写代码块,将该方法变为抽象方法,抽象方法交给非抽象的子类去实现。

1.1.4 代码格式如下:

abstract修饰符.

public abstract class Person {
    //抽象方法:交给非抽象的子类去实现
	public abstract void eat();
}

//在非抽象的子类方法中去实现方法
public class Japanese extends Person {
    @Override
	public void eat() {
		System.out.println(super.getName() + "吃米饭");
	}	
}
1.2 抽象类

​ 使用abstract修饰的类.

1.3 深入抽象类和抽象方法(面试题)

1.可以使用new关键字来创建抽象类对象吗?

​ 答:不可以

​ 补充:匿名内部类的步骤:

​ (1).顶层建立一个匿名类(没有名字的类)

​ (2).继承A类,实现A类的抽象方法;

​ (3).创建匿名对象

​ 很多人容易把匿名内部类当成使用new关键字创建抽象类的对象,这里一定要注意。

2.抽象类中只有抽象方法吗?

​ 答:抽象类中就可以有静态方法和成员方法

3.抽象类中可不可以没有抽象方法?

​ 答:可以,但毫无意义

4.如果父类是抽象类,则子类必须实现父类的抽象方法吗?

​ 答:不是,子类如果是抽象类,可以不去实现父类的抽象方法

5.抽象类能不能有构造方法?作用是什么?

​ 答:可以。作用是让子类调用,给父类的属性赋值。

2.接口

2.1 含义

接口是特殊的抽象类

2.2 接口关键字

implements实现接口的关键字;

interface定义接口的关键字。

2.3 注意

在JDK1.8之前,接口里只有静态常量和抽象方法;JDK1.8开始,接口里就有了默认方法和静态方法。

2.4 应用场景

​ 抽象类中只有静态常量或者静态方法就用接口替代。

2.5 设计思想

​ 接口更像一个规范/标准

2.6 经典面试题(重点)

​ 1.一个类可以实现多个接口吗?

​ 答:可以

​ 2.一个接口可以实现多个接口吗?

​ 答:不可以

​ 3.接口里边的方法一定都是抽象的吗?

​ 答:不一定。JDK1.8之后就允许使用静态方法和默认方法。

​ 4.接口解决了单线程的问题

​ 5.一个类是否可以继承一个类,并同时实现多个接口?

​ 答:可以。

​ 6.接口可以new对象吗?

​ 答:不可以。new出来的是匿名内部的对象

​ 7.多个接口中有相同的抽象方法,在实现类中实现几个方法?

​ 答:只有一个

//I1和I2的默认方法名冲突了,在A类中就必须重写
@Override
public void method02() {
	//可以在实现类中调用指定接口的默认方法
	I1.super.method02();
		
	System.out.println("xxxx");
}

3.多态

3.1 类的多态

子类对象指向父类引用(父类引用里存的是子类对象在堆里开辟的地址)。

Vehicle v = new Bike();
//Vehicle是父类,Bike是子类
3.2 接口的多态

实现类的对象指向接口的引用(接口的引用中存的是实现类对象在堆内存里开辟的地址)。

IUSB usb = new Disk();
//IUSB是接口,Disk是实现类
3.3 OPC原则 - 开闭原则

​ O - open - 在需求更改时,对创建类是欢迎的

​ C - close - 在需求更改时,改变原有类是拒绝的

​ P - principle(原则)

4 对象转型

4.1 前提

父子类关系

4.2 向上转型

向上转型:子类类型 转 父类类型

4.2.1 注意:

​ (1)向上转型就是多态

​ (2)可以调用父类非私有化属性

​ (3)可以调用父类非私有化方法

​ (4)可以调用子类重写父类的方法;

​ (5)不可以调用子类属性

​ (6)不可以调用子类方法

4.2.2 向上转型(多态)的优缺点

优点:在需求更改时符合OCP原则

缺点不可以调用子类/实现类自己独有的属性和方法

4.3 向下转型

向下转型:父类类型 转 子类类型 (强转)

4.3.1.注意:

向下转型不安全,容易出现ClassCastException(类型转换异常),所以不能直接将父类对象强转为子类类型。

解决方案:向下转型一定要向上转型后再向下转型

​ 向下转型一定要用instanceof判断。

	Animal an = new Cat();//向上转型
	//Animal an = new Dog();//向上转型

	if(an instanceof Dog){//判断引用an所执行的对象是否是Dog类型的

		Dog dog = (Dog) an;//向下转型
		System.out.println(dog);

	}else if(an instanceof Cat){//判断引用an所执行的对象是否是Cat类型的

		Cat cat = (Cat) an;
		System.out.println(cat);
	}

5 内部类

5.1 含义

在一个类的内部定义的类称为内部类。内部类允许把一些逻辑相关的类组织在一起,并且控制内部类的可视性。

5.2 分类
1.成员内部类

成员内部类里可以调用外部类的所有属性

2.静态内部类

静态内部类只能调用外部类的静态属性

3.接口内部类

接口内部类可以调用外部接口的静态常量

4.局部内部类

局部内部类可以调用外部类当前方法的局部变量 + 所有属性

注意:(1)不能用访问修饰符修饰局部变量

​ (2)在局部内部类中调用方法中的局部变量,在JDK1.8版本之前,该变量必须手动添加final;在JDK1.8版本之后,该变量会自动转换为常量

​ (3)不能用访问修饰符修饰局部内部类

面试题:为什么局部内部类中调用方法中的局部变量,该变量会变成常量?

​ 答:变成常量后,该量存放在常量池中,比局部变量的生命周期更长,保证内部类对象可以随时调用该常量。

5.匿名内部类

​ 应用场景1:如果抽象类的子类只使用一次,就直接用匿名内部类代替,减少了子类的创建
​ 应用场景2:如果接口的实现类只使用一次,就直接用匿名内部类代替,减少了实现类的创建

		 /** 1.创建匿名类
		 * 2.匿名类继承A类,重写A类的抽象方法
		 * 3.创建匿名类的对象
		 * 4.该对象指向父类的引用(多态)
		 */
		 A a = new A() {
			
			@Override
			public void method() {
				System.out.println("xxx");
			}
		};
		a.method();
		
		/**
		 * 1.创建匿名类
		 * 2.匿名类实现I1接口,重写I1的抽象方法
		 * 3.创建匿名类的对象
		 * 4.该对象指向接口的引用(多态)
		 */
		I1 i1 = new I1() {
			
			@Override
			public void method() {
				System.out.println("xxxxxxxxxxx");
				
			}
		};
		i1.method();

6 包装类

6.1 含义

8种基本数据类型对应的8个类

6.2 出现原因

​ Java为纯面对对象语言(万物皆对象),8种基本数据类型不能创建对象,破坏了Java为纯面对对象语言的特征,Java就给8种基本数据类型分别分配了对应的类,这种类就叫做包装类(封装类)

6.3 分类
基本数据类型包装类继承关系
byteByteextends Number extends Object
shortShortextends Number extends Object
intIntegerextends Number extends Object
longLongextends Number extends Object
floatFloatextends Number extends Object
doubleDoubleextends Number extends Object
charCharacterextends Object
booleanBooleanextends Object

注释:int的包装类是Integer,char的包装类是Character,其余基本数据类型的包装类都是首字母大写。

6.4 应用场景

​ 集合。集合是存放数据的容器,和数组类似,但集合只能存引用数据类型的数据,要想集合存储基本数据类型,就可以将基本数据类型装箱成对应的引用数据类型。

6.5 装箱、拆箱
1.手动装箱

​ 基本数据类型 --> 包装类的对象

​ 关键字:valueOf、Integer

int i = 10;
Integer integer = Integer.valueOf(i);
System.out.println(integer);
2.手动拆箱

​ 包装类的对象 --> 基本数据类型

​ 关键字:intValue/…Value

Integer integer = new Integer();
int i = integer.intValue();
System.out.println(i);
3.自动装箱

​ 从JDK1.5开始,就可以自动装箱和自动拆箱了。

int i = 10;
Integer integer = i;//底层实现与手动装箱一样
System.out.println(integer);
4.自动拆箱
Integer integer = new Integer();
int i = integer;
System.out.println(i);
6.6 经典面试题

​ 1.将String类型数组转换为int类型的数组。

//将String[] s = {"1","2","3","4","5","6"}转换为int类型的数组
String[] s = {"1","2","3","4","5","6"};
int[] x = new int[s.length];

for(int i = 0;i < x.length;i++){
    Integer integer = Integer.valueOf(s[i]);
    is[i] = integer;//自动拆箱
}
for(int e : x){
    System.out.println(e);
}

2.判断下列代码为true还是false

Integer integer1 = Integer.valueOf(100);
Integer integer2 = Integer.valueOf(100);
System.out.println(integer1 == integer2);//true

Integer integer3 = Integer.valueOf(200);
Integer integer4 = Integer.valueOf(200);
System.out.println(integer3 == integer4);//false

Integer integer5 = Integer.valueOf(-127);
Integer integer6 = Integer.valueOf(-127);
System.out.println(integer5 == integer6);//true -128~127

Integer a = new Integer(10);
Integer a1 = new Integer(10);
System.out.println(a == a1);//false,比较的是两个不同对象的地址,所以肯定不同

Integer b = 10;
Integer b1 = 10;
System.out.println(b == b1);//true,
// 首先我们应该知道随着Integer的加载,Integer中有一个静态内部类IntegerCache也会随之加载,这个内部类的加载时会生成一个包含[-128,127]的Integer对象的数组(你可以叫它是缓存,因为在这个区间的数用得最多)
// 首先b、b1是自动装箱,自动装箱其实就是自动调用了valueOf(int i),在这个方法中会判断如果i在[-128,127]之间,则会从缓存中获取。
// 因为10(<=127),所以b和b1都是从缓存中获取的同一个对象。
6.7 底层分析* - Integer
public class MyInteger{
    
    private int value;
    
    public MyInteger(int value){
        this.value = value;
    }
    public int intValue(){
        return value;
    }
    
    public static MyInteger valueOf(int i){
        if(i >= MyIntegerCache.low && i <= MyIntegerCache.high){
            return MyIntegerCache.cache[i - MyIntegerCache.low];
        }
        return new MyInteger(i);
    }
    
    //MyInteger的缓存类
    private static class MyIntegerCache{
        private static final int low = -128;
        private static final int high = 127;
        private static final MyInteger[] cache;
        
        static{
            int j = low;
            cache = new MyInteger[high - low + 1];
            for(int i = 0;i < cache.length;i++){
                cache[i] = new MyInterger(j++);
            }
        }
    }
}

7 String类、StringBuffer、StringBuilder

7.1 String
1.String创建对象问题(面试题)
//只创建1个对象 - "abc",在常量池中,就会生成一个对象
String str1 = "abc";
String str2 = "abc";
System.out.println(str1);
System.out.println(str2);

//面试题2:如下代码创建几个String对象
//创建三个String对象(两个new String,一个"abc")
String str3 = new String("abc");
String str4 = new String("abc");
System.out.println(str3);
System.out.println(str4);

//面试题3:
String str1 = "abc";
String str2 = "abc";
System.out.println(str1 == str2);//true

//面试题4:
//常量直接在翻译是就拼接
String str3 = "ab" + "c";
System.out.println(str1 == str3);//true

//面试题5:
//常量直接在翻译是就拼接
final String s1 = "ab";
final String s2 = "c";
String str4 = s1 + s2;
System.out.println(str1 == str4);//true

//面试题6:
String s3 ="ab";
String s4 = "c";
String str5 = s3 + s4;//new StringBuilder(s3).append(s4).toString()
System.out.println(str1 == str5);//false
2.String常用方法

注:以下方法使用时都要返回新的字符串

String方法作用
concat()在字符串末尾追加字符
substring(a)截取从a下标处到字符串末尾
substring(a,b)截取从a下标(包含)到b下标(不包含)
toLowerCase()转小写
toUpperCase()转大写
trim()去掉首尾空格
replace(‘a’,‘b’)替换字符
replaceAll(“c”,“d”)替换字符串
replaceFirst(“c”,“d”)替换第一个出现的字符串
equals(“a” ,“b”)判断两个字符串是否相同(区分大小写)
equalsIgnoreCase(“a” ,“b”)判断两个字符串是否相同(不区分大小写)(应用于验证码)
startsWith(“a”)判断是否以某个字符串开头
endWith(“a”)判断是否以某个字符串开头
indexOf(“a”)查询子字符串在此字符串中的下标
lastIndexOf(“a”)查询子字符串在此字符串中最后一次的下标
length()获取字符串长度
charAt()获取指定下标上的字符
valueOf()将int/double/char…转换为String类型
3.代码演示
	public static void main(String[] args) {
		/**
		 * String 的常用方法
		 */
		
		String str = "123abcDEF";
		
		str = str.concat("123");//在此字符串末尾追加字符串,返回新字符串
		System.out.println(str);
		str = str.substring(3);//从开始下标处截取到字符串末尾,返回新字符串
		System.out.println(str);
		str = str.substring(3, 7);//从开始下标处(包含)截取到结束下标处(不包含),返回新字符串
		System.out.println(str);
		str = str.toLowerCase();//转小写,返回新的字符串
		System.out.println(str);
		str = str.toUpperCase();//转大写,返回新的字符串
		System.out.println(str);
		
		str = "  1  23   ab  cD   EF   123     ";
		
		str = str.trim();//去掉首尾空格,返回新的字符串
		System.out.println(str);
		str = str.replace('2', '-');//替换字符,返回新的字符串
		System.out.println(str);
		str = str.replaceAll(" ", "");//替换字符串,返回新的字符串
		System.out.println(str);
		str = str.replaceFirst("3", "Kobe");//替换第一个出现的字符串,返回新的字符串
		System.out.println(str);
		
		System.out.println("判断两个字符串是否相同(区分大小写):" + str.equals("1-KobeabcDEF1-3"));//true
		System.out.println("判断两个字符串是否相同(不区分大小写):" + str.equalsIgnoreCase("1-KobeABCDEF1-3"));//true
		System.out.println("判断此字符是否以某个字符串开头" + str.startsWith("1-"));//true
		System.out.println("判断此字符是否以某个字符串结尾" + str.endsWith("e"));//false
		
		System.out.println("查询子字符串在此字符串中的下标:" + str.indexOf("K"));//2
		System.out.println("查询子字符串在此字符串中最后一次的下标:" + str.lastIndexOf("3"));//14
		
		System.out.println("获取字符串的长度" + str.length());//15
		System.out.println("获取指定下标上的字符:" + str.charAt(5));//e
		
		System.out.println("将int转换为String:" + String.valueOf(100));
		System.out.println("将double转换为String:" + String.valueOf(123.123));
		System.out.println("将char转换为String:" + String.valueOf('c'));
		//还有一种最简单的方法:把任意对象、基本数据类型与一个空字符串相连就可以直接转换成字符串。
		int i = 100;
		String s = i + "";
		System.out.println(s);
		
	}
7.2 StringBuffer和StringBuilder
7.2.1 含义

​ StringBuffer和StringBuilder都被称为字符串缓冲区。都代表可变的字符序列

​ 与String对象的不同:StringBuffer和StringBuilder为可变对象

7.2.2 工作原理

预先申请一块内存,存放字符序列,如果字符序列满了,会重新改变缓存区的大小,以容纳更多字符。

7.2.3 底层分析

继承关系:StringBuffer extends AbstractStringBuilder
字符串缓冲区 继承 抽象字符串生成器

默认缓冲区大小16个字符

7.2.4 StringBuffer和StringBuilder常用方法
StringBuffer/StringBuilder方法作用
append()在末尾追加字符串
insert()指定下标处插入数据
setCharAt()替换指定下标上的字符
replace()从开始下标处(包含)替换到结束下标处(不包括)的字符串
deleteChar()删除指定下标上的字符
delete()从开始下标处(包含)删除到结束下标处(不包括)的字符串
reverse()反转字符
length()获取字符串长度
7.2.5 代码演示
		//默认的缓冲区大小:16个字符
		StringBuilder a = new StringBuilder();
		System.out.println(a);
		
		//自定义缓冲区大小:30个字符
		StringBuilder b = new StringBuilder(30);
		System.out.println(b);
		
		//缓冲区大小:stu.length + 16   "abcd1234"+16
		StringBuilder sb = new StringBuilder("abcd1234");
		System.out.println(sb);
		
		sb.append("DEF123");//在末尾追加字符串
		sb.insert(5, "Tom");//指定下标处插入数据
		sb.setCharAt(4, 'B');//替换指定下标上的字符
		sb.replace(3, 6, "xx");//从开始下标处(包含)替换到结束下标处(不包括)的字符串
		sb.deleteCharAt(1);//删除指定下标上的字符
		sb.delete(2, 6);//从开始下标处(包含)删除到结束下标处(不包括)的字符串
		sb.reverse();//反转字符
		
		System.out.println(sb);
		System.out.println("获取字符串长度" + sb.length());//11
7.2.6 StringBuffer vs StringBuilder

​ 注意:使用上没有任何区别

StringBuffer:线程不安全,效率更高,在单线程的情况下使用

StringBuilder:线程安全,效率更低,在多线程的情况下使用

7.2.7 为什么需要StringBuffer和StringBuilder类?

​ 因为其可变性。一个String对象的长度是固定不变的,如果我们要频繁的附加新的字符串,使用String对象的话,系统会频繁创建String对象,造成性能下降。所以不建议使用+来进行频繁的字符串串联,应该使用java.lang.StringBuffer或StringBuilder。

		//获取自1970.1.1 0:0:0到现在的毫秒数
		long startTime = System.currentTimeMillis();
		
		String str = "Kobe";
		System.out.println(str);
		for(int i = 0;i < 30000;i++){
			str += "NB";
			//底层实现:str = new StringBuilder(str).append("NB").toString();
		}
		
		//获取自1970.1.1 0:0:0到现在的毫秒数
		long endTime = System.currentTimeMillis();
		
		System.out.println("消耗时长:" + (endTime - startTime));//效率比单纯的字符串拼接高的多

8 正则表达式regex

8.1 含义

用来描述或者匹配一系列符合某个语句规则的字符串。

8.2 经典案例
案例1:把一个字符串中的电话号码的中间四位替换成xxxx
		String str = "小明18758184171 小强18240834972";
		
		String regex = "(1\\d{2})(\\d{4})(\\d{4})";
		str = str.replaceAll(regex,"$1****$3");
		//分析底层:
		//Pattern pattern = Pattern.compile(regex);//获取到正则表达式的对象
		//Matcher matcher = pattern.matcher(str);//正则表达式的匹配结果
		//matcher.replaceAll(str);//根据匹配结果替换字符串
		 
		System.out.println(str);
案例2:检验QQ邮箱
		String str = "1875818417@qq.com";
		
		String regex = "\\d{6,12}@qq.com";
		
		boolean bool = str.matches(regex);//判断该字符串是否匹配正则表达式
		//底层实现:
		//Pattern.matches(regex,str);
			//Pattern pattern = Pattern.compile(regex);//获取到正则表达式的对象
			//Matcher matcher = pattern.matcher(str);//正则表达式的匹配结果
		    //matcher.matches();//根据匹配结果替换字符串
		 
		System.out.println(bool);
案例3:分隔路径
		String str = "C:\\资源\\日韩\\波多野结衣.avi";
		
		String regex = ":?\\\\";//:\\ 或  \\
		
		String[] split = str.split(regex);
		//底层实现:
		//Pattern pattern = Pattern.compile(regex);//获取到正则表达式的对象
		//String[] split = pattern.split(str);//依据正字表达式分隔字符串
		 
		for (String s : split) {
			System.out.println(s);
案例4:找到前端代码中的图片路径
		String str = "<img src='hhy/aaa.jpg'/><div><div/> <input type='image' src='submit.gif' /><img src='bbb.jpg'/>";

		String regex = "<img\\b[^>]*\\bsrc\\b\\s*=\\s*('|\")?([^'\"\n\r\f>]+(\\.jpg|\\.bmp|\\.eps|\\.gif|\\.mif|\\.miff|\\.png|\\.tif|\\.tiff|\\.svg|\\.wmf|\\.jpe|\\.jpeg|\\.dib|\\.ico|\\.tga|\\.cut|\\.pic)\\b)[^>]*>";

		Pattern pattern = Pattern.compile(regex);//获取到正则表达式的对象
		Matcher matcher = pattern.matcher(str);//获取匹配结果
		
		//System.out.println("在字符串中是否整个匹配:" + matcher.matches());
		//System.out.println("在字符串中是否开头就匹配:" + matcher.lookingAt());
		//System.out.println("在字符串中是否有包含匹配:" + matcher.find());

		//遍历匹配结果
		while(matcher.find()){
			String group = matcher.group();
			System.out.println(group);
			String group1 = matcher.group(2);//获取正则表达式的第二组数据
			System.out.println(group1);
		}
8.3 底层分析

Pattern:代表正则表达式的匹配模式

Matcher:提供了对正则表达式的分组支持,以及对正则表达式的多次匹配支持

9 时间类(Date、SimpleDateFormat、Calendar)

9.1 Date类

日期类。表示特定的瞬间,精确到毫秒。

		Date date = new Date();
		System.out.println(date);
		//Wed   Apr  28  11:25:08   CST   2021
		//星期  月份  日期  时:分:秒	  时区   年份
		
		//从1970.1.1 0:0:0 往后推1000毫秒
		Date date2 = new Date(1000);
		System.out.println(date2);

​ 补充:@Deprecated —> 过时的注解

9.2 SimpleDateFormat类

格式化日期类。将显示的日期信息格式化。

		SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
	
		//格式化日期时间
		String string = sdf.format(new Date());
		System.out.println(string);//2021年04月28日 11:45:16
		
		//将字符串转换为Date对象
		Date date = sdf.parse("2021年04月28日 11:61:02");
		System.out.println(date);
9.3 Calendar类

​ 日历类。是一个抽象类,主要用于完成日期字段之间相互操作的功能,即可以设置和获取日期数据的特定部分。

		//获取日历数的对象
		Calendar c = Calendar.getInstance();
		
		int year = c.get(Calendar.YEAR);
		int month = c.get(Calendar.MONTH)+1;
		int day = c.get(Calendar.DAY_OF_MONTH);
		int hour = c.get(Calendar.HOUR);
		int minute = c.get(Calendar.MINUTE);
		int second = c.get(Calendar.SECOND);
		
		System.out.println(year);
		System.out.println(month);
		System.out.println(day);
		System.out.println(hour);
		System.out.println(minute);
		System.out.println(second);
		
		//JDK1.8开始,使用到的时间类
		System.out.println(LocalDate.now());
		System.out.println(LocalDateTime.now());

10 Math类

10.1 含义

Math类提供了一序列基本数学运算和几何函数的方法。

​ Math类是final类,并且它的所有成员变量和成员方法都是静态的。

10.2 常用方法
Math方法作用
Math.pow(a,b)a的b次方
Math.sqrt(a)平方根
Math.abs(a)绝对值
Math.ceil(a)向上取整
Math.floor(a)向下取整
Math.round(a)四舍五入
Math.max(a)最大值
Math.min(a)最小值
Math.random()获取随机值0(包含)~1(不包含)
10.3 经典面试题
面试题1:随机输出1~100的数字
System.out.println("获取1~100的随机值" + ((int)(Math.random()*100)+1));
面试题2:abs()有可能出现负数吗?

​ 答:

System.out.println("绝对值:" + Math.abs(Integer.MIN_VALUE));

abs()底层实现

public static int abs(int a) {
     return (a < 0) ? -a : a;
}
//-2147483648 ~2147483647

11. 静态导入

​ 当使用一个类里面的静态方法或者静态变量时,每次都要写类名。如果不想写,想直接写方法名或者变量名,就可以考虑静态导入。

语法:import static 包名.类名.*

​ 如:import static java.lang.Math.*;

导入该类下的所有静态方法和常量

不需用写类名,直接用方法名调用

缺点:可读性不高

12.Random类

12.1 含义

此类用于生成随即数。

12.2 理解什么是随机

​ 系统里的随机数都是伪随机,通过算法得出的一个较为随机的数字。

种子数:种子固定,随机出来的数据也是固定的。

12.3 应用需求
1.点名器
		String[] names = {"小明","小陆","小郑","小罗","小刘","小白","小张","小李","小强","小美",};
		
		Random ran = new Random();
		int index = ran.nextInt(names.length);
		
		System.out.println(names[index]);
2.随机数

.nextInt().nextDouble().nextBoolean()

		//创建随机类的对象
		Random ran = new Random();
		
		System.out.println("随机出int值:" + ran.nextInt());
		System.out.println("随机出int值(0~9):" + ran.nextInt(10));
		System.out.println("随机出double值:" + ran.nextDouble());
		System.out.println("随机出boolean值:" + ran.nextBoolean());
12.4 底层分析
public class MyRandom{
   
    //种子数
    private long seed;
    
    public MyRandom(){
        //计算出较为随机的种子数
        this(seedUniquifier() ^ System.nanoTime());
    }
    
    //提供随机数字的方法
    public long seedUniquifier(){
        long current = System.currentTimeMillis();
        for(;;){
            current = current * 181783497276652981L;
            if(c%5==0){
                return current;
            }
        }
    }
    
    public MyRandom(long seed){
        this.seed = seed;
    }
    
    public int nextInt(){
        return (int)seed;
    }
    
     public int nextInt(int num){
        return Math.abs((int)seed)%num;
    }
    
     public boolean nextBoolean(){
        return ((int)seed)>0?true:false;
    }
    
}

13.System类

13.1 含义

​ 系统类。System类提供了一些静态属性和方法,允许通过类名直接调用。

13.2 分类

(1) 系统标准的输入流(控制台 -> 程序)

InputStream in = System.in;

(2) 系统标准的输出流(程序 -> 控制台)

PrintStream out = System.out;

(3) 系统标准的错误输出流(程序 -> 控制台)

PrintStream err = System.err;

(4) 研究系统的输出流和错误流:

​ 结论:out是一个线程,err是一个线程,两个线程抢到CPU资源后才能运行,抢资源的过程是随机的

13.3 System的静态方法

(1) 退出当前虚拟机,输入0表示正常退出

System.exit(0);

(2) 获取1970.1.1 0:0:0到现在的毫秒数

System.out.println("获取毫秒值:" + System.currentTimeMillis());

(3) 获取到当前系统参数(以键值对的形式存储参数) Key - Value

Properties properties = System.getProperties();
System.out.println(properties);

String value = System.getProperty("os.name");
System.out.println(value);

14.Runtime类

14.1 含义

表示运行环境的对象

14.2 常见方法

​ 获取闲置内存数freeMemory();

​ 获取最大内存数maxMemory();

​ 获取处理数availableProcessors();

​ 获取系统的时间currentTimeMillis();

//获取运行环境的对象
Runtime run = Runtime.getRuntime();

System.out.println("获取闲置内存数" + run.freeMemory());
System.out.println("获取最大内存数" + run.maxMemory());
System.out.println("获取处理数" + run.availableProcessors());
/**
* 测试程序:消耗时长、消耗内存
*/
		
//获取运行环境的对象
Runtime run = Runtime.getRuntime();
		
long startTime = System.currentTimeMillis();
long startMemory = run.freeMemory();
		
StringBuilder sb = new StringBuilder("燕燕小可爱");
for (int i = 0; i < 30000; i++) {
	sb.append("皇冠给你带");
}
		
long endTime = System.currentTimeMillis();
long endMemory = run.freeMemory();
		
System.out.println("消耗时长:" + (endTime - startTime));
System.out.println("消耗内存:" + (startMemory - endMemory));
14.3 面试题

问题:消耗内存会出现负数吗?

答案:有可能,在执行代码块的时候,垃圾回收器回收了一部分闲置内存,导致运行后的内存反而更大了。

15.大数值运算类

15.1 BigInteger

整数类型的大数值运算

加法add();

减法subtract();

乘法multiply();

除法divide();

		/**
		 * 大数值的运算类
		 * 
		 * BigInteger - 整数类型的大数值运算
		 */
		
		BigInteger big1 = new BigInteger("123467890");
		BigInteger big2 = new BigInteger("123467890");
		
		BigInteger add = big1.add(big2);//加法
		System.out.println(add);
		
		BigInteger subtract = big1.subtract(big2);//减法
		System.out.println(subtract);
		
		BigInteger multiply = big1.multiply(big2);//乘法
		System.out.println(multiply);
		
		BigInteger divide = big1.divide(big2);//除法
		System.out.println(divide);
15.2 BigDecimal

小数类型的大数值运算类

​ 注意:不要将小数直接做运算,会失去精度。如:0.5-0.3

加法add();

减法subtract();

乘法multiply();

除法divide();

divide(除数,保留小数位,保留模式)

保留模式:

保留模式说明
BigDecimal.ROUND_DOWN直接省略多余的小数,比如1.28如果保留1位小数,得到的就是1.2
BigDecimal.ROUND_UP直接进位,比如1.21如果保留1位小数,得到的就是1.3
BigDecimal.ROUND_HALF_UP四舍五入,2.35保留1位,变成2.4
BigDecimal.ROUND_HALF_DOWN四舍五入,2.35保留1位,变成2.3

代码:

		BigDecimal big1 = new BigDecimal("0.5");
		BigDecimal big2 = new BigDecimal("0.2");
		
		BigDecimal add = big1.add(big2);//加法
		System.out.println(add);
		
		BigDecimal subtract = big1.subtract(big2);//减法
		System.out.println(subtract);
		
		BigDecimal multiply = big1.multiply(big2);//乘法
		System.out.println(multiply);
		
		BigDecimal divide = big1.divide(big2);//除法
		System.out.println(divide);

		BigDecimal big1 = new BigDecimal("10");
		BigDecimal big2 = new BigDecimal("3");
		
		BigDecimal divide = big1.divide(big2);//除法
		System.out.println(divide);//报错,无限循环
		
		//divide(big2, 保留小数位, 保留模式)
		BigDecimal divide = big1.divide(big2, 3, BigDecimal.ROUND_HALF_UP);
		System.out.println(divide);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

釣餌锒鐺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值