Java重新来过六(接口和继承,数字和字符串,日期,Java书籍推荐)

一,接口和继承

1,接口:接口就像是一种约定在学习了多态之后就能进一步加深理解。

2,对象转型:

向上转型(即子类转父类):把右边的当作左边来用(即将子类对象当成父类对象来用)

向下转型(即父类转子类):强制转换有风险

没有继承关系的两个类,互相转换,一定会失败

向上转型(实现类转换为接口):接口中有的方法,实现类中一定是有的,可以转换成功。

向下转型(接口转换为实现类):有风险

instanceof Hero判断一个引用所指向的对象,是否是Hero类型,或者Hero的子类System.out.println(h1 instanceof Hero);

3,方法重写:又叫方法覆盖,子类可以继承父类的对象方法,在继承后,重复提供该方法。

如图4所示,多态:都是同一个类型,调用同一个方法,却能呈现不同的状态

类的多态 
父类引用指向子类对象(调用方法,执行的是对应子类中的方法)

                       要实现类的多态,需要如下条件
                                       1。父类(接口)引用指向子类对象
                                       2。的调用方法有重写

package charactor;
 
import property.Item;
import property.LifePotion;
import property.MagicPotion;
   
public class Hero {
    public String name;
    protected float hp;
 
    public void useItem(Item i){
        i.effect();
    }
 
    public static void main(String[] args) {
         
        Hero garen =  new Hero();
        garen.name = "盖伦";
     
        LifePotion lp =new LifePotion();
        MagicPotion mp =new MagicPotion();
         
        garen.useItem(lp);
        garen.useItem(mp);     
         
    }
       
}

使用多态的好处?

5,隐藏:类子父覆盖类的。方法与重写类似,的方法的英文重写子类覆盖父类的对象方法 

6,super:实例化子类,父类的构造方法一定会被调用,并且是父类构造方法先调用(子类构造方法会默认调用父类的无参的构造方法)

子类显式调用父类带参构造方法:

    public ADHero(String name){

        super(name);

        System.out.println("AD Hero的构造方法");

    }

调用父类属性:

    public int getMoveSpeed2(){

        return super.moveSpeed;

    }

通过超级调用父类的useItem方法:

    // 重写useItem,并在其中调用父类的userItem方法

    public void useItem(Item i) {

        System.out.println("adhero use item");

        super.useItem(i);

    }

如图7所示,对象类:是所有类的父类声明一个类的时候,默认是继承了对象 

 toString()的意思是返回当前对象的字符串表达
通过System.out.println打印对象就是打印该对象的toString()返回值


垃圾回收方法:终结():

当一个对象没有任何引用指向的时候,它就满足垃圾回收的条件

当它被垃圾回收的时候,它的finalize() 方法就会被调用。

finalize() 不是开发人员主动调用的方法,而是由虚拟机JVM调用的。


equals() 用于判断两个对象的内容是否相同


这不是Object的方法,但是用于判断两个对象是否相同
更准确的讲,用于判断两个引用,是否指向了同一个对象


 hashCode方法返回一个对象的哈希值


Object还提供线程同步相关方法
wait()
notify()
notifyAll()


getClass()会返回一个对象的类对象

8、final :final修饰类,方法,基本类型变量,引用的时候分别有不同的意思。

final修饰类:表示该类不能被继承

final修饰方法:表示该方法不能被重写(覆盖)(在子类中)

final修饰基本类型变量:表示该变量只有一次赋值的机会。

final修饰引用:表示该引用只有一次指向对象的机会。

常量指的是可以公开,直接访问,不会变化的值 :public static final int itemTotalNumber = 6;//物品栏的数量

9、抽象类:在类中声明一个方法,这个方法没有实现体,是一个“空”方法 ,使用修饰符“abstract" 

当一个类有抽象方法的时候,该类必须被声明为抽象类(子类被要求实现父类中的抽象方法)   

 一旦一个类被声明为抽象类,就不能够被直接实例化

抽象类可以没有抽象方法

抽象类和接口的区别:

区别1:
        子类只能继承一个抽象类,不能继承多个
        子类可以实现多个接口
区别2:
    抽象类可以定义
        public,protected,package,private
        静态和非静态属性
        final和非final属性
    但是接口中声明的属性,只能是
        public
        静态
        final的
即便没有显式的声明         (public static final) int resistMagic;

抽象类和接口都可以有实体方法。 接口中的实体方法,叫做默认方法

10、内部类:分为四种

非静态内部类 :可以直接在一个类里面定义(必须建立在一个存在的对象基础上)              语法: new 外部类().new 内部类()
静态内部类 :静态内部类的实例化,不需要一个外部类的实例为基础,可以直接实例化                new 外部类.静态内部类();
匿名类 :在声明一个类的同时实例化它,使代码更加简洁精练

        Hero h = new Hero(){

            //当场实现attack方法

            public void attack() {

                System.out.println("新的进攻手段");

            }

        };

本地类:可以理解为有名字的匿名类

        //与匿名类的区别在于,本地类有了自定义的类名

        class SomeHero extends Hero{

            public void attack() {

                System.out.println( name+ " 新的进攻手段");

            }

        }

在匿名类中使用外部的局部变量,外部的局部变量必须修饰为final

在jdk8中,已经不需要强制修饰成final了,如果没有写final,不会报错,因为编译器偷偷的帮你加上了看不见的final

11、默认方法:默认方法是JDK8新特性,指的是接口也可以提供具体方法了,而不像以前,只能提供抽象方法default public void revive() {       System.out.println("本英雄复活了");    }

假设没有默认方法这种机制,那么如果要为Mortal增加一个新的方法revive,那么所有实现了Mortal接口的类,都需要做改动。

但是引入了默认方法后,原来的类,不需要做任何改动,并且还能得到这个默认方法

通过这种手段,就能够很好的扩展新的类,并且做到不影响原来的类

UML:Unified Module Language统一建模语言

二、数字和字符串

1、装箱拆箱:

所有的基本类型都有对应的类类型,这种类就叫做封装类。

基本类型转封装类:Integer it = new Integer(i);

封装类转基本类型:int i2 = it.intValue(); 

自动装箱:不需要调用构造方法,通过=符号自动把 基本类型 转换为 类类型 就叫装箱              Integer it2 = i;

 自动拆箱:不需要调用Integer的intValue方法,通过=自动把Integer类型自动转换成int类型,就叫拆箱  int i3 = it;

int的最大值可以通过其对应的封装类Integer.MAX_VALUE获取    System.out.println(Integer.MIN_VALUE); 

2、字符串转换:

数字转字符串:

方法1: 使用String类的静态方法valueOf                                                String str = String.valueOf(i);
方法2: 先把基本类型装箱为对象,然后调用对象的toString                  Integer it = i;    String str2 = it.toString();

字符串转数字:调用Integer的静态方法parseInt                                      int i= Integer.parseInt(str);

3、数学方法:java.lang.Math提供了一些常用的数学运算方法,并且都是以静态方法的形式存在

Math.round(f);四舍五入,Math.random();随机浮点数,Math.sqrt(f);开方,Math.pow(f,n);f的n次方,Math.PI,Math.E 自然常数

4、格式化输出:

如果不使用格式化输出,就需要进行字符串连接,如果变量比较多,拼接就会显得繁琐

%s 表示字符串
%d 表示数字
%n 表示换行

String sentenceFormat ="%s 在进行了连续 %d 次击杀后,获得了 %s 的称号%n";

printf和format能够达到一模一样的效果:

        String sentenceFormat ="%s 在进行了连续 %d 次击杀后,获得了 %s 的称号%n";
        //使用printf格式化输出
        System.out.printf(sentenceFormat,name,kill,title);
        //使用format格式化输出
        System.out.format(sentenceFormat,name,kill,title);

换行符就是另起一行 --- '\n' 换行(newline)
回车符就是回到一行的开头 --- '\r' 回车(return)
在eclipse里敲一个回车,实际上是回车换行符

Java是跨平台的编程语言,同样的代码,可以在不同的平台使用,比如Windows,Linux,Mac
然而在不同的操作系统,换行符是不一样的
(1)在DOS和Windows中,每行结尾是 “\r\n”;
(2)Linux系统里,每行结尾只有 “\n”;
(3)Mac系统里,每行结尾是只有 "\r"。
为了使得同一个java程序的换行符在所有的操作系统中都有一样的表现,使用%n,就可以做到平台无关的换行

其他常用的格式化方式:总长度,左对齐,补0,千位分隔符,小数点位数,本地化表达 

package digit;
  
import java.util.Locale;
   
public class TestNumber {
   
    public static void main(String[] args) {
        int year = 2020;
        //总长度,左对齐,补0,千位分隔符,小数点位数,本地化表达
          
        //直接打印数字
        System.out.format("%d%n",year);
        //总长度是8,默认右对齐
        System.out.format("%8d%n",year);
        //总长度是8,左对齐
        System.out.format("%-8d%n",year);
        //总长度是8,不够补0
        System.out.format("%08d%n",year);
        //千位分隔符
        System.out.format("%,8d%n",year*10000);
  
        //小数点位数
        System.out.format("%.2f%n",Math.PI);
          
        //不同国家的千位分隔符
        System.out.format(Locale.FRANCE,"%,.2f%n",Math.PI*10000);
        System.out.format(Locale.US,"%,.2f%n",Math.PI*10000);
        System.out.format(Locale.UK,"%,.2f%n",Math.PI*10000);
          
    }
}

5、字符:

保存一个字符的时候使用char

char对应的封装类是Character 

Character的常见方法:

package character;
 
public class TestChar {
 
    public static void main(String[] args) {
         
        System.out.println(Character.isLetter('a'));//判断是否为字母
        System.out.println(Character.isDigit('a')); //判断是否为数字
        System.out.println(Character.isWhitespace(' ')); //是否是空白
        System.out.println(Character.isUpperCase('a')); //是否是大写
        System.out.println(Character.isLowerCase('a')); //是否是小写
         
        System.out.println(Character.toUpperCase('a')); //转换为大写
        System.out.println(Character.toLowerCase('A')); //转换为小写
 
        String a = 'a'; //不能够直接把一个字符转换成字符串
        String a2 = Character.toString('a'); //转换为字符串
         
    }
}

字符串转换为字符数组             char[] cs = str.toCharArray();

 常见转义:

package character;
  
public class TestChar {
  
    public static void main(String[] args) {
        System.out.println("使用空格无法达到对齐的效果");
        System.out.println("abc def");
        System.out.println("ab def");
        System.out.println("a def");
          
        System.out.println("使用\\t制表符可以达到对齐的效果");
        System.out.println("abc\tdef");
        System.out.println("ab\tdef");
        System.out.println("a\tdef");
         
        System.out.println("一个\\t制表符长度是8");
        System.out.println("12345678def");
          
        System.out.println("换行符 \\n");
        System.out.println("abc\ndef");
 
        System.out.println("单引号 \\'");
        System.out.println("abc\'def");
        System.out.println("双引号 \\\"");
        System.out.println("abc\"def");
        System.out.println("反斜杠本身 \\");
        System.out.println("abc\\def");
    }
}

6、字符串:字符串即字符的组合,在Java中,字符串是一个类,所以我们见到的字符串都是对象 
常见创建字符串手段: 
. 每当有一个字面值出现的时候,虚拟机就会创建一个字符串 
. 调用String的构造方法创建一个字符串对象 
. 通过+加号进行字符串拼接也会创建新的字符串对象 

        String garen ="盖伦"; //字面值,虚拟机碰到字面值就会创建一个字符串对象
         
        String teemo = new String("提莫"); //创建了两个字符串对象
         
        char[] cs = new char[]{'崔','斯','特'};
         
        String hero = new String(cs);//  通过字符数组创建一个字符串对象
         
        String hero3 = garen + teemo;//  通过+加号进行字符串拼接

immutable 是指不可改变的

字符串长度:length()方法返回当前字符串的长度

随机字符串,字符串数组排序,穷举法破解密码

7、操纵字符串

charAt(int index)获取指定位置的字符

toCharArray()获取对应的字符数组

//截取从第3个开始的字符串 (基0)

 String subString1 = sentence.substring(3);         String subString2 = sentence.substring(3,5);

        //根据,进行分割,得到3个子字符串
        String subSentences[] = sentence.split(",");
        for (String sub : subSentences) {
            System.out.println(sub);
        }

System.out.println(sentence.trim());          //去掉首尾空格

        //全部变成小写

        System.out.println(sentence.toLowerCase());

        //全部变成大写

        System.out.println(sentence.toUpperCase());

    public static void main(String[] args) {
    
        String sentence = "盖伦,在进行了连续8次击杀后,获得了超神 的称号";
  
        System.out.println(sentence.indexOf('8')); //字符第一次出现的位置
          
        System.out.println(sentence.indexOf("超神")); //字符串第一次出现的位置
          
        System.out.println(sentence.lastIndexOf("了")); //字符串最后出现的位置
          
        System.out.println(sentence.indexOf(',',5)); //从位置5开始,出现的第一次,的位置
          
        System.out.println(sentence.contains("击杀")); //是否包含字符串"击杀"
          
    }

String temp = sentence.replaceAll("击杀""被击杀"); //替换所有的

temp = sentence.replaceFirst(",","");//只替换第一个

8、比较字符串:

str1和str2的内容一定是一样的!    但是,并不是同一个字符串对象

        String str1 = "the light";
         
        String str2 = new String(str1);
         
        //==用于判断是否是同一个字符串对象
        System.out.println( str1  ==  str2);

是同一个对象-特例

        String str1 = "the light";

        String str3 = "the light";

使用equals进行字符串内容的比较,必须大小写一致 
equalsIgnoreCase,忽略大小写判断内容是否一致

        System.out.println(str1.startsWith(start));//以...开始

        System.out.println(str1.endsWith(end));//以...结束

9、StringBuffer:是可变长的字符串

追加 删除 插入 反转:

package character;
  
public class TestString {
  
    public static void main(String[] args) {
        String str1 = "let there ";
 
        StringBuffer sb = new StringBuffer(str1); //根据str1创建一个StringBuffer对象
        sb.append("be light"); //在最后追加
         
        System.out.println(sb);
         
        sb.delete(4, 10);//删除4-10之间的字符
         
        System.out.println(sb);
         
        sb.insert(4, "there ");//在4这个位置插入 there
         
        System.out.println(sb);
         
        sb.reverse(); //反转
         
        System.out.println(sb);
 
    }
  
}

为什么StringBuffer可以变长?
和String内部是一个字符数组一样,StringBuffer也维护了一个字符数组。 但是,这个字符数组,留有冗余长度
比如说new StringBuffer("the"),其内部的字符数组的长度,是19,而不是3,这样调用插入和追加,在现成的数组的基础上就可以完成了。
如果追加的长度超过了19,就会分配一个新的数组,长度比原来多一些,把原来的数据复制到新的数组中,看上去 数组长度就变长了

自己设计一个可变长度的StringBuffer

package character;
 
public class MyStringBuffer implements IStringBuffer{
 
    int capacity = 16;
    int length = 0;
    char[] value;
    public MyStringBuffer(){
        value = new char[capacity];
    }
     
    //有参构造方法
    public MyStringBuffer(String str){
        this();
        if(null==str)
            return;
         
        if(capacity<str.length()){
            capacity  = value.length*2;
            value=new char[capacity];
        }
         
        if(capacity>=str.length())
            System.arraycopy(str.toCharArray(), 0, value, 0, str.length());
         
        length = str.length();
         
    }
     
    @Override
    public void append(String str) {
 
        insert(length,str);
    }
 
    @Override
    public void append(char c) {
        append(String.valueOf(c));
         
    }
 
    @Override
    public void insert(int pos, char b) {
        insert(pos,String.valueOf(b));
    }
 
    @Override
    public void delete(int start) {
         
        delete(start,length);
    }
 
    @Override
    public void delete(int start, int end) {
        //边界条件判断
        if(start<0)
            return;
         
        if(start>length)
            return;
         
        if(end<0)
            return;
         
        if(end>length)
            return;
         
        if(start>=end)
            return;
         
        System.arraycopy(value, end, value, start, length- end);
        length-=end-start;
         
    }
 
    @Override
    public void reverse() {
 
        for (int i = 0; i < length/2; i++) {
             
            char temp = value[i];
            value[i] = value[length-i-1];
            value[length-i-1] = temp;
        }
         
    }
 
    @Override
    public int length() {
        // TODO Auto-generated method stub
        return length;
    }
 
    @Override
    public void insert(int pos, String b) {
 
        //边界条件判断
        if(pos<0)
            return;
         
        if(pos>length)
            return;
         
        if(null==b)
            return;
         
        //扩容
        while(length+b.length()>capacity){
            capacity = (int) ((length+b.length())*1.5f);
            char[] newValue = new char[capacity];
            System.arraycopy(value, 0, newValue, 0, length);
            value = newValue;
        }
         
        char[] cs = b.toCharArray();
         
        //先把已经存在的数据往后移
         
        System.arraycopy(value, pos, value,pos+ cs.length, length-pos);
        //把要插入的数据插入到指定位置
        System.arraycopy(cs, 0, value, pos, cs.length);
         
        length = length+cs.length;
         
    }
     
    public String toString(){
         
        char[] realValue = new char[length];
 
        System.arraycopy(value, 0, realValue, 0, length);
         
        return new String(realValue);
         
    }
     
    public static void main(String[] args) {
        MyStringBuffer sb = new MyStringBuffer("there light");
        System.out.println(sb);
        sb.insert(0, "let ");
        System.out.println(sb);
 
        sb.insert(10, "be ");
        System.out.println(sb);
        sb.insert(0, "God Say:");
        System.out.println(sb);
        sb.append("!");
        System.out.println(sb);
        sb.append('?');
        System.out.println(sb);
        sb.reverse();
        System.out.println(sb);
         
        sb.reverse();
        System.out.println(sb);
         
        sb.delete(0,4);
        System.out.println(sb);
        sb.delete(4);
        System.out.println(sb);
 
    }
 
}

三、日期

1、Date类 :
注意:是java.util.Date; 
而非 java.sql.Date,此类是给数据库访问的时候使用的

2、时间原点概念:

所有的数据类型,无论是整数,布尔,浮点数还是字符串,最后都需要以数字的形式表现出来。

日期类型也不例外,换句话说,一个日期,比如2020年10月1日,在计算机里,会用一个数字来代替。

那么最特殊的一个数字,就是零. 零这个数字,就代表Java中的时间原点,其对应的日期是1970年1月1日 8点0分0秒 。 (为什么是8点,因为中国的太平洋时区是UTC-8,刚好和格林威治时间差8个小时)

为什么对应1970年呢? 因为1969年发布了第一个 UNIX 版本:AT&T,综合考虑,当时就把1970年当做了时间原点。

所有的日期,都是以为这个0点为基准,每过一毫秒,就+1

Date d1 = new Date();       //当前时间


getTime() 得到一个long型的整数
这个整数代表 从1970.1.1 08:00:00:000 开始 每经历一毫秒,增加1


当前日期的毫秒数
new Date().getTime() 和 System.currentTimeMillis() 是一样的

3、日期格式化:

日期转字符串:

y 代表年

M 代表月

d 代表日

H 代表24进制的小时

h 代表12进制的小时

m 代表分钟

s 代表秒

S 代表毫秒

public static void main(String[] args) {
          
        //y 代表年
        //M 代表月
        //d 代表日
        //H 代表24进制的小时
        //h 代表12进制的小时
        //m 代表分钟
        //s 代表秒
        //S 代表毫秒
        SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS" );
        Date d= new Date();
        String str = sdf.format(d);
        System.out.println("当前时间通过 yyyy-MM-dd HH:mm:ss SSS 格式化后的输出: "+str);
         
        SimpleDateFormat sdf1 =new SimpleDateFormat("yyyy-MM-dd" );
        Date d1= new Date();
        String str1 = sdf1.format(d1);
        System.out.println("当前时间通过 yyyy-MM-dd 格式化后的输出: "+str1);
         
    }

字符串转日期:模式(yyyy/MM/dd HH:mm:ss)需要和字符串格式保持一致,如果不一样就会抛出解析异常ParseException

    public static void main(String[] args) {
        SimpleDateFormat sdf =new SimpleDateFormat("yyyy/MM/dd HH:mm:ss" );
  
        String str = "2016/1/5 12:12:12";
          
        try {
            Date d = sdf.parse(str);
            System.out.printf("字符串 %s 通过格式  yyyy/MM/dd HH:mm:ss %n转换为日期对象: %s",str,d.toString());
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
          
    }

4、Calendar日历:

Calendar与Date进行转换:采用单例模式获取日历对象Calendar.getInstance();

package date;
  
//
import java.util.Calendar;
import java.util.Date;
  
public class TestDate {
  
    public static void main(String[] args) {
        //采用单例模式获取日历对象Calendar.getInstance();
        Calendar c = Calendar.getInstance();
          
        //通过日历对象得到日期对象
        Date d = c.getTime();
  
        Date d2 = new Date(0);
        c.setTime(d2); //把这个日历,调成日期 : 1970.1.1 08:00:00
    }
}

翻日历:

添加方法,在原日期上增加年/月/日
设置方法,直接设置年/月/日

package date;
 
import java.text.SimpleDateFormat;
//
import java.util.Calendar;
import java.util.Date;
 
public class TestDate {
 
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 
    public static void main(String[] args) {
        Calendar c = Calendar.getInstance();
        Date now = c.getTime();
        // 当前日期
        System.out.println("当前日期:\t" + format(c.getTime()));
 
        // 下个月的今天
        c.setTime(now);
        c.add(Calendar.MONTH, 1);
        System.out.println("下个月的今天:\t" +format(c.getTime()));
 
        // 去年的今天
        c.setTime(now);
        c.add(Calendar.YEAR, -1);
        System.out.println("去年的今天:\t" +format(c.getTime()));
 
        // 上个月的第三天
        c.setTime(now);
        c.add(Calendar.MONTH, -1);
        c.set(Calendar.DATE, 3);
        System.out.println("上个月的第三天:\t" +format(c.getTime()));
 
    }
 
    private static String format(Date time) {
        return sdf.format(time);
    }
}

四,推荐书籍

核心Java字典

有效的Java零食,提升代码质量

 

用Java思考提升功力

Head First Java这是给幼儿园小朋友看的

官方出的Java Tutorial BEST OF THE BEST

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值