java学习2--基础笔记练习

抽象类

把客观世界中的相类似的事物经过分析抽象就形成了类,类实例化就变成了对象。但是,并不是每一个类都能准确的刻画对象的行为。例如圆、长方形、三角形都是图形,都有求面积和周长的方法,但是图形这个类型不能准确的描述计算面积的方法,这个时候就可以把图形定义成抽象类。

当一个类没有足够明确的信息来描述刻画对象时,这个类就要定义成抽象类。

如果一个方法不能明确如何实现时,这个方法就要定义成抽象方法。

关于抽象方法说明如下:
(1)抽象方法只有声明,没有实现;
(2)抽象类可以包含抽象方法,也可以不包含抽象方法。但是包含抽象方法的类必须定义成抽象类;
(3)抽象类不能被实例化,抽象类可以被继承,所以不允许被定义成final类;
(4)继承抽象类的类必须实现抽象类的抽象方法,否则,也必须定义成抽象类;
(5)一个类实现某个接口,但没有实现该接口的所有方法,则必须定义成抽象类

向上转型是指把一个子类的对象转成一个父类的对象。向上转型也是实现多态的手段。
Shape shape1=new Circle(3);//向上转型
Circle c1=(Circle)shape1;//向下转型—向下转型是不安全的

接口

Java语言的接口是一些抽象方法的声明,是一些抽象方法的集合,这些方法都没有实现,需要在实现这些接口的类中来具体实现这些方法。不同的类可以有不同的实现,从而这些实现可以具有不同的行为(功能)。

接口的定义跟外部类相似,只能定义成public权限或者默认权限。接口里的变量和方法都是公有的,即只能是public权限,但public可以省略。接口里的变量必须是static、final的,因而也可以称为静态常量。

抽象类与接口紧密相关。然而接口又比抽象类更抽象,这主要体现在他们的差别上:
(1)类能实现多个接口,只能继承一个类,抽象类的子类仍可实现接口。接口可以支持多继承;
(2)抽象类中可以有普通方法,接口里的方法都是抽象方法,且都是public方法;
(3)抽象类中的成员变量可以被不同的修饰符来修饰,可以有实例变量,也可以有类变量,接口中的成员变量是public、static、final的变量;
(4)抽象类中有构造方法,接口中不能有构造方法。

** 如果把现实问题抽象出来后更符合类的特征,具有实例变量、非抽象的方法,那么只能是用抽象类;
如果实际问题只能抽象出需要规范的功能方法,而且这些方法不知道如何实现,需要在子类再实现,不能抽象出实例变量,那么就应该使用接口。当然这时使用抽象类也可以,但是会丧失灵活性,因为其他类继承该抽象类后就不能再继承别的类了**

多态

   多态是指实现接口的多个类或一个父类的多个子类虽然有相同的方法,但是具有不同的表现方式。

Java中多态有两种实现形式。
一种是通过方法的重载,一个类中定义了多个名字相同、参数不同的方法。当实际调用时,java编译器会根据参数的不同来自动决定调用哪个方法。方法重载是在编译时就能决定调用哪个方法,因而也称为静态多态。
一种是通过方法覆盖,即子类通过覆盖父类的方法或类实现接口的方法。

内部类

如果把类定义在另一个类的里面,则这个里面的类就称为内部类。
内部类的优点是它属于外部类的一个成员,与成员变量和成员方法一样,可以很方便的访问外部类定义的成员变量和成员方法,而且不用在外面额外增加一个类的定义。
内部类有4种形式:
实例成员内部类、静态内部类、局部内部类、匿名内部类。

实例成员内部类是定义在类体内部、方法外面的一个类,它与实例变量的地位一样,属于外部类的对象所有,存在于对象的内存空间,只有创建了外部类的对象后,该对象内存空间才有内部类的定义,才能使用该内部类
把一个内部类定义成static,则该内部类就称为静态内部类。静态内部类存在于外部类的内存空间,所以静态内部类不能访问外部类的实例变量和实例方法,只能访问外部类的static的成员变量和成员方法。同时,在测试类中使用静态内部类的语法也不一样,不需要创建外部类的对象。
方法体内的类称为局部内部类,它的作用域只是所在的方法内。
匿名内部类就是没有名字的内部类,一般用在图形界面中,用于做事件监听器。创建匿名内部类必须事先有一个接口或者父类,把内部匿名类定义为接口的一个实现类或者是某个父类的子类。

面向接口编程

面向接口编程就是先把客户的业务逻辑功能提取出来,作为接口,业务具体实现通过该接口的实现类来完成。将具体逻辑与实现分开,减少了各个类之间的相互依赖。当各个类变化时,不需要对已经编写的系统进行改动,添加新的实现类就可以了,不用担心新改动的类对系统的其他模块造成影响。其遵循的思想是:对扩展开放,对修改关闭。
当客户需求变化时,只需编写该业务逻辑的新的实现类,就可以完成需求,不需要改写现有代码,减少对系统的影响。

//编写接口(Shape),编写类圆(Circle)实现接口 Shape,编写类长方形(Rectangle)实现接口 Shape,
//类实现接口
public interface Shape{
  public double getArea(double a);
  public double getArea(double a,double b);
  public void draw();
}

class Circle implements Shape{
  private double r;
  public void setR(){
    this.r=r;
  }
  public double getR(){
    return r;
  }
  public double getArea(double a){
    return Math.PI*2*2;
  }
  public double getArea(double a,double b){
    return a*b;
  }//类实现接口中的所有方法,调用时会根据参数自行调用
  public void draw(){
    System.out.println("i am a cricle");
  }
}

class Rectangle implements Shape{
  private double x,y;
  public Rectangle(double a,double b){
    this.a=a;
    this.b=b;
  }
  public double getArea(double a){
    return Math.PI*2*2;
  }
  public double getArea(double a,double b){
    return a*b;
  }//类实现接口中的所有方法,调用时会根据参数自行调用,继承抽象类时也是一样
  public void draw(){
    System.out.println("i am a rectangle");
  }
}

public class TestShapeClass{
  public static void mian(String[] args){
    CircleClass c=new CircleClass(3);
    System.out.println(c.getArea(3));
    c.draw();
    RectangleClass r=new RectangleClass(1,2);
    System.out.println(r.getArea(1,2));
    r.draw();
  }
}


异常

在这里插入图片描述
在这里插入图片描述
Java中所有的异常类都是java.lang.Throwable的子类。Throwable类有两个直接子类:Error类及Exception类,
Error类描述的是内部系统错误,包括动态链接失败、虚拟机错误等,Java程序不做处理。这类异常主要是和硬件有关系,而不是由程序本身抛出。通常不由Java程序处理,用户也无法捕获。
*Exception类是Java程序中需要大量处理的。Exception类定义的是较轻的错误,你可以编写代码来处理这类错误。Exception类描述的是程序和外部环境引起的错误,这些错误能通过程序捕获和处理。

   运行时异常RuntimeException是一些可以通过适当的处理而避免的异常,在程序运行中可自动由JVM引发并处理,编程时不需捕获或声明
   非运行时异常,通常由环境因素引起的,与程序员无关,如输入、输出异常IOException,文件不存在、无效的URL等等。Java编译器要求Java程序必须捕获或声明所有的非运行时异常

就是将语句放入try中,加入这里面有问题就会执行catch,整个过程不影响其他代码段

public static void main(String[] args) {
  int a=3,b=0,c=0;
  try {
	c=divide(a,b);//divide方法会抛出异常
  }catch (Exception e) {//捕获异常
	System.out.println("调用divide出现错误: "+e.getMessage());
  }
  System.out.println("c="+c);//c仍是初始值0
}}

某个方法需要抛出异常,可以通过使用throws语句和throw语句来实现。throw关键字是抛出异常对象,throws关键字是声明该方法可能会抛出的异常类型。

1.throws
方法使用throws声明中使用throws声明抛出的异常类的格式如下:
[访问修饰符] 返回值类型 方法名([形参列表]) throws 异常类列表
{ …… }
异常类之间用逗号分隔。这些异常类的来源有两种情况:一种是方法中调用了可能抛出的异常的方法而产生的异常。
另一种是方法体中生成并使用throw手动抛出的异常。
2.throw
程序员可以根据实际情况在程序中抛出一个异常。例如,用户自定义的异常不能由系统自动抛出,它必须在程序中明确抛出异常。
throw语句用来直接抛出一个异常,后接一个可抛出的异常类对象。其格式如下:
throw new 异常类名();或
异常类名 对象名 =new 异常类名();
throw对象名;

public class TestThrow {
  static int divide(int a,int b) throws Exception{
   //divide方法不处理异常,用throw关键字抛出异常对象给调用者
    if(b==0) throw new Exception("除数为零");
	  int c=0;c=a/b;
	  return c;
  }
public static void main(String[] args) {
  int a=3,b=0,c=0;
  try {
	c=divide(a,b);//divide方法会抛出异常
  }catch (Exception e) {//捕获异常
	System.out.println("调用divide出现错误: "+e.getMessage());
  }
  System.out.println("c="+c);//c仍是初始值0
}}  

关于抛出异常,在编写类继承代码时要注意:
一个方法被覆盖时,覆盖它的方法必须抛出跟被覆盖的方法相同的异常或者异常的子类,或者不抛出异常。
如果父类抛出多个异常,那么重写(覆盖)的方法必须抛出那些异常的一个子集,也就是说不能抛出新的异常。

定义一个分数异常类 ScoreException 继承 Exception,
表示分数异常类(当分数小于 0 或大于 200 时会抛出这个异常),在无参数构造方法中让异常的默认信息是“分数异常,分数应该在 0 到 200 之间”
(通过调用父类 Exception的有参数构造方法给父类 Exception 的 message 属性赋值为这个字符串)。
在有一个参数的构造方法中(参数为 String message),直接调用父类的有参数构造方法把参数message传给父类Exception的 message 属性。

public class ScoreException extends Exception{
    public ScoreException(){
          super("分数异常,分数应该在0到200之间");
    }
    public ScoreException(String message){
          super(message);
    }
}

定义一个学生类 Student,具有 name、age、score 属性,具有 getName、setName、getAge、setAge、getScore、setScore 和 print 方法,print 方法输出属性信息,
具有 3 个参数的构造方法 Student(String name ,int age,double score),
在构造方法中判断 score 是 否 在 0-200 之 间 ,如不在这个范围则抛出ScoreException;
在setScore 方法中也要判断形参score是否在 0-200 之间,如不在这个范围则抛出ScoreException

public class Student{
  private String name,int age,double score;
  public void setName(String name){
    this.name=name;
  }
  public String getName(){
    return name;
  }
  public void setAge(int age){
    this.age=age;
  }
  public String getAge(){
    return age;
  }
  public void setScore(double score){
    this.score=score;
  }
  public String getScore(){
    return score;
  }
  public void print(Student s){
    System.out.println(s+"的姓名是"+this.name);
    System.out.println(s+"的年龄是"+this.age);
    System.out.println(s+"的成绩是"+this.score);
  }
  public Studen(String name,int age,double score){
    this.name=name;
    this.age=age;
    if (score>200||score<0){
       throw new ScoreException();
    }
    this.score=score;
  }
  public Student(){}
  
}

main 方法中完成如下工作:
(1) 创建对象 zhangsan=new Student(“张三”,20,220);要求能捕获异
常,并在 catch 中输出异常信息。
(2) 创建对象 lisi=new Student(“李四”,30,120);
(3) 调用 lisi 的 setScore()方法给 score 赋值 230,要求能捕获异常。

public class TestStudent{
  public static void main(String[] args){
    try{
      Student  zhangsan =new Student("张三",20,220);
      zhangsan.print();
    }catch(ScoreException e){
       System.out.println(e.getMessage());
       e.printStackTrace();
    }
    try{
      Student lisi =new Student("李四",30,120);
      lisi.print();
      lisi.setScore(200);
    }catch(ScoreException e){
       System.out.println(e.getMessage());
       e.printStackTrace();
    }
  }
}

常用类库

类库的结构
java.lang: 语言基础类库(System、Math、Thread、基本数据类型类)
java.util: Java的工具类库(向量、栈、日期)
java.io: Java的标准输入输出类库
java.applet: 用于实现Java Applet小程序的类库
java.awt: 早期的用于构建图形用户界面的类库
java.awt.event: 界面用户交互控制和事件响应类
java.swing: 用于构建图形用户界面的类库
java.net:Java 的用于实现网络功能的类库

本章着重要学习的常见类
字符串类(String 、 StringBuffer、 StringTokenizer)
日期类(Date、Calendar)
包装类
集合类(Set、List、HashSet、ArrayList、Map、HashMap、Iterater、ListIterator、Comparable、Comparator)

字符串String

定长字符串:String类,不能更改
可变字符串:StringBuffer类(使用灵活,线程安全)—可追加、插入、修改,但内存管理复杂
1.字符串常量

String str="我是字符串常量";

2.构造方法

//1.创建空串
public String()
String s=new String();
//2.创建字符串对象
public String(String str);
String s=new String("we are students");
//3.以*字符数组*value中的字符建一个新串。
public String(Char[] value)
char a[] ={'w','h','y'};
String s=new String(a);
//4.将*字符数组*a中第startIndex个字符开始的count个字符组合创建一个新字符串。startIndex从0开始。   
public String(char a[],int startIndex,int count):
char a[]={'a','t','b','u','s','n','v'}
String s=new String(a,2,3);
//5.将**字节数组**array创建一个新字符串。
public String(byte[] array)
byte[] a={54,55,56};
String s=new String(a);//678
//6.将**字节数组**array 的第offset个数组元素开始的length个字节创建一个新字符串。
public String(byte[] array,int offset,int length ):
byte[] a={54,55,56};
String s=new String(a,1,2); //s="78"
//7.以StringBuffer创建新串
public String(StringBuffer buffer)

这两种创建字符串对象方式的区别是:双引号自动创建的字符串对象存在于常量池,
通过构造方法创建的字符串对象存在于堆内存中。

String s1 = new String("abc") ;  
String s2 = new String("abc") ;
String s3 = "abc" ; String s4 = "abc" ;

在这里插入图片描述
字符串在拼接过程中会产生大量垃圾对象,这消耗了大量的不必要的系统资源,影响效率,所以一般不用这种字符串方式进行拼接,常用StringBuffer类。

String s1 = "abc";  
s1=s1 + "cd"  ;//此时"abc"就是垃圾对象。

String类的实用成员方法:
1.获取字符串长度:public int length()
2.字符串的比较
(1)public boolean equals(String s):判断字符串的内容是否相同(区分大小写)。
(2)public boolean equalsIgnoreCase(String s)
3、判断该字符串是否以prefix为前缀。
public boolean startsWith(String prefix)// endsWith
4、按字典顺序比较两个字符串
public int compareTo(String s)
5、返回字符串的副本,忽略前导空白和尾部空白。
public String trim()
6.字符串的检索
(1)public int indexOf(String str)
从第一个字符开始寻找str子串首次出现的位置
(2)public int indexOf(String str,int startpoint)
从startpoint位置处开始寻找str子串首次出现的位置
(3) public int lastIndexOf(String str)
从第一个字符开始寻找str子串最后出现的位置
(4)public int lastIndexOf(String str,int startpoint)
从startpoint位置开始反向寻找str子串最后出现的位置,相当于从0到startpoint位置寻找最后一次出现str的位置
7.字符的检索
(1)public int indexOf(int charp)
返回指定字符charp在此字符串中第一次出现处的索引。
(2)public int indexOf(int charp,int startpoint)
从指定位置startpoint开始检索字符charp,返回首次出现的位置
(3) public int lastIndexOf(int charp)
检索指定字符charp最后出现的位置。
(4)public int lastIndexOf(int charp,int startpoint)
从索引0到startpoint之间检索字符charp最后出现的位置。
8.截取字符串
(1)public String subString(int startpoint)
返回从第startpoint个位置开始到结束截取的字符串。
10.替换
(1)public String replace(char oldChar,char newChar)
(2)public String replaceAll(String old,String new)
11.字符串连接
public String concat(String s)
String str=“我是”,s=“中国人”;
String kk=str.concat(s);
12.字符串向字符数组转换
(1)public void getChars(int start,int end,char c[],int offset):将从start到end-1位置的字符复制到c中,从c的offset开始存放。
(2)public char[] toCharArray():将字符串中的全部字符复制到字符数组中,返回数组的引用。
char a[]=str.toCharArray();
(3)public byte[] getBytes():字符串向字节数组转换

StringBuffer类

是线程安全的可变的字符串,有改变字符串的若干方法。

StringTokenizer类

将一个字符串分解成若干子串
StringTokenizer(String str,String delim)
用字符串str构造一个分解器,分隔符是delim
Stringtokenizer stoken2=new StringTokenizer(" I,am,a,student ", ", ");

日期类

1.Date类
public long getTime()
2.Calendar类
获取Calendar类对象的方法:
public static Calendar getInstance();
例如:
Calendar rightNow = Calendar.getInstance();

包装类

在java中数据类型总共可分为两类:
基本数据类型(值类型)
类类型(引用数据类型)
基本类型的数据不是对象,不能作为对象调用其toString()、hashCode()、getClass()、equals()等等方法。在这里插入图片描述
1.字符串转换为数值
Byte、Short、Integer、Long、Float、Double都有一个parse***方法,转换为该类对应的基本类型,例如:

   public static int parseInt(String s)
   例如:String s="12345";  
   int k=Integer.parseInt(s);

2.数值转换为字符串
String类中有一系列static方法----valueOf(type var)。

public static String  valueOf(int n);
例如:float x=123.987f;
String temp=String.valueOf(x);

** 所谓装箱,就是把基本类型用它们相对应的引用类型包起来,使它们可以具有对象的特质,如我们可以把int型包装成Integer类的对象,或者把double包装成Double类的对象,等等。
所谓拆箱,就是跟装箱的方向相反,将Integer及Double这样的引用类型的对象重新转化为基本数据类型的数据。**

集合

集合:类似于数组,是存放对象的聚集。集合对象中存放的是一组对象。换句话说,集合中的存放的元素是对象。
集合API中的接口和类主要位于java.util包中。
Collection接口重要的方法有:

public boolean add(Object obj);
//将对象obj加入到当前集合对象中
public boolean addAll(Collection c);
//将集合c中的元素加入到当前集合对象中
public void clear();
//清除当前集合中的所有元素
public boolean contains(Object obj);
//判断当前集合中是否包含obj对象
public Iterator iterator();
//得到当前集合的迭代器
public boolean remove(Object obj);
//删除当前集合中的obj对象
public int size();
//得到当前集合中元素的总数
public boolean isEmpty();
//判断当前集合是否为空
public Object[] toArray();
//将当前集合对象转化成对象数组
注意:
集合类中的许多方法的参数都是Object类型。

Set接口
Set中的元素必须唯一。不允许有重复的元素。

实现Set接口的类主要有:
AbstractSet:所有Set的实现类都直接或者间接继承AbstractSet父类。
HashSet:内部使用一个哈希表来实现Set集合,并允许存放null元素。不保证元素的排列顺序,顺序有可能发生变化。在编程中常常使用该类。
LinkedHashSet:在内部使用链表的 Set,既有 HashSet 的查询速度,又能保存元素被加进去的顺序去(插入顺序)。
TreeSet:使用二叉树实现Set集合,用来对元素进行排序,保证元素的唯一。

//HashSet的构造函数如下:
HashSet() :构造一个空 set。
HashSet(Collection  c) :构造一个包含指定 collection 中的元素的新 set。

List接口
List接口定义了一个有序的对象集合,允许重复元素存在。
List类似于动态数组或变长数组。List中存放的元素的数量(List的容量)可以随着插入操作自动进行调整。
Iterator接口
Iterator接口主要用来遍历集合中的元素。
在实际应用中只要用到Collection接口的类都会用到iterator这个接口,所有实现Collection接口的类都有一个iterator()方法,用来返回一个实现Iterator接口的对象。
作用是对Collection的元素进行遍历等操作。
只能单向移动。
ListIterator接口
ListIterator接口是Iterator接口的子接口,它针对List集合有序的特点,提供了双向检索和元素存取的功能。
集合遍历的方法
循环遍历(有序集合,每个元素的位置固定,可以用for循环)

void enumerate(Collection list){
    for(int i=0;i<list.size();i++)
        Object o=list.get(i);
}  

迭代器遍历(所有实现了Iterable接口的集合类)

Iterator it=list.iterator();
while(it.hasNext()){//判断该迭代器中是否还有元素需要迭代,返回true或false
      System.out.println(it.next());//返回迭代的下一个元素,指针下移
}

for-each形式
所有利用迭代器迭代的元素都可以用for-each形式。

for(Object ob:list){  //形参数据类型 形参名:从哪个集合对象中取元素
	System.out.println(ob);
}

Map集合
Collection接口表示的是单一对象的集合;即每个位置保存的是单一的对象
Map中保存关键字-值这种形式的对象。

成员方法:

public Set keySet();
//返回此映射中包含的键的 set 视图 
public Colletion values();
//返回此映射中包含的值的 collection 视图 
public Set entrySet();
//返回此映射中包含的映射关系的 set 视图 ,即返回的Set中包含了Map中所有的关键字-值对
Map中 还定义了对Map数据集合的操作方法:

public void clear();//清空整个集合
public Object get(Object obj);//根据关键字obj得到对应的值
public Object put(Object key, Object value);//将键-值对加入到当前的Map中
public void remove(Object key );//从当前Map中删除key代表的键-值对

实现了Map接口的类中常用的是HashMap和HashTable。
HashTable是线程访问安全的
HashTable的子类Properties: Properties的关键字和值只能是String; Properties经常用来读取配置信息。
HashMap:实现Map接口,存储键/值映射关系,不能保证其元素的存储顺序,即不保证放入与取出的顺序一致。

泛型:编译期用来检查输入集合中数据的类型,从而避免操作时强制类型转换。
例如:

List<String> ls=new ArrayList<String>();
ls.add("a1");
ls.add(2);//报错
//取元素时不用再强制类型转换,因为强制类型转换会出错
for(String str:ls){
      System.out.println(str);
}
Iterator<String> it=ls.iterator();
while(it.hasNext()){
	System.out.println(it.next());
}

Hashmap中也可使用泛型。

Map<String,Student> mp=new HashMap<String,Student>();
Set<String> set=mp.keySet();
Iterator<String> it=set.iterator();
while(it.hasNext()){
	System.out.println(mp.get(it.next()).getName());
}
  • 41
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值