寒假宅喵java学习

1.25

小fleeting 学习java

关于辅助书籍:
Core Java 字典
比如学习完了IO的知识,觉得意犹未尽,那么就通过这本字典一样的Java书籍,把IO的知识更丰满的刷一遍

Effective Java 零食,提升代码质量
作为初学者,首要任务不是提升质量,而是掌握完成功能的基本手法。这本书就像零食一样,只要主食吃了,你不吃零食也没关系,但是吃点零食会觉得生活质量得到了提升。不用通看,碰到什么,看什么,一次也不应该看太多,当做有益的课外补充。

1. JDK环境配置

     win+R:   cmd

2. 用命令行编译、运行java文件

前情:
小fleeting已经在c盘配置了jdk,并并列建立了project文件
project下设j2se文件,再下设src文件,用来存放java源文件

第一个代码源文件

  public class HelloWorld{
  public static void main(String[] args){
    System.out.println("hello world");
  }
}

命令行效果:
运行结果
其中:
cd c:\project\j2se\src 切换目录到源文件目录
javac filename.java 编译 java文件,并且得到一个class文件
java filename 运行class文件

----------------------------------------------------------------------------------------------

1.26

1.what i learn

  • eclipse

  • 面向对象
    类、属性(字段)、方法

                                    形象表述
    

在这里插入图片描述

                               代码             
public class Hero {
   String name;  //姓名
   float hp;     //血量
   float armor;  //护甲
   int moveSpeed;//移动速度
   
   //超神
   void lengendary(){
	   System.out.println("超神");
   }
   
   //坑队友
   void keng(){
     System.out.println("坑队友!");
   }
   
   //获取护甲值
   float getArmor(){
	 return armor;
   }
   
   //加速
   void addSpeed(int speed){
	   moveSpeed= moveSpeed+speed;
   }
   
   //回血
   void recovery(float blood){
	   hp=hp+blood;
   }
   
   public static void main(String[] args) {
       Hero garen =  new Hero();
       garen.name = "盖伦";
       garen.hp = 616.22f;
       garen.armor=27.5f;
       garen.moveSpeed = 350;
       garen.addSpeed(100);
        
  }
   
}
  • 变量

    基本类型,类型转换,作用域,命名,final
    在这里插入图片描述
    在这里插入图片描述

  • 操作符

异或^:左右两数相同则返回0,不同则为1
任何数和0 进行异或 都等于自己

带符号右移 >>: 移动后正的还是正的,负的还是负的,符号不变
无符号右移>>>:移动后,变正的了

                             **  eg1:**
public class HelloWorld {
    public static void main(String[] args) {
        int i = 1;
        boolean b = !(i++ == 3) ^ (i++ ==2) && (i++==3);
        //i值            2           3
        //表达式           false       true
        //              true    ^   true
        //                      false  
         
        System.out.println(b);
        System.out.println(i);
    }
}

所以,输出结果为:
false
3

                           **eg2:**
public class HelloWorld {
    public static void main(String[] args) {
        int i = 1;
        int j = ++i + i++ + ++i + ++i + i++;
        //i值        2     3     4     5     6
        //取值      2     2     4     5     5
        System.out.println(j);
    }
}

所以结果为18

                            eg3
public class HelloWorld {
    public static void main(String[] args) {
        int i = 1;
        i+=++i;
        // 2
        // 3
        System.out.println(i);
    }
}

相当于i+=++i -->i=i+(++i)–>i=1+(2)–>I=3。

2.新学的programmer

-1 输出
public class HelloWorld{
public static void main(String[] args){

int a;
System.out.println(“输入身高(m):”);
System.out.println(“体制为:” + a);
}
}

-2 输入
import java.util.Scanner;

public class HelloWorld{
public static void main(String[] args){
Scanner s= new Scanner(System.in);
int a=s.nextInt();
float height=s.nextFloat();
}
}

-3 整数转二进制

Integer.toBinaryString()

----------------------------------------------------------------------------------------------

1.27

一、控制流程

  1. deeeeeebug
int  f=10000*Math.pow(1.05, n);//会报错

不是int,因为应该是double类型

2.使用boolean变量结束外部循环

public class HelloWorld {
    public static void main(String[] args) {
        boolean breakout = false; //是否终止外部循环的标记
        for (int i = 0; i < 10; i++) {
 
            for (int j = 0; j < 10; j++) {
                System.out.println(i + ":" + j);
                if (0 == j % 2) {
                    breakout = true; //在内部修改这个变量值
                    break;
                }
            }
            if (breakout) //判断是否终止外部循环
                break;    //借助boolean变量结束外部循环
        }
 
    }
}
  1. 使用标签结束外部循环
   //在外部循环的前一行,加上标签
        outloop: 
        for (int i = 0; i < 10; i++) {
             
            for (int j = 0; j < 10; j++) {
                System.out.println(i+":"+j);
                if(0==j%2) 
                    break outloop; //在break的时候使用该标签,结束外部循环
            }  
        }
        outloop这个标示是可以自定义的比如outloop1,ol2,out5

4.练习-黄金分割点:

寻找某两个数相除,其结果 离黄金分割点 0.618最近
分母和分子不能同时为偶数
分母和分子 取值范围在[1-20]

public class HelloWorld{
 public static void main(String[] args){
   float result=0.382f,maybe;
   int a,b,a1=1,a2=1;
   for (a = 1; a <=20; a++) {
	   for (b = 1; b <=a; b++) {
		 //分母和分子不能同时为偶数
		  if(a%2==0&&b%2==0)           
			   continue;
		  //下面这个必须要先加(float),才能得到正确结果
	      maybe=(float)b/a;
	      if(Math.abs(result-0.618)>Math.abs(maybe-0.618))//绝对值
	      { 
	      result=maybe;
	      a1=a;
	      a2=b;
	      }
	   }
	}
	
   System.out.println("分母"+a1+"分子"+a2);
 }
}

结果:分母13,分子8

  1. 练习 水仙花数(三位数)

个位:i%10
十位:i/10%10
百位:i/100

  1. 调试,断点,单行运行

二、数组

{ 声 明 一 个 引 用 a : i n t [ ] a ; 创 建 一 个 由 a 指 向 的 数 组 : a = n e w   i n t [ 5 ] ; 初 始 化 数 组 : a [ 0 ] = 1 ; a [ 2 ] = 2 ; \left\{ \begin{matrix} 声明一个引用a :int [] a; \\ \\ 创建一个由a指向的数组:a =new \ int[5]; \\ \\ 初始化数组:a[0]=1;a[2]=2; \\ \end{matrix} \right. aint[]a;a:a=new int[5];a[0]=1;a[2]=2;

同时进行
写法一: 分配空间同时赋值

int[] a = new int[]{100,102,444,836,3236};

写法二: 省略了new int[],效果一样

int[] b = {100,102,444,836,3236};

{ 第 i 个 − > 长 度 a . l e n g t h = i 下 标 i − 1 − > 下 标 范 围 \left\{ \begin{matrix} 第i个 ->长度 a.length=i\\ \\ 下标i-1->下标范围\\ \end{matrix} \right. i>a.length=ii1>
(i=1,2,3…)

  1. 排序
  • 选择
    i:0; length-1;++
    j: i+1; length ;++
    在这里插入图片描述
for (int j = 0; j < a.length-1; j++) {
            for (int i = j+1; i < a.length; i++) {
                if(a[i]<a[j]){  
                    int temp = a[j];
                    a[j] = a[i];
                    a[i] = temp;
                }
            }
        }
  • 冒泡
    i: 0;length;++
    j: 0; length-1-i;++
    在这里插入图片描述
 for (int j = 0; j < a.length; j++) {
            for (int i = 0; i < a.length-j-1; i++) {
                if(a[i]>a[i+1]){  
                    int temp = a[i];
                    a[i] = a[i+1];
                    a[i+1] = temp;
                }
            }
        }
  1. 二维数组

     //创建+初始化
    int[][] a = new int[2][3]{     //2表示有两个一维数组,3表示每个一维数组的长度是3
       {1,2,3},
       {4,5,6},
       };
    

    //遍历
    for (int i = 0; i < a.length ; i++) {
        for (int j = 0; j < a[i].length; j++) {
     	a[i][j]。。。。。。
      	}
       }
    

    三.新学的programmer

  2. 随机分配0-100

     (int) (Math.random()*100)
    
  3. 复制数组

    System.arraycopy(src, srcPos, dest, destPos, length)
    

eg:合并数组
首先准备两个数组,他俩的长度是5-10之间的随机数,并使用随机数初始化这两个数组;然后准备第三个数组,把前两个数组合并到第三个数组中

public class HelloWorld{
 public static void main(String[] args){
	int a[]=new int[(int) (Math.random() * 5)+5];
	int b[]=new int[(int) (Math.random() * 5)+5];
	int c[]=new int[a.length+b.length];
	
	
	
	for (int i = 0; i < a.length; i++) {
		a[i]=(int) (Math.random()*100);
	}
	for (int i = 0; i < b.length; i++) {
		b[i]=(int) (Math.random()*100);
	}
	for(int i : a)
	{
		System.out.println(i+" ");
	}
	for(int i : b)
	{
		System.out.println(i+" ");
	}
	
	
	System.arraycopy(a, 0, c, 0, a.length);
	System.arraycopy(b, 0, c, a.length, b.length);
	
	for(int i : c)
	{
		System.out.println(i);
	}
     
 }	
}
     注意:1.增强型for循环
         - 增强型for循环只能用来取值,却不能用来修改数组里的值!赋值不可以!
         -  内部的i直接表示一个数组元素,不用再额外a[i]。
         - 二维数组也可以for增强
       for (int[] row : a) {
          for (int each : row) {
             System.out.print(each + "\t");
          }
          System.out.println();
       }

          2.例题中,放好a后,放b时的destPos是a.length,而不是a.length-1.
  1. Arrays

      import java.util.Arrays; 
    
关键字简介用法
copyOfRange数组复制int a[ ]=Arrays.copyOfRange(original, from, to) // 第一个参数表示源数组 , 第二个参数表示开始位置(取得到) , 第三个参数表示结束位置(取不到)
toString()转换为字符串System.out.println(Arrays.toString(a));
sort正排序Arrays.sort(a);
binarySearch搜索System.out.println(Arrays.binarySearch(a, n)); //n表示要找的数字,返回其所在数组的下标位置。 //使用binarySearch之前,必须先使用sort进行排序
equals判断是否相同System.out.println(Arrays.equals(a, b));
fill填充Arrays.fill(a, 5);

eg:练习-二维数组排序
首先定义一个5X8的二维数组,然后使用随机数填充满。
借助Arrays的方法对二维数组进行排序。

参考思路:
先把二维数组使用System.arraycopy进行数组复制到一个一维数组
然后使用sort进行排序
最后再复制回到二维数组。

import java.util.Arrays; 

public class HelloWorld{
 public static void main(String[] args){
	
	 int a[][]=new int[5][8];
	 int b[]=new int [40];

	 for (int i = 0; i < a.length; i++) {
		for (int j = 0; j < a[i].length; j++) {
			a[i][j]=(int)(Math.random()*100);
		}
	}
    for(int []row:a)
    {
    	System.out.println(Arrays.toString(row));
    }
    System.out.println(" ");
   // 把二维数组复制到一维数组
    for(int i = 0; i < a.length; i++) {
    	System.arraycopy(a[i], 0, b, i*8, a[i].length);
	}
    // 对一维数组进行排序
    Arrays.sort(b);
    // 把一维数组复制到二维数组
    for(int i = 0; i < a.length; i++)
    {
    	System.arraycopy(b, i*8, a[i], 0, a[i].length);
    }
    System.out.println("结果:");
    for(int []row:a)
    {
    	System.out.println(Arrays.toString(row));
    }
  }
}	

运行效果:
在这里插入图片描述

----------------------------------------------------------------------------------------------

1.28

一、类和对象

在这里插入图片描述
1.方法

调用
以下:方法名一样,方法的参数不一样
》》1个参数时:
在这里插入图片描述
输出:盖伦攻击了提莫
》》2个参数时
在这里插入图片描述

升级:继承下的调用
eg:类Support继承类Hero
在这里插入图片描述
在这里插入图片描述
结果:在这里插入图片描述

升级:方法的重载
-public void attack(类名 … 参数名)
-自动给匹配不同的参数对应情
在这里插入图片描述

构造
-方法名和类名一样(包括大小写)
-实例化一个对象的时候,必然调用构造方法
不过一般默认提供一个
-显式写法没有返回类型!!!
-构造也可以带参数
在这里插入图片描述
输出:
Hero 类的构造方法
Hero 类的构造方法

new:实例化

2.this
实例:

 public class Hero {
	 String name;
	 float hp;
	 float armor;
	 int moveSpeed;
	 
	 public Hero(String name,float hp){
		 System.out.println(name+"dl");
	 }
	 
	 public Hero(String name, float hp,float armor, int moveSpeed){
	   this(name,hp);//通过this调用其他的构造方法
	   System.out.println(" bjyxszd");
	   this.armor=armor;通过this访问属性
     }
	 
	 //打印this看到的
	//格式:Hero@c17164 c17164即虚拟地址,每次执行,得到的地址不一定一样
	 public void showAddressInMemory(){
	    System.out.println("虚拟地址:"+this);//this代表当前对象,此处及hp
	 }
	 
    public static void main(String[] args) {
		Hero hp= new Hero("兵长",12,100,12);
		
		System.out.println(hp.armor);
		
		hp.showAddressInMemory();
	}
}

结果:
在这里插入图片描述
3.传参

 eg
   main{ int xueping = 100;
     
         teemo.huixue(xueping);
     
         System.out.println(xueping);      
}
    public void huixue(int xp){
    xp=0;
}
则输出的仍为100,没变


eg:
public void attack(Hero hero, int damage) {
    hero.hp = hero.hp - damage;
}

public static void main(String[] args) {
    Hero teemo = new Hero("提莫", 383);
    garen.attack(teemo, 100);
    System.out.println(teemo.hp);
}
则输出的为283,变
  • 修饰符
    在这里插入图片描述

继承就是extend后,这个类有了父类的字段和方法 (获得了父类属性)
访问就是new了对象后,能直接对象。父类方法或者字段(查看父类属性)

  • private修饰的字段或方法,除了自己这个类,其他类都不能访问和继承
  • 默认的字段属性,同一个包下的类都可以继承或者访问,不同包则不行
  • protected修饰的字段或方法,同包可以继承和访问;但是不同包的类只能继承,不能访问查看
  • public修饰的字段或方法,都能访问,都能继承
  • 别忘记final关键字
  • 类属性static

类属性是公有的,一变都变

  • 类方法static

不需要对象的存在,直接就访问;功能性色彩

  • 属性初始化

eg:对象属性的初始化有三种方式
这三种方式,谁先执行?谁后执行?

    public class Hero {
    public String name = "some hero"; 
 
     public Hero(){
         name = "one hero";
     }
     {
         name = "the hero";
     }
   }
  解析:
    【实践打印】先设计一个类方法 public static String getName(String pos)
    在属性初始化的时候,调用这个方法的返回值。 观察这个方法的输出顺序
package charactor;

public class Hero {
  public String name =Hero.getName("属性声明") ;
    
  public Hero(){
      name = Hero.getName("构造方法");
  }
  {
      name = Hero.getName("初始化块");
  }
   
  public static String getName(String pos){
      System.out.println(pos);
      return pos;
  }
   
  public static void main(String[] args) {
      new Hero();
  }
}

得到
在这里插入图片描述

  • 单例模式

饿汉/懒汉(尤其是视频)
三要素 :1.构造方法私有化 (private) 2.类属性实例化一次 (private static) 3.类方法getInstance,返回上一步的类属性。(public static)
这样,外部无法通过new 得到新的实例

  • 枚举类型

枚举enum的地位和class一样,是一种特殊的类
1.预先定义常数

public enum Season {
	SPRING,SUMMER,AUTUMN,WINTER
   }

2.不能实例化。
- Season jijie= new Season(); 会报错
- Season jijie= Season.SPRING; ✔
3.常用于固定情景,如switch。
使用枚举,就能把范围死死的限定在这目标范围当中
4.遍历枚举:通过 values返回数组

       Season a[]=Season.values();  //values返回枚举数组
       for(Season i:a)
       {
    	   System.out.println(i);
       }

二、接口与继承

  1. 接口

    AD.java:
    
package character;
//设计了这么一个接口,在接口里规定了他会物理攻击这个方法。
public interface AD {
    public void physicAttack();//仅声明了方法,没有方法体。
 }  
 //某一个类如果要实现这个接口,就必须要提供这里边的这个方法。

 ADhero.java:
package charactor;
 
public class ADHero extends Hero implements AD{
 //某一个类如果要实现这个接口,就必须要提供这里边的这个方法。
  
    @Override   //只是一个规范化注解
    public void physicAttack() {
        System.out.println("进行物理攻击");
    }
 
}

  1. 对象转型
  • 向上转型(子类转化成父类,类转化为接口)都成功;反之不一定

练习1:

package charactor;
  
import charactor1.Support;
  
public class Hero {
    public String name;
    protected float hp;
      
    public static void main(String[] args) {
        Hero h =new Hero();
        ADHero ad = new ADHero();
        Support s =new Support();
          
        h = ad;
        ad = (ADHero) h;
        h = s;
        ad = (ADHero)h;
    }
      
}
以上    1.前情:ADHero和Support都是Hero的继承,是其子类

        2.    Hero ad     =     new Hero();
              引用       指向     对象类型
           
        3.       h        =       ad;       //子类转成父类,恒成立
              Hero类     指向     ADHero类    
                
                 ad       =        h;       //父类转成子类,不一定
             ADHero类    指向      Hero
              
      第一个     ad       =       (ADHero) h;     //成立 
             ADHero类    指向   Hero被强制转化成ADHero类  

        第二个     ad       =       (ADHero) h;   //不成立
             ADHero类    指向   support无法强制转化成adhero,因为没有继承关系  

练习2:

package charactor;
     
public class Hero {
    public String name;
    protected float hp;
         
    public static void main(String[] args) {
        ADHero ad = new ADHero();
            
        AD adi = ad;
   
        ADHero adHero = (ADHero) adi;
            
        adapHero.magicAttack();
    }
         
}
  以上  1. AD adi = ad;  
          把一个ADHero类型转换为AD接口
     从语义上来讲,把一个ADHero当做AD来使用,而AD接口只有一个
     physicAttack方法,这就意味着转换后就有可能要调用physicAttack
     方法,而ADHero一定是有physicAttack方法的,所以转换是能成功的。
       2. ADHero adHero = (ADHero) adi;
        adi引用所指向的对象是一个ADHero,要转换为ADAPHero就会
           失败。假设能够转换成功,那么就可以使用magicAttack方法,而
           adi引用所指向的对象ADHero是没有magicAttack方法的。
  • instanceof

//判断引用h1指向的对象,是否是ADHero类型
System.out.println(h1 instanceof ADHero);
//判断引用h1指向的对象,是否是Hero的子类型
System.out.println(h1 instanceof Hero);

重写
关键:子类继承父类后,于子类中重新提供该方法。
是子类覆盖父类的对象方法

隐藏
是子类覆盖父类的类方法
∵是类方法,所以调用只与其类型有关,而与指向哪个对象无关

  • 多态

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

                           练习
 1. 设计一个接口
     接口叫做Mortal,其中有一个方法叫做die
 2. 实现接口
     分别让ADHero,APHero,ADAPHero这三个类,实现Mortal接口,不同的
     类实现die方法的时候,都打印出不一样的字符串
 3. 为Hero类,添加一个方法,在这个方法中调用 m的die方法。
        public void kill(Mortal m)
 4. 在主方法中
   首先实例化出一个Hero对象:盖伦
   然后实例化出3个对象,分别是ADHero,APHero,ADAPHero的实例
   然后让盖伦 kill 这3个对象

代码如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

----------------------------------------------------------------------------------------------

1.29

一、接口与继承(续上)

在这里插入图片描述

  • super

    实例化子类的时候,无论如何 都会先调用父类的构造方法
    默认情况下,会调用父类的无参的构造方法。
    eg:代码:
    (此处父类显式地提供了无参构造)
    在这里插入图片描述
    在这里插入图片描述
    会输出:
    在这里插入图片描述

使用关键字super 显式调用父类带参的构造方法
则实例化子类的时候,调用父类有参的构造方法。
对比:关键词this调用当前对象
eg:
在这里插入图片描述
在这里插入图片描述
\ !结果

但是,当父类没有无参构造方法的时候( 提供了有参构造方法,并且不显示提供无参构造方法),子类就会抛出异常,因为它尝试去调用父类的无参构造方法。
遇到这种情况,有2种解决办法。
第一,把父类当中的无参构造方法补上去。
第二,不补父类的无参构造方法,直接调用父类存在的的有参构造方法,但是参数为空字符,即super(“ ”)

  • object

    -Object类是所有类的父类
    -toString() finalize() equals()
package character;
  
public class Hero {
    public String name;
    public float price;
     
    //toString()的意思是返回当前对象的字符串表达
    public String toString()
    {
    	return "这位"+name+"怒气值"+price;
    }
    
    //当一个对象没有任何引用指向的时候,它就满足垃圾回收的条件
    //当它被垃圾回收的时候,它的finalize() 方法就会被调用
    public void finalize()
    {
    	System.out.println("他的团长被回收了");	
    }
   
    //equals() 用于判断两个对象的内容是否相同
    public boolean equals(Object o)  
    {
    	if(o instanceof Hero){
    		Hero oo=(Hero) o;
    		return(this.price==oo.price);   //更准确的讲,==用于判断两个引用,是否指向了同一个对象
    	}
    	return false;
    }
    public static void main(String[] args) {
        
    	for (int i = 0; i < 80000; i++) {
    		//不断生成新的对象
            //每创建一个对象,前一个对象,就没有引用指向了
            //那些对象,就满足垃圾回收的条件
            //当,垃圾堆积的比较多的时候,就会触发垃圾回收
            //一旦这个对象被回收,它的finalize()方法就会被调用
        	Hero h= new Hero();
		}
    	
    	Hero h1= new Hero();
        h1.name = "兵长";
        h1.price=10000f;
        Hero h2= new Hero();
        h2.price=1000f;
         
        System.out.println(h1.toString());
        System.out.println(h1.equals(h2));
    }
}
  • abstract抽象类

    抽象方法:
    在类中声明一个方法,这个方法没有实现体,是一个“空”方法

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


    当一个类有抽象方法的时候,该类必须被声明为抽象类
package charactor;
 
public abstract class Hero {
    String name;
 
    float hp;
 
    float armor;
 
    int moveSpeed;
 
    public static void main(String[] args) {
 
    }
 
    // 抽象方法attack
    // Hero的子类会被要求实现attack方法
    public abstract void attack();
 
}

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

  • 内部类

1. { 非 静 态 内 部 类 : n e w 外 部 类 对 象 内 部 类 ( ) ; 静 态 内 部 类 : n e w 外 部 类 . 静 态 内 部 类 ( ) ; 匿 名 类 : 声 明 一 个 类 的 同 时 实 例 化 它 本 地 类 : 申 明 时 无 需 与 属 性 和 方 法 平 等 \left\{ \begin{matrix} 非静态内部类 : new 外部类对象内部类(); \\ \\静态内部类:new 外部类.静态内部类(); \\ \\匿名类:声明一个类的同时实例化它 \\ \\本地类:申明时无需与属性和方法平等 \end{matrix} \\ \right. new();new.();
详见内部类

  1. 匿名类举例:
public abstract class Hero {
   public abstract void seal();//声明抽象方法。
   
   public static void main(String[] args) {
	    
	   //匿名类
	   Hero bz=new Hero(){        //直接实例化一个抽象类
		   public void seal(){      //并“当场”实现其抽象方法。
			   System.out.println("binzhang");
		   }
	   };
	   bz.seal();
	   
}
      
}
  1. 在匿名类中使用外部的局部变量,外部的局部变量必须修饰为final
  • 默认方法

-接口也可以提供具体方法
-声明成 default

package charactor;
 
public interface Mortal {
    public void die();
 
    default public void revive() {   //默认方法revive
        System.out.println("本英雄复活了");
    }
}
  • UML

在这里插入图片描述
在这里插入图片描述

二、练习

练习-Animal类

  1. 创建Animal类,它是所有动物的抽象父类。
  2. 声明一个受保护的整数类型属性legs,它记录动物的腿的数目。
  3. 定义一个受保护的构造器,用来初始化legs属性。
  4. 声明抽象方法eat。
  5. 声明具体方法walk来打印动物是如何行走的(包括腿的数目)。

练习-Spider类

  1. Spider继承Animal类。
  2. 定义默认构造器,它调用父类构造器来指明所有蜘蛛都是8条腿。
  3. 实现eat方法

练习-Pet接口
根据UML类创建pet(宠物)接口

  1. 提供getName() 返回该宠物的名字
  2. 提供setName(String name) 为该宠物命名
  3. 提供 play()方法

练习-Cat类

  1. 该类必须包含String属性来存宠物的名字。
  2. 定义一个构造器,它使用String参数指定猫的名字;该构造器必须调用超类构造器来指明所有的猫都是四条腿。
  3. 另定义一个无参的构造器。该构造器调用前一个构造器(用this关键字)并传递一个空字符串作为参数
  4. 实现Pet接口方法。
  5. 实现eat方法。
public abstract class Animal {
   protected int legs;
   protected Animal(int legs)
   {
	   this.legs=legs;
   }
   public abstract void eat();
   
   public void walk(){
	  System.out.println("动物走路用"+legs+"只脚");
   }	   
}`
package exercise;

public class Spider extends Animal{
    
	public void eat(){
		System.out.println("实现了eat方法");
	}
	public Spider(){
		super(8);
	}
}

package exercise;

public interface pet {
	public String getName();
	public void setName(String name);
	public void play();
}

package exercise;

public class Cat extends Animal implements pet{
   
	
	// 该类必须包含String属性来存宠物的名字。
	private String name="猫";
   
	//定义一个构造器,它使用String参数指定猫的名字;该构造器必须调用超类构造器来指明所有的猫都是四条腿。
   public Cat(String name){
	   super(4);
	   this.name=name;
   }
   
   // 另定义一个无参的构造器。该构造器调用前一个构造器(用this关键字)并传递一个空字符串作为参数
   public Cat(){
	  this(" "); 
   }
   
   //实现Pet接口方法。
    @Override
	public String getName(){
		return name;
	}
    @Override
	public void setName(String name){
		this.name=name;
    	System.out.println("实现setname方法");
	}
    @Override
	public void play(){
		System.out.println("实现play方法");
	}
	
	// 实现eat方法。
    public void eat(){
    	System.out.println("实现eat方法");
    }
}

三、日期

  • Date类
    – java.util.Date
    –时间原点(1970年),过一毫秒则+1
    –基本用法:

new Date():当前时间
new Date(数字x):表示从原点开始,+x毫秒后的时间
getTime():表示从原点开始经历的毫秒数

package date;
import java.util.Date;
//注意:是java.util.Date;
//而非 java.sql.Date,此类是给数据库访问的时候使用的
  
public class TestDate {
  
    public static void main(String[] args) {

        Date now= new Date();
        //打印当前时间
        System.out.println("当前时间:"+now);
        
        Date zero = new Date(0);
        System.out.println("用0作为构造方法,得到的日期是:"+zero);        
        Date zero2 = new Date(5000);
        System.out.println("从1970年1月1日 早上8点0分0秒 开始经历了5秒的时间"+zero2);
          
        //getTime() 得到一个long型的整数
        //这个整数代表 1970.1.1 08:00:00:000,每经历一毫秒,增加1
        System.out.println("当前时间getTime()返回的值是:"+now.getTime());
       
    }
}

在这里插入图片描述

  • 日期格式化类(SimpleDateFormat)

    • 日期转字符串:format
      -java.text.SimpleDateFormat;
package date;
  
//
import java.text.SimpleDateFormat;
import java.util.Date;
  
public class TestDate {
  
    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("当前时间格式化后的输出: "+str);
        
    }
}

在这里插入图片描述

ADD: syso出的都是String类型,所以日期类如果要syso输出,需要先format成String。

  • 字符串转日期:parse
    –import java.text.ParseException;
package date;
import java.util.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
  
public class TestDate {
  
    public static void main(String[] args) {
        SimpleDateFormat sdf =new SimpleDateFormat("yyyy/MM/dd HH:mm:ss" );
  
        String str = "2016/1/5 12:12:12";
        System.out.println(str);
          
        try {
        	//字符串通过格式转换为日期对象
            Date d = sdf.parse(str);
            System.out.println(d);
        } catch (ParseException e) {
            e.printStackTrace();
        }
          
    }
}

在这里插入图片描述

练习-日期格式化

准备一个长度是9的日期数组
使用1970年-2000年之间的随机日期初始化该数组
按照这些日期的时间进行升序排序
比如 1988-1-21 12:33:22 就会排在 1978-4-21 19:07:23 前面,因为它的时间更小,虽然日期更大

package date;
import java.util.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
 

public class TestDate {
  
	public static Date getRandomDate(int start,int end)
	{
		SimpleDateFormat sdf =new SimpleDateFormat("yyyy");
		try{
			//将年份转化为字符串,再转化成日期类型
			Date dstart=sdf.parse(String.valueOf(start));//将基本数据型态转换成 String 的 static 方法 
			Date dend=sdf.parse(String.valueOf(end+1));// 2001 不是 2000,要在2001的基础上减少以毫秒,才表示2000最后一刻
			
			//获得相对时间原点,并进行随机分布
			long tstart=dstart.getTime();
			long tend=dend.getTime();
			long timeRandom = (long) (tstart + Math.random() * (tend - tstart));
		
			Date randomDate=new Date(timeRandom);
			return randomDate;
			
		}catch(ParseException e){
			e.printStackTrace();
		}
		return null;
	}
    
	//日期转化为字符串格式
    public static String toString(Date d, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(d);
    }
    
	public static void main(String[] args) {
        
		//准备一个长度是9的日期数组
    	Date d[]=new Date[9];
    	
    	//使用随机日期初始化该数组
    	for(int i=0;i<d.length;i++)
    	{
    		d[i]=getRandomDate(1970,2000);
    	}
    	
    	//输出日期数组
    	System.out.println("得到的随机日期数组:");
    	for(int i=0;i<d.length;i++)
    	{
    		//日期转化为字符串输出
    		System.out.println(toString(d[i],"yyyy-MM-dd HH:mm:ss")+"\t");
    	    if(i%3==2)
    	    	System.out.println();
    	}
    	
       
    	//选择法排序
        for (int i = 0; i < d.length-1; i++) {
            for (int j = i+1; j < d.length; j++) {
            	//日期转字符串
                String istr = toString(d[i],"HHmmss");
                String jstr = toString(d[j],"HHmmss");
 
                //字符串转整型
                int ilnt = Integer.parseInt(istr);
                int jlnt = Integer.parseInt(jstr);
 
                //排序
                if( ilnt>jlnt  ){  
                    Date temp = d[j];
                    d[j] = d[i];
                    d[i] = temp;
                }
            }
        }
    	
    	//输出排序后日期数组
    	 System.out.println("排序后的随机日期数组:");
         for (int i = 0; i < d.length; i++) {
             System.out.print(toString(d[i],"yyyy-MM-dd HH:mm:ss")+"\t");
             if(2==i%3)
                 System.out.println();
         }
    	
    }
}

Calendar类

常用于进行“翻日历”,比如下个月的今天是多久

  • Calendar与Date进行转换
import java.util.Calendar;
import java.util.Date;
  
public class TestDate {
  
    public static void main(String[] args) {
        //采用单例模式获取日历对象Calendar.getInstance();
        Calendar c = Calendar.getInstance();
        System.out.println("1:"+c);  
        
        //通过日历对象得到日期对象
        Date d = c.getTime();
        System.out.println("2:"+d);  
  
        Date d2 = new Date(0);
        System.out.println("3:"+d2);  
        c.setTime(d2); //把这个日历,调成日期 : 1970.1.1 08:00:00
        System.out.println("4:"+d2);  
        System.out.println("5:"+c);  
        
    }
}

在这里插入图片描述

  • 翻日历
    add方法,在原日期上增加年/月/日
    set方法,直接设置年/月/日/
        Calendar c = Calendar.getInstance();
        Date now = 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()));
 **练习-Calendar**
== 找出下个月的倒数第3天是哪天==
package date;
  
//
import java.util.Calendar;
import java.util.Date;
import java.text.SimpleDateFormat;

  

public class TestDate {
  
	public static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	
    public static void main(String[] args) {
        //采用单例模式获取日历对象Calendar.getInstance();
        Calendar c = Calendar.getInstance(); 
        
        //通过日历对象得到日期对象
        //***输出方法一
        Date d = c.getTime();
        System.out.println("今天是:"+sdf.format(d));  
  
        //先翻到下下个月
        c.add(Calendar.MONTH,2);
        //设置到月初
        c.set(Calendar.DATE,1);
        //再往回翻3天
        c.add(Calendar.DATE,-3);
        
        //***输出方法二
        String str=sdf.format(c.getTime());
        System.out.println("这个月的倒数第三天:"+str);
        
    }
}
//两种输出方法,其实质都是把日历------》日期------》字符串------》输出
//                 (getTime)      (format)     (syso)

在这里插入图片描述

----------------------------------------------------------------------------------------------

1.30

在这里插入图片描述=

一、数字与字符串

  • 封装类
    即:所有的基本类型对应的类类型
    比如int对应的类是Integer

  • 拆装箱
    基本类型和封装类型间的相互转化
    两种方法

  • 最大值、最小值
    封装类.MAX_VALUE
    封装类.MIN_VALUE
    用于在这里插入图片描述
    在这里插入图片描述
    - 字符串转换
    步骤 1 : 数字转字符串
    步骤 2 : 字符串转数字
    比如:String类与int类转化,Integer为中介

    在这里插入图片描述
    - 数学方法
    - java.lang.Math
    - 静态方法:
    四舍五入(round), 随机数(random),开方(sqrt),次方(pow)
    π(PI),自然常数(E)

                    练习:求1000,0000内质数个数
    
          方一:`
    
package digit;
public class TestNumber {
   
	public static void main(String[] args){
	int n=0;
	for(int i=1;i<=10000000;i++){
		int flag=1; 
		for (int j = 2; j <=Math.sqrt(i); j++) {
			
	    	 if(i%j==0)
			{
				flag=0;
				break;
			}
		}
	    if(flag==1)
			n++;
	}
	System.out.println(n);
  }
}
   方二:
package digit;
 
public class TestNumber {
 
    public static void main(String[] args) {
         
        int max = 10000*1000;
        int count = 0 ;
        for (int i = 1; i <=max; i++) {
            if(isPrime(i)){
                count++;
            }
        }
        System.out.println("一千万以内的质数一共有 : " + count);
 
    }
 
    private static boolean isPrime(int i) {
        for (int j = 2; j <= Math.sqrt(i); j++) {
            if(0==i%j)
                return false;
        }
        return true;
    }
     
}
  • 格式化输出
    -printf和println
    eg:
    //直接使用+进行字符串连接,
    System.out.println( name+ " 在进行了连续 " + kill);
    //使用格式化输出
    System.out.printf("%s 在进行了连续 %d " ,name,kill);
    - %n换行,%r回车

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

    - 总长度,左对齐,补0,千位分隔符,小数点位数,本地化表达

        int year = 2020;
          
        //直接打印数字
        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);

输出:在这里插入图片描述


字符

char, Character
在这里插入图片描述

  • 字符转成字符串
 String a = 'a'; //不能够直接把一个字符转换成字符串
 String a2 = Character.toString('a'); //转换为字符串
  • 字符串转化为字符数组
String str = "abc123";
char[] cs = str.toCharArray(); 
  • 一个 \t 制表符长度是8,可以达到对齐的效果
        System.out.println("abc\tdef");
        System.out.println("ab\tdef");
        System.out.println("a\tdef");

在这里插入图片描述

  • 字符串

    Java中,字符串是一个类,所以我们见到的字符串都是对象
    String类 不能被继承

    字符串创建好后,不可改变。

    常见创建字符串手段:

    1. 每当有一个字面值出现的时候,虚拟机就会创建一个字符串

    2. 调用String的构造方法创建一个字符串对象

      String teemo = new String(“提莫”); // 通过String创建了一个字符串对象

      char[] cs = new char[]{‘崔’,‘斯’,‘特’};

      String hero = new String(cs); // 通过字符数组创建一个字符串对象

    3. 通过+加号进行字符串拼接也会创建新的字符串对象

练习:创建一个长度是5的随机字符串,随机字符有可能是数字,大写字母或者小写字母

package digit;
   
public class TestNumber {
   
    public static void main(String[] args) {
  
        int n=0;
        String str="";
        while(n<5)
        {
        	//ASCII表中,‘0’到‘z‘间包含的所有字符
        	char aa=(char)(Math.random()*74+48);
        	//挑出满足的字符
        	if(Character.isDigit(aa)||Character.isLetter(aa))
        	{
                str+=aa;  //通过+加号进行字符串拼接也会创建新的字符串对象
                n++;
        	}
        }
        System.out.println(str);
    }
}

练习:字符串数组排序
创建一个长度是8的字符串数组
使用8个长度是5的随机字符串初始化这个数组
对这个数组进行排序,按照每个字符串的首字母排序(无视大小写)

package digit;
   
public class TestNumber {
	
	//创建长度是5的随机字符串
	static String randomString(){
	   int n=0;
       String str="";
       while(n<5)
       {
       	//ASCII表中,‘0’到‘z‘间包含的所有字符
       	char aa=(char)(Math.random()*74+48);
       	//挑出满足的字符
       	if(Character.isDigit(aa)||Character.isLetter(aa))
       	{
               str+=aa;  //通过+加号进行字符串拼接也会创建新的字符串对象
               n++;
       	}
       }
       return str;
   }
	
	//返回该字符串的第一个首字母
		static char getFirstletter(String str)
		{
			char []c =str.toCharArray();
			for (int i = 0; i < c.length; i++) {
				if(c[i]>='0'&&c[i]<='9')
					continue;
				if(c[i]>='a'&&c[i]<='z')
					c[i]-=32;
				return c[i];
			}
			return 0;
		}
	
    public static void main(String[] args) {
    
    	//创建一个长度是8的字符串数组
        String []a=new String[8];
        
        //使用随机字符串初始化这个数组
        System.out.println("原数组为:");
        for(int i=0;i<a.length;i++)
        {
        	a[i]= randomString();
        	System.out.printf("%s ",a[i]);
        }
        

    	//对这个数组按照每个字符串的首字母排序(无视大小写)
         char cc[]=new char[8];
    	 for(int i=0;i<a.length;i++)
    	   {
    	     cc[i]= getFirstletter(a[i]);
    	     //System.out.printf("%c ",cc[i]);
    	   }
    	 
    	 //按照每个字符串的首字母选择排序
    	 for (int j = 0; j < cc.length-1; j++) {
             for (int k = j+1; k < cc.length; k++) {
                 if(cc[k]<cc[j]){  
                     String temp = a[j];
                     a[j] = a[k];
                     a[k] = temp;
                     char TEMP = cc[j];
                     cc[j] = cc[k];
                     cc[k] = TEMP;
                 }
             }
         }
    	 //输出排序后的数组
         System.out.println("");
         System.out.println("排序后数组为:");
         for(int i=0;i<a.length;i++)
         {
         	System.out.printf("%s ",a[i]);
         } 	        
    	        
    }
 }

练习:破解密码

  1. 生成一个长度是3的随机字符串,把这个字符串作为当做密码

  2. 使用穷举法生成长度是3个字符串,匹配上述生成的密码

package digit;
   
public class TestNumber {
	
	//创建长度是3的随机字符串
	static String randomString(){
	   int n=0;
       String str="";
       while(n<3)
       {
       	//ASCII表中,‘0’到‘z‘间包含的所有字符
       	char aa=(char)(Math.random()*74+48);
       	//挑出满足的字符
       	if(Character.isDigit(aa)||Character.isLetter(aa))
       	{
               str+=aa;  //通过+加号进行字符串拼接也会创建新的字符串对象
               n++;
       	}
       }
       return str;
   }
		

	//使用递归生成 长度为3的字符串,并匹配
    public static boolean found=false;

    //递归
    public static void generate(char[] guessword,int index,String password){
       if(found)
    	    return;
       //生成
       for(char c='0';c<='z';c++)
       {
           if(!Character.isLetterOrDigit(c))
               continue;
           guessword[index]=c;
           //下一层
           if(index!=guessword.length-1){
               generate(guessword,index+1,password);
           }
           //最后一层
           else{
        	   String guess= new String(guessword);
        	   //匹配
        	   if(guess.equals(password)){
                   System.out.println("找到了,密码是" + guess);
                   found =true;  
        	   }
           }     
       }
   }
    public static void main(String[] args) {
    

        	String password= randomString();
        	System.out.println("密码是:" + password);
        	
        	char[] guessword=new char[3];
        	generate(guessword,0,password);
        }
 }
 
  • 字符串基本操作
  • .charAt(int index) :获取指定位置的字符(基0)
    .toCharArray(): 获取对应的字符数组
    .substring(int):截取子字符串(基0)(“左开右闭”或“从左边开始”)
    .split(char c) 分隔 (根据分隔符进行分隔,得到几个字符串)
    .trim() 去掉首尾空格
    .toLowerCase()
    .toUpperCase() 大小写
    .indexOf(char)
    .lastIndexOf(char)
    .contains(char) 定位
    .replaceAll(char,char)
    .replaceFirst(char,char) 替换
    在这里插入图片描述

练习:每个单词的首字母都转换为大写
给出一句英文句子: “let there be light”
得到一个新的字符串,每个单词的首字母都转换为大写
解析:

              句子------------------ 单词---------------------字母
             字符串(间隔符)      字符串数组   (字符数组)    字符
package digit;
   
public class TestNumber {
	
	
    public static void main(String[] args) {
        //字符串
    	String s = "let there be light";
        System.out.println(s);
        
        //字符串数组
        String words[]=s.split(" ");
        for(int i=0;i<words.length;i++){
          //首字符
          char FirstLetter = Character.toUpperCase(words[i].charAt(0));
          //剩余字符
          String rest=words[i].substring(1);
          //组建1
          words[i]=FirstLetter+rest;
        }
     
        //组建2(成字符串)
        String result="";
        for(String word : words){
        	result+=word+" ";	
        }
        result=result.trim();
        System.out.println(result);
    
    }
}

练习:单词间隔大写小写模式
把 lengendary 改成间隔大写小写模式,即 LeNgEnDaRy

package digit;
   
public class TestNumber {    
    public static void main(String[] args) {
        String s = "lengendary";
        char[] cs =s.toCharArray();

        for (int i = 0; i < cs.length; i++) {
            if(0==i%2)
                cs[i] = Character.toUpperCase(cs[i]);
        }
        String result = new String(cs);
        System.out.printf(result);
 
    }
}

**练习:把最后一个two单词首字母大写 **
Nature has given us that two ears, two eyes, and but one tongue, to the end that we should hear and see more than we speak
把最后一个two单词首字母大写

package digit;
   
public class TestNumber {    
    public static void main(String[] args) {
        String s = "Nature has given us that two ears, two eyes, and but one tongue, to the end that we should hear and see more than we speak";
        char sc[]=s.toCharArray();
        
        int location=s.lastIndexOf("two");
        sc[location]='T';
        
        String result="";
        for(char i:sc)
        {
        	result+=i;
        }
        System.out.printf(result);
 
    }
}
  • 字符串之间

    • 内容是否相同:

使用equals进行字符串内容的比较,必须大小写一致
equalsIgnoreCase,忽略大小写判断内容是否一致
eg:
str1.equals(str2)
str1.equalsIgnoreCase(str3)
返回true/false

  • 所指对象是否相同:==
  • 是否以子字符串开始或者结束顶折纠问

startsWith //以…开始
endsWith //以…结束

练习:比较字符串
创建一个长度是100的字符串数组
使用长度是2的随机字符填充该字符串数组
统计这个字符串数组里重复的字符串有多少种
如:在这里插入图片描述

package digit;
   
public class TestNumber {
	
	//创建长度是2的随机字符串
	static String randomString(){
	   int n=0;
       String str="";
       while(n<2)
       {
       	//ASCII表中,‘0’到‘z‘间包含的所有字符
       	char aa=(char)(Math.random()*74+48);
       	//挑出满足的字符
       	if(Character.isDigit(aa)||Character.isLetter(aa))
       	{
               str+=aa;  //通过+加号进行字符串拼接也会创建新的字符串对象
               n++;
       	}
       }
       return str;
   }
	
    static String[]cc = new String[100];
    static int  pos=0;
    private static int putIntoDuplicatedArray(String s) {
            int flag=1; 
    	    for (int i = 0; i < pos; i++) {
				if(s.equals(cc[i])==true){
					flag=0;
					break;
				}
             }
              if(flag==1){
            	 cc[pos++]=s;
            	 return 1; 
              }
              else
            	  return 0;
    }
	
    public static void main(String[] args) {
    
    	//创建一个长度是100的字符串数组
    	int count=0;
        String []a=new String[100];
        
        //使用随机字符串初始化这个数组
        System.out.println("原数组为:");
        for(int i=0;i<a.length;i++)
        {
        	a[i]= randomString();
        	System.out.printf("%s ",a[i]);
        }
        

        for(int i=0;i<a.length;i++){
        	int flag=0;
        	for(int j=i+1;j<a.length;j++){
        		if(a[i].equals(a[j]))
        			{
        			flag++;
        			if(flag==1)
        				count+=putIntoDuplicatedArray(a[i]);
        			break;
        			} 		    
        	  }
        }
        System.out.println("");	
        System.out.println("有"+count+"种重复");	
        for(int i=0;i<pos;i++){
        	System.out.println("它是:"+cc[i]);
        }
 	        
    }
 }

输出结果:
在这里插入图片描述

============================================================================================================================================

1.31

  • StringBuffer

  • StringBuffer是可变长的字符串(基0)
  • 本质:留有冗余长度
  • 基本操作:
    append(String str); //追加字符串
    append(char c); //追加字符
    insert(int pos,char b); //指定位置插入字符
    insert(int pos,String b); //指定位置插入字符串
    delete(int start); //从开始位置删除剩下的
    delete(int start,int end); //从开始位置删除结束位置-1
    reverse(); //反转
    length(); //返回长度
String str1 = "let there ";
 
        StringBuffer sb = new StringBuffer(str1); //根据str1创建一个StringBuffer对象
        //其实也可以直接创建  StringBuffer sb = new 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);

在这里插入图片描述

在这里插入图片描述

length: “the”的长度 3
capacity: 分配的总空间 19

  • 练习:MyStringBuffer

解析:插入insert 和 append

(1)边界条件判断
插入之前,首先要判断的是一些边界条件。 比如插入位置是否合法,插入的字符串是否为空
(2)扩容
1. 要判断是否需要扩容。 如果插入的字符串加上已经存在的内容的总长度超过了容量,那么就需要扩容。
2. 数组的长度是固定的,不能改变的,数组本身不支持扩容。 我们使用变通的方式来解决这个问题。
3. 根据需要插入的字符串的长度和已经存在的内容的长度,计算出一个新的容量。 然后根据这个容量,创建一个新的数组,接着把原来的数组的内容,复制到这个新的数组中来。并且让value这个引用,指向新的数组,从而达到扩容的效果。
(3)插入字符串
1. 找到要插入字符串的位置,从这个位置开始,把原数据看成两段,把后半段向后挪动一个距离,这个距离刚好是插入字符串的长度
2. 然后把要插入的数据,插入这个挪出来的,刚刚好的位置里。
(4)修改length的值
最后修改length的值,是原来的值加上插入字符串的长度
(5)insert(int, char)
参数是字符的insert方法,通过调用insert(int, String) 也就实现了。

append
追加,就是在最后位置插入。 所以不需要单独开发方法,直接调用insert方法,就能达到最后位置插入的效果

delete
在这里插入图片描述

代码如下:
IStringBuffer.java

package digit;
  
public interface IStringBuffer {
    public void append(String str); //追加字符串
    public void append(char c);  //追加字符
    public void insert(int pos,char b); //指定位置插入字符
    public void insert(int pos,String b); //指定位置插入字符串
    public void delete(int start); //从开始位置删除剩下的
    public void delete(int start,int end); //从开始位置删除结束位置-1
    public void reverse(); //反转
    public int length(); //返回长度
}
                      MyStringBuffer.java
package digit;
 
public class MyStringBuffer implements IStringBuffer{
 
    int capacity = 16;
    int length = 0;
    char[] value;//value:用于存放字符数组
    
    //无参构造方法
    public MyStringBuffer(){
        value = new char[capacity];//根据容量初始化value
    }
     
    //有参构造方法
    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());

        // 或:value =str.toCharArray();(字符数组指向字符串转化过来的字符数组)
         
        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
    //从开始位置删除结束位置-1
    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())*2.0f);
            //因为数组长度不能变
            //等号右边:创建一个新的字符数组   ;等号左边:通过一个新的引用指向这个字符数组
            char[] newValue = new char[capacity];
            System.arraycopy(value, 0, newValue, 0, length);//把老的数组(内容)复制到新的数组
            value = newValue;//通过老引用=新引用,让value间接指向一个新的字符数组
        }
         
        char[] cs = b.toCharArray();
         
        //通过复制arraycopy
        //先把已经存在的数据往后移
        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);
 
    }
 
}


输出:

在这里插入图片描述


---------------------------------------------------------------------------------------------------------------------------

小fleeting的寒假宅喵java学习
基础篇在此就告一段落啦!!!
呼,花了快一周的时间,
不过小fleeting很有成就感💪
寒假宅味之 《进阶收获upup篇》 马上就要来啦 ~~要follow下去呦~
下一夜,我也会向你展示一个甜美的梦
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值