/* 多态 常用的定义形式: 父类 名 = new 子类构造器; 接口 名 = new 实现类构造器; 比如Dog继承了Animal,可以定义成 Animal a = new dog(); 此时方法运行的是dog的,其他属性是用Animal的,a还是一个Animal,只不过行为是狗 可以说编译看左边运行看右边 现在a是一个动物,想给他转化成狗,需要强制转换. 狗转换成动物不需要强制转换,是自动的 Dog d = (Dog) a; 把动物a强制变成狗,这是有可能转错的,因为a不一定是狗 虽然编译阶段不会出问题,但是转错了一运行就会崩溃 为了避免转错,可以用instanceof,如果通过再进行强转,避免崩溃 if(a instanceof Dog){Dog d = (Dog) a;} */ /* 多态的优势 可以实现解耦,方便后续更新维护 定义方法的时候,入参也可以多种多样.比如入参需要是动物,那狗也可以,乌龟也可以,这就是多态 如果不用多态,要么只能传狗,要么只能进乌龟,非常不方便 */ /* 内部类 类里面可以继续加类,比如人类里面有心脏类,汽车类里有发动机类 静态内部类 如果内部类用public static class 类名{} 那跟外部类一样没区别,只是位置在别人里面 创建对象的时候用外部类点上内部类就能创建 外部类.内部类 名字 = new 外部类.内部类(); 成员内部类 public class 类名{} 这个就跟实例成员变量一样,必须创建对象了,有一个对象初始化了,才能再有这个类,创建的时候要先new外部类,再new内部类 外部类.内部类 名字 = new 外部类.new 内部类(); 这个内部类是可以直接访问实例成员对象的,因为他依附于这个类的对象存在了. 这个情况更符合实际情况,先有车对象才有这个车内部的发动机 匿名内部类 主要是为了lambda简化而生,可以精简代码风格 比如有一个父类是动物,方法是跑,但是这个方法是抽象的,不知道具体怎么跑. 这时候我需要运行一次这个方法, 正常情况我需要先创建一个子类比如老虎,来继承动物类,然后重写这个方法,再创建一个对象,再来完成跑 但是这个对象创建其实对我来说没什么用,我只需要跑就行了,是老虎还是兔子无所谓,这时候就可以用匿名内部类 Animal a = new Animal(){ @Override 重写跑方法 } 然后直接调a这个对象跑就行了 */ /* 9月7日 */ /* Objects 所有的类都会默认继承Object类,所以Objects类里的方法所有类都能用. Objects类里提供了两个方法:equals()和toString() toString: 如果没被重写,那么toString方法会打印地址值,equals会比较地址值是否一样 但是一般情况我们打印是不想打印地址,而是要看内容 这时候需要重写toString.任何类都可以重写toString方法,不输出地址而是输出内容,想怎么输出就在么重写,在类里面输入toS连续回车可以快速重写 equals: equals比较的时候我们很多时候也不是要比较地址,而是要比较内容,比如有两个学生对象都是new出来的,但是名字和学号相同,这时候两个地址不一样的 这种情况如果直接用equals来比较,那会返回false, 但是实际我们认为名字和学号都一样的学生他就是一样的,而不是看他地址一不一样.所以要重写equals方法,按照实际需求设计 在类里面输入equal连续回车可以快速重写 另外,字符串的比较可以直接用equals,比如 字符串1.equals(字符串2); 但是这样操作不稳妥,如果字符串1是null就会崩溃报错 此时可以利用Objects.equals(字符串1,字符串2),这个方法会先对字符串1做一次非空校验,非常稳妥 isNull: 可以看这个玩意是不是null,实际上和直接比较(一个东西==null)输出返回是一样的,没什么用,但是看起来专业 用Objects.isNull(一个东西);通过返回布尔类型来调用 */ /* StringBuilder StringBuilder能更快的拼接字符串,也比String有更多的Api来调用 StringBuilder支持链式编程,可以sb.append().append().append().append().append(); 常用api: append() reverse() toString() length() String类直接拼接字符串的时候,因为String内容不可变没法拼,所以实际上是每次拼接都要先创建一个StringBuilder,然后再拼接,再toString,非常麻烦 StringBuilder就等于一个容器盒子,里面随便拼,拼完整个输出就行了 */ /* Math类 主要用来搞数学方法,是工具类,比如正弦余弦.绝对值之类的 Math.abs() 取绝对值 Math.ceil() 取天花板, 比如4.0001会取5 Math.floor()取地板, 比如3.999会取3 Math.pow(a,b) a的b次方 Math.round() 四舍五入 Math.random() 生成0-1之间的随机数 */ /* System类 也等于是工具类,用System.来调用 System.exit(0) 终止JVM虚拟机,直接结束程序.非0表示异常终止,一般都不会用 System.currentTimeMillis() 获取从1970-1-1 00:00:00到现在的毫秒值,返回一个long值. 可以进行时间计算,性能分析,比如跑一个循环之前取一个,跑完以后再取一个,两者相减再除1000,就知道这段代码跑了多少秒 System.arrayCopy(入参1,2,3,4,5) 这个api里面参数太复杂,不可能没必要记住.可以直接ctrl+p来查看 一共五个参数, 具体是:被拷贝的数组,从哪个索引开始拷贝,要复制到哪个数组,粘贴到哪个位置,拷贝几个数据 */ /* BigDecimal 因为浮点型运算精度失真,直接运算会出问题 比如0.09+0.01,直接加输出的结果是0.099999999999999 这时候可以先把数据转化成BigDecimal,然后再调用BigDecimal的方法进行运算最后输出结果 把小数转化成BigDecimal可以用构造器,但是非常不建议直接用double类型转化成BigDecimal类型,因为还是有可能失真 比较好的方法是用String来转化(创建)成BigDecimal对象,比如BigDecimal bd = new BigDecimal("0.01") 因为这个"0.01"是字符串,就不会出现精度问题 还有一种是用它的valueOf()方法,比如BigDecimal bd = BigDecimal.valueOf(0.01); 实际上valueOf做的事情是 先把0.01变成字符串"0.01",然后再做上面的操作,总之这两种方法都不会导致精度失真 具体运算方法: 相加 add 相减 subtract 相乘 multiply 相除 divide 变成double值 doubleValue() BigDecimal b1 = BigDecimal.valueOf(10.0); BigDecimal b2 = BigDecimal.valueOf(3.0); BigDecimal b3 = b1.add(b2); double B3 = BigDecimal.doubleValue(b3); 值得注意的是,如果获得的结果本身就不能精确,那必须指定结果要保留几位,以及舍入模式,比如四舍五入或者取天花板ceil地板floor 如果BigDecimal算出来的结果是不精确的,本身就会直接报错 BigDecimal b4 = b1.divide(b2); 因为结果是3.333333所以就会报错,正确写法像下面这样 BigDecimal b4 = b1.divide(b2,2,RoundingMode.HALF_UP);这样告诉他保留两位小数,向上取整,就不出错了 */
9.7号笔记
最新推荐文章于 2024-07-19 17:37:28 发布