女娲补天——Java

Java入门

环境安装与搭建

  • JDK:Java Development Kit
  • JRE:Java Runtime Environment
  • JDK包含了JRE

女娲补天——Java_第1张图片
javac:编译器,将Java源代码编译成字节码。
java:字节码解释器,直接从类文件执行Java应用程序字节代码。

程序设计两大方法

面向过程

  • 算法为核心
  • 将大问题化为若干个小问题(函数)
  • 数据与操作分离,对数据与操作的修改变得很困难
  • 数据的安全性得不到保证
  • 需求不明确、变动较大、规模很大
  • 自顶向下的设计模式
    • 主函数依赖于子函数,子函数又依赖于更小的子函数。
  • 直接面向问题

面向对象

  • 确定该问题由哪些事物组成
  • 通过模拟事物的出现

什么是类

  • 把一类事物的静态属性和动态可以执行的操作组合在一起的所得到的感念
  • 类是抽象的,用来模拟一类事物,是一个概念
  • 一旦被定义,类的概念就永远存在了

一个一个对象问题会很复杂,故着眼于对象的类型建立模型,并把类型简称成类(class)

什么是对象

  • 类的一个个体
  • 具体的,实实在在存在的事物
  • 一切皆对象
    • 具体物理实体的抽象
    • 人为的概念
    • 其他有明确边界和意义的东西

类的定义

  • 属性(field)(数据成员、字段、域):用于描述类或对象的状态或特征
  • 方法(member method):描述类或对象的行为
class A{
	int i;//数据成员
	int j;
}

class test{
	public static void main(String[] args)
	{
		A aa = new A();//(A *)malloc(sizeof(A));动态分配
		//new A(); 在堆中动态分配了一块区域,被当作了A 对象
		//a本身的内存是在栈中分配的
		//堆中内存的地址赋给了aa
		//aa指向堆中的内存,aa代表了堆中的内存
		//内存=堆内存heap new出来的东西
		//+栈内存stack 局部变量 在栈中的东西系统自动释放
		//data segment 
		//code segment
		//aa.i, aa.j  代表aa这个静态指针变量指向的动态内存中的A对象
		//aa只占四个字节,存放事物的地址,第一个字节的地址
		aa.i = 10;
		aa.j = 20;
		System.out.println("%d %d",aa.i,aa.j);
		
	}
}

(一)封装

类的实例(instance)——对象

对象创建过程:
Employee li4 = new Employee("Lis", 29,’f’, 4477.77);

以上过程中实现了:
① 声明一个引用(reference)
向编译器注册一个类对象的名字

② 操作符new为各成员变量分配存储空间,并自动初始化为变量类型的默认值;

③ 调用构造方法显式进行有关成员变量的初始化;

④ 返回对象的引用。

构造器(constructor)

构造器也是一种特殊的方法(method),用于类创建对象时的属性初始化

  • 有参构造器用具体数据对类的属性进行初始化,
  • 无参构造器用默认值(0?)对类的属性初始化

定义:

  • 名字和类名一样
  • 无返回值

注意事项:

  • 一个类对象只能调用一个构造方法
  • 一个类至少有一个构造方法
  • 如果自己定义了构造方法,则编译器不再提供默认的构造方法
  • 1:1的匹配

构造器重载

  • 形参的个数
  • 形参的类型

返回值不能作为是否构成函数重载的依据

//参数不同的构造器
Employee();
Employee(String name);
Employee(String name, int age, char sex);
Employee(double baseSalary);
Employee(String name, int age, char sex, double baseSalary);

当一个对象被创建时,会对其中各种类型的成员变量自动进行初始化赋值

局部变量编译器是不会自动进行初始化的,java要求所有的局部变量在使用之前都必须的初始化

在用new新创建对象时,首先会对该对象的实例变量赋予默认初值,之后才调用构造器

关键词this

用this()代表本类构造器

表示前面出现过的变量重载

女娲补天——Java_第2张图片

对象成员访问

this是特殊的引用,代表当前对象,用来区分参数名和属性名

一个对象只含有属性的空间,n个对象公用 一份方法的拷贝

class A{
	public int i;
	public A(int j)
	{
		i = j;
	}
	public void show()
	{
		System.out.printf("i=%d", this.i);
		//this代表的是当前正在调用show方法的对象
	}
}
public class test
{
	public static void main(String[] args) {
		A aa1 = new A(10);
		A aa2 = new A(20);
		aa1.show();
		aa2.show();
	}
	
}
  • 是一个系统隐含的指针被自动附加在非静态的成员函数参数列表中
  • 当前时刻,哪个对象调用该函数,那么this就指向当前调用该函数的对象,系统会自动在该函数的参数列表里添加一个隐藏的this指针,并且把调用该函数的对象的地址赋给this指针,这样一样,在函数的内部通过this就可以访问当前正在调用该函数的对象的成员
  • 静态函数内部,没有this指针
    女娲补天——Java_第3张图片
    非静态方法都默认含有一个this指针
    this代表正在调用本方法的对象

静态(static)

静态成员属于类本身,而不是属于某个对象,即可以被类的所有对象所共用。static放在变量前表明该属性是各个对象公用的。

静态成员分为

  • 静态数据成员
  • 静态方法成员

static属性i是属于类本身,或者讲没有对象,我们仍果然可以通过类名的方式访问static属性

  • 非静态的可以访问静态的
  • 静态的不可以访问非静态的

通过类名只能访问一个类中非私有静态成员
私有静态成员你也不可以通过对象名访问

static方法也是属于类的

一个类的属性可以是是个类对象(类之间的包含关系)

静态变量存储在静态存储区(即方法区)
任何方法都可直接引用。不可用this引用

静态方法只能访问类的静态成员

类的访问控制符

基本分类

  • public:可以通过外部访问方式访问类内部的public成员
  • protect
  • 默认【不加任何修饰符】
  • private
    • 不可以通过外部访问方式访问类内部的private成员

内部访问控制符是透明的,所有的成员可以互相访问;访问控制符是针对外部访问而言的

外部访问的方式:

  • 通过类名访问类内部的成员
  • 通过类对象访问类内部成员

类文件与包

类文件

Java以类作为编译单元

  • 每个类编译后都生成一个**.class文件**。这是“与平台无关的”字节码文件,并且只是在程序执行它的时候才被调入。
  • 其好处是便于实现Java承诺的一次编码,到处运行

包的声明:package 包名

包名.类名同一个包中,类名必须唯一;不同包中的类名可以存在相同的情况。

  • 包(package)是Java提供的类文件组织与管理机制。
  • 包可以有子包,子包还可以再设子包,形成包的层次结构

说明:

  • 一个源文件只能有一条package语句,并且要位于该文件的最前面(注释除外)。
  • 如果要把多个文件中的类装入同一个包,则每个源文件的最前面都要写同样的package语句(包名也相同)
  • 在默认的情况下,如果一个源程序文件没有声明包,系统就会为源文件创建一个未命名包,将该源文件中定义的类都组织在这个未定义包中。
  • 由于未命名包没有名字,所以不能为其他包引用。为了被其他包引用,应该为源文件声明一个包名。
  • 只有在整个包的最上层目录才可以运行

(二)继承(extend)

class SubClass extends SuperClass
{
}

继承的好处

  • 继承关系反映了现实生活中一般到特殊的关系。利用继承可以较好地模拟出现实世界事物之间的继承联系,使得代码得到极大的重用,形成一种类的层次体系结构
  • 为多态创造条件

注意问题

1.子类内部可以访问父类非私有的成员
2.通过子类对象名只能放为从父类继承过来的非私有成员

私有属性、私有方法不能被继承。私有不能被继承,私有物理上已经被继承过来,只不过逻辑上程序员不能去访问它。因此继承必须慎重,否则会导致内存浪费。

Java只支持单继承,不允许多重继承

  • 单继承是指only 一个父类
  • 多继承可以有很多个父类

继承可以有多层继承,即某一个类可以继承某一个类的子类

子类可以继承父类所有的成员变量和成员方法,但子类永远无法继承父类的构造方法
女娲补天——Java_第4张图片

子类访问父类成员的三种方式

  • 在子类内部访问父类成员
  • 通过子类对象名访问父类成员
  • 通过子类的类名访问父类成员
    经验证,子类通过上述三种方式的任何一种都无法访问父类的私有成员,因此我们可以得出结论:
    私有成员无法被子类继承

super()

  • 每个子类构造方法的第一条语句,都是隐含的调用super(),如果父类没有这个构造函数,那么在编译的时候就会报错
  • 如果显示的写出super()语句,必须保证该语句是第一条语句,否则会出现报错
  • super()如果不写,则编译器会自动添加,所以如果此时父类没有无参的构造器
  • 既可以显示写super():前提是父类必须有无参的构造函数
  • 也可以显示写super(实参):前提是父类必须有带参的构造函数
  • 调用父类的构造函数的语句必须借助于super,不能直接写父类的类名
  • 一个构造函数中不能写多个super(参数列表)语句

方法重写

如果子类对父类的方法不够满意时,就应该重写方法。

方法重写的条件:

  • 重写方法必须和被重写方法具有相同的方法名称参数列表返回值类型
  • 重写方法的访问权限不能低于被重写方法

(三)多态

利用多态可以实现,同一段代码做不同事情
一个父类引用既可以指向父类对象,也可也指向子类对象
它可以根据当前时刻指向的不同,自动调用不同对象的方法,这就是多态

注意事项

  • 子类对象可以直接赋给父类引用,但父类对象在任何情况下都不可以直接赋给子类引用,因为子类是父类的一种,但父类不是子类的一种。

  • 通过父类引用只能访问子类对象从父类继承过来的成员

  • 通过父类引用不能访问子类对象所特有的成员

class A
{
	public void f()
	{
		System.out.printf("AAAA\n");
	}
}
class B extends A
{
	public void f()
	{
		System.out.printf("BBBB\n");
	}
	public void g()
	{
		
	}
}
public class TestPoly
{	
	public static void main(String[] args)
	{
		A aa = new A(); 
		//aa是父类引用
		B bb = new B(); 
		//bb是子类引用
		aa.f();
		bb.f(); 
		aa = bb;
		//把bb当做aa来看待,因为子类可以当做父类来看待,所以本语句ok
		
		bb = aa; 
		//把aa当做bb来看待,因为父类不能被当做子类看待,所以本语句error
	//狗狗可以当做动物看待,但动物不可以当做狗来看待
		
		aa.f();//BBBB 同样的代码语句做不一样的事情
		//通过父类引用只能访问子类对象从父类继承过来的成员
		//aa.g(); //error通过父类引用不能访问子类对象所特有的成员
	
		//向下造型 强制类型转换
		B bb2 = (B)aa; 
		//only when 父类引用本身指向的就是一个子类对象时,才可以把父类引用强制转化为子类引用
	}
}	

向上造型(upcasting)

  • 把子类对象当作父类对象来使用,安全可行
  • 因为子类对象总可以当作父类的实例

向下造型(downcasting)

  • 不自然不安全
  • 向下造型必须进行强制类型转换
    • 圆括号括起(类名)就是一种强制造型操作向下造型强制类型转换

抽象类(abstract)

不能造对象

  • 利用抽象类是为了更好地对加以分类,就如同人类不但给各种具体植物取了名字还发明了”植物“这个抽象的词对所有具体植物进行归类
  • 通常最上面的若干层类都是抽象的,Java用来模拟现实世界,所以也存在抽象类
abstract class A//含有抽象方法的类必然是抽象类
{
	abstract void f();//没有方法体的方法叫做抽象方法
	//抽象方法要求末尾必须得加分号,前面必须得加abstract
	//只给出方法头,而不给出具体代码方法
}
abstract class B//抽象类不一定包含抽象方法
{
	public void g(){
	}
}

一个抽象类通常都含有抽象方法
只要含有抽象方法的类一定是抽象类

abstract class A
{
	abstract public void f();
}
class B extends A
{
	public  void f()
	{
	}
}
public class 
{	
	public static void main(String[] args)
	{
	}
}

不可以定义抽象类对象,但是抽象类可以实现多态。

abstract class A
{
	abstract public void f();
}
abstract class B extends A
{
	System.out.println("BBBB");
}
public class TestAbstract
{	
	public static void main(String[] args)
	{
		A aa = new A(); 
		//error 抽象类无法创造对象
		B bb = new B(); //OK
		b.f(); //OK
		A aa;//ok 可以定义一个抽象类的引用,但是不可以定义一个抽象类的对象
		aa = bb;
		aa.f();
	}
}

final关键词

修饰范围

整个

  • 表示该类不能被继承
  • 如果认为一个类已经很完美且不需要定义任何子类来继承它时,可以使用final

类中的若干个属性

  • 该属性能且只能被赋一次值,赋值方法有两种:
    • 1.在定义成员变量的同时初始化
    • 2.在类中所有的构造函数中初始化
  • 注意:任何一个类的普通方法都不可以修改final修饰过的成员变量的值

类中的若干个方法

  • 表示该方法可以被子类继承,但不可以被子类重写
final class A
{
}
class B extends A //error final修饰类表示该类不能被继承
{
}
class TestFinal_1{
	public static void main(String[] args)
	{
	}
}

class A
{
	final public int b; 
	//error 常变量必须被赋值(默认值也不算是真正的赋值),之后也不能被改变
	//相当于C语言的static 增加程序安全性
	final public int i //= 10; 
	
	public A//构造器一定会被调用,所以可以实现赋值的最终效果
	{
		i = 22//如果上面i=22报错,只能赋值一次
	}
	public void f()//方法不一定被调用
	{
		i = 22; //error 无法为最终变量i指定值
	}
}
class TestFinal_2{
	public static void main(String[] args)
	{
	}
}
final class A
{
	final public void f()
	{
		System.out.println("AAAA");
	}
}
class B extends A //final方法只能被继承不能被重写
{	
	public void f()
	{
		System.out.println("BBBB");//final方法重写error
	}
}
class TestFinal_3{
	public static void main(String[] args)
	{
	}
}

(四)接口(interface)

  • 抽象方法和常量值的几何
  • 本质上说,接口是一种特殊的抽象类
[public] interface interfaceName [extends SuperInterfaceList]
{
//一个接口可以继承多个接口列表
//但是一个类只能继承一个父类,即只能有一个父亲
	//常量定义和方法定义
}

接口中定义的属性必须是public static final类型的
接口中定义的方法必须是public abstract类型的

  • 接口中定义的属性的值在实现类中不能被更改
  • 一个类只能实现某个接口,不能继承某个接口。但接口可以继承接口,接口不但可以继承接口,而且可以继承多个接口,即接口允许多继承
  • 如果一个类只实现了一个接口的部分方法,则该类必须声明为抽象类
  • 一个类可以在继承一个父类的同时实现一个或多个接口,但extends关键字必须在implements关键字之前
  • 不可以new接口对象,但可以定义一个接口引用类型的变量将其指向实现接口的对象,达到多态的目的。
  • 在接口中定义构造函数是错误的
interface It 
//接口由关键词interface引出
//其前可以使用public或abstract,也可以什么都不写(默认public),但一定不可以使用private修饰
{
	public static final int i = 20;
	public abstract void f;
	public void(); //接口方法不能带有主体
}
interface It2 
{
	int i = 20;//修饰符可以部分或全部省略
	void f(); //省略后代表的含义一致,因为这是强制的
}
// class A extends It//error 类不能继承接口,类可以继承类
abstract class A implements It //实现接口里面所有的成员变量和成员方法
{
	public void f()
	{
		System.out.println("i = %d",i);
	}
}
abstract class B //抽象类不强制拥有抽象方法
{	public void f()
	{
	}
}
class TestInterface_1{
	public static void main(String[] args)
	{
	}
}
interface It
{
	void f();//默认public abstract
}
class A implements It
{
	//void f() //不能重写 形参一样 函数名一样 访问权限值需更高
	//重写接口方法时public不能省
	public void f()
	{
		System.out.println("AAAA");
	}
	public void g()
	{
	}
}
class TestInterface_2{
	public static void main(String[] args)
	{	
		int i;
		It it;
		it = new A();//接口是抽象的,但可以定义一个实现该接口的对象,把这个对象的地址发送给接口来引用,通过接口的引用可以调用这个对象指向的真正的成员
		//多态+接口
		it.f();
		it.g();//通过接口的引用只能调用从父类继承过来的成员,不能调用子类所特有的
		//It it2 = new It();//error It是抽象的:无法对其进行实例化。即抽象类不能创造对象
	}
}
class A{
	int i;
	public void show()
	{	System.out.printf("show --> %d\n",i);
	//此刻的i是属性,此时的i等价于this.i
	}
	public void f()
	{
		int i; //这里的i和属性i没有冲突
		System.out.printf("f --> %d\n",i);//error 因为i是局部变量,Java要求局部变量在使用前必须被赋初始值
	}
}

实现的接口类

  • 如果一个类只实现了一个接口的部分方法,则该类必须声明为抽象类
  • 一个类要想实现某接口中的方法时,必须得在方法返回值前加上public
  • 不可以new接口对象,但可以定义一个接口引用该类型的变量并将其指向实现该接口的对象,达到多态的目的

接口的作用

  • 通过接口实现不相关类的相同行为
    • 如:Java规定所有可以完成自我复制功能的类都是必须得实现java.lang.Colneable接口,但该接口却是空的,该接口中没有任何内容,only空接口目的只是为了起标志作用
  • 接口提供了不同对象进行协作的平台
    • 事件处理
  • 接口可以实现多继承,从一定程度上弥补了类只能单继承的缺口
  • 接口是我们了解一个类功能的重要途径
    • 如:Java的整个容器框架就是以接口的方式建立起来的,实现不同接口的类完成的是不同的功能(list, Set, Map)

接口与抽象类区别

  • 接口中的方法不允许有方法体,但抽象类却允许
  • Java类不允许多继承,接口却允许多继承

枚举(enumerate)

  • 本质上是一个类,它的隐含父类是java.lang.Enum
  • 枚举值是被声明枚举类创建的自身实例,如red是Color的一个实例,并不是整数或其他类型
  • 对象即属性
  • 将值逐一列出,使用语句
    public enum Color{red,yellow,blue,white,black};
  • 枚举值可以用==equals()进行比较判断是否相等

泛型基础

泛指任何类型或多种类新给,用于在设计时无法确定的情形
类名<具体类型名> 引用名 = new类名<具体类型名>();

泛型方法的一般格式

[访问权限] <泛型标识>返回类型 方法名(泛型标识 参数名){}

Java数据结构结构

  • 群结构(group structure)
    • 集合(set):集合中的成员互不相同
      • 加入(add)成员、删除(delete)成员。
      • 对集合进行交(intersect)、并(union)、差(difference)运算。
      • 判断一个数据是否集合的成员,判断一个集合是否另一个集合的子集,判断两个集合是否相等。
      • 迭代:穷举查询等。
  • 表结构()
    • 线性结构(linear structure):所有元素都按照某种顺序排列在一个序列中
      • 直接(随机)存取结构
      • 顺序存取结构
    • 非线性结构
      • 一个元素可能会与多个元素有关系,形成一对多()
  • 映射结构

(五)容器(Set)

集合就是将若干用途、性质相同或相近“数据”组合而成的一个整体
容器一定是类,类不一定是容器

集合类型分类

  • Set 无序、不重复
  • List 区分元素的顺序、可重复
  • 映射(Map) key-value

为什么需要容器呢?

  • 数组长度难以扩充
  • 数组中的元素类型必须相同,限制了存储数据类型多样性的发挥

Collection接口

public interface Collection extends Iterable

Collection接口方法介绍

int size()
boolean isEmpty()
boolean contains(Object o)
boolean containsAll(Collection<?> c)
boolean add(Object o)//把o添加到当前集合中,插入成功返回true
boolean addAll(Collection<? Extends E> c)
boolean remove(Object o)
boolean removeAll(Collection<?> c)
boolean retainAll(Collection<?> c)
Iterator<E> interator()
boolean equals(Object o)
int hashCode()
void clear()
Object{} toArray() //容器不是数组,不能通过下标的方式去访问,只有数组才可以通过下标来访问
<T> T{} toArray(T[] a))

List接口及其实现

List是Collection的子接口,其定义如下:
public interface List extends Collection

  • 通用实现
    • ArrayList:数组实现
    • LinkedList:双向链表
  • 专用实现
    • CopyonWriteArrayList
E set(int index,E element)
E get(int index) //返回给定位置index处的元素
E remove(int index)
void add(int index, E element)
boolean addAll(int index,Collection<?extends E> c)
int indexOf(Object o)
int lastIndexOf(Object o)
List Iterator<E> listIterator()
List<E> subList(int fromIndex,int toIndex)

Set接口及其实现

Set是Collection的子接口,其定义如下:
public interface Set extends Collection

  • 通用实现
    • HashSet:采用散列存储非重复元素,是无序的
    • TreeSet:有序排列
    • LinkedHashSet:具有可预知的迭代顺序,并且是用链表实现的。
  • 专用实现
    • EnumSet:用于枚举类型的高性能Set实现
    • CopyOnWriteArrayList:通过复制数组支持实现

(六)聚集的标准输出

Iterator接口

Iterator接口用统一的方式对集合中的各个元素进行遍历

Iterator接口的对象又称为迭代器,利用该对象可以方便的便利容器中的元素

所有实现了collections街廓的容器类都有一个iterator()方法
boolean hasNext():判断当前游标的后面是否还有下一个元素

next():先返回当前游标的下一个元素,然后游标后移一个位置。
remove():删除最近返回的当前元素。先调用一次next()方法之后才能调用一次remove方法,不推荐使用

public static boid showCollection(Collection c)
{
	Iterator it = c.interator();
	while(it.hasNext())
		System.out.println(it.next());
}

foreach一般格式

for (类  元素名  :聚集名) {}

Map接口类及其应用

Map映射是一种把键对象值对象进行映射的集合,它的每一个元素都包含一对键对象和值对象
public interface Map

boolean containsKey(Object key)
boolean containsValue(Object value)
boolean isEmpty()
boolean equals(Object o)
Set<K> keySet()
Set<Map.Entry<K,V>>entrySet()
V get(Object key)
V put(K key,V value) //different from add(only 1 element)
//根据key计算出存储位置,然后把value存入此位置时,如果该位置已有元素则覆盖它
//该方法返回覆盖之前的元素对象的值,如果以前此位置为空,则返回null
V remove(Object key)
int size()
int hashCode()
void clear()
void putAll(Map<? Extends K,? extends V>t)
Collection<V> values()

Collections类

colleaction接口的实现类,如ArrayList、LinkedList本身并没有提供排序、倒置、查找等方法,这些方法是由collections类实现的,该类有很多public static方法,可以直接对collection接口的实现类进行操作

(七)异常概述

为什么需要异常

程序中出现的问题是无法通过逻辑判断来解决的

异常的处理机制

  • 当Java程序运行出现问题时,系统会自动检测到该错误,并立即生成一个与该错误对应的异常对象
  • 然后把该异常对象提交给Java虚拟机
  • Java虚拟机会自动寻找相应的处理代码来处理这个异常,如果没有找到,程序将会被强行终止
  • 程序员可以自己编写代码来捕捉可能出现的异常,并编写代码来处理相应的异常

异常分类

女娲补天——Java_第5张图片

  • Throwable
    • Error:系统错误,程序员无法处理这些异常
    • Exception:是程序员可以捕获并处理的异常
      • RuntimeException 是可以处理也可以不处理的异常
      • Exception子类但不是RuntimeException的子类的 是必须处理的异常

Exception e是一个大的父类

  • 它是在运行中发生的错误,不是语法错误,也不是逻辑错误,而是一些具有一定不确定性的事件所引发的程序不正常运行
    • ArithmeticException:数学异常。
    • ArrayIndexOutOfBoundsException:数组下标越界异常。
    • ClassCastException:类型转换异常。
    • IllegalArgumentException:非法参数异常。
    • IndexOutBoundsException:下标转换异常。
    • IOException:输入输出流异常
    • NullPointerException:空指针异常。
    • UnsupportedOperationException:不支持的操作。
class A
	int divide (int a, int b)// add sub minus multiply positive nagetive
	{ 
		int m;
		m = a/b;
		return m;
	}
}
public class TsetExcep_1{
	public static void main(String[] args)
	{
		A aa = new A();
		
		try{
			aa.divide(6,2);//可能会出错的代码
		}
		catch(ArithmeticException e)//e来接收try语句中抛出的异常对象 让catch捕获
		{
			e.printStackTrace();//可以简单理解为输出该异常的具体信息;
			System.out.printl("除零错误,你的程序出错啦!除数不能为零");
		}
		
		System.out.printl("llalallallallal");
	}
}	
public class TsetExcep_2{
	public static void main(String[] args)
		{
			int i;
			Scanne sc = new Scanner();
			try{
				i = sc.nextInt();
				System.out.printf("i = %d\n", i);
			}
			catch(InputMismatchException e)   
		//无法获取用户到底输入的是什么,所以我们只能用try catch实现异常捕获,而不是用if else
			{
				System.out.printl("输入数据不合法,程序被终止!");
			}
class A
	int divide (int a, int b){ 
		int m;
		m = a/b;
		return m;
	}
	public void f()
	{
		g();
	}
	public void g()
	{
		divide(6,0);
	}
}

public class TsetExcep_3{
	public static void main(String[] args)
		{
			try{
				new A().g();//可能会出错的代码
			}
			catch(Exception e)
			{
				e.printStackTrace();//可以简单理解为输出该异常的具体信息;				
			}

	}
}	
import java.io.*
class A{
	public void f() throws IOException //throws再抛 不处理
	{ 
		throw new IOException();//throw 抛无异常
		//必须处理的异常
	}
	public void g()
	{
		throw new ArithmeticException();
		//可不处理的异常
	}
}

public class TsetExcep_4{
	public static void main(String[] args) //throws IOException
		{
			A aa = new A();
			
			try{
				aa.f();
			}
			catch(IOException e)
			{
				e.printStackTrace();
			}

	}
}	

要么自己try catch 要么就甩锅给调用者try catch

Finally的作用

import java.io.*
class A{
	int divide (int a, int b){ 
		int m;
		m = a/b;
		return m;
	}
}

public class TsetExcep_5{
	public static void main(String[] args) 
	{
		try{
			A aa = new A(6,2);
		}
		catch(ArrayIndexOutBoundsException e)
		{
			e.printStackTrace();
		}
		finally
		{
			System.out.printf("wuuw");
		}
	}
}	
  • 无论try所指定的程序块是否抛出异常,也无论catch语句的异常类型是否与所抛弃的异常的类型一致,finally中的代码一定会得到执行
  • finally语句为异常处理提供一个统一的出口,使得在控制流程转到程序的其他部分以前,能够对程序的状态作统一的管理
  • 通常在finally语句中可以进行资源的请理工作,如关闭打开的文件、删除临时文件等

throw

throw 用来抛出异常;格式throw new 异常名(参数)

假设f方法抛出了A异常,则f方法有两种方式来处理

  • throws A
    • 谁调用f方法,谁处理A异常,f方法本身不处理异常
  • try{...} catch(){ ...}
    • f方法本身自己来处理A异常

要抛出的异常必须得是Throwable的子类

import java.io.*
class B extends Throwable
{
	//extends Throwable 去掉报错
	//自定义异常
	
}
class A{
	public int divide (int a, int b){ 
		int m;
		m = a/b;
		return m;
	}
}

public class TsetExcep_6{
	public static void main(String[] args) 
		{
	}
}	
import java.io.*
class DivisorIsZeroException extends Exception
{
	//extends Throwable 去掉报错
	//自定义异常
	public DivisorIsZeroException(String name){
		super(name);
	}
}
class A{
	public int divide (int a, int b) throws  DivisorIsZeroException
	{ 
		int m;
		if(0==b)
			throw DivisorIsZeroException("除数不能为零!");
		else
			m = a/b;
		return m;
	}
}

public class TsetExcep_7{
	public static void main(String[] args) 
		{
			A aa = new A();
			try{
				aa.divide(6,0);
			}catch(Exception e)
			{
				e.printStackTrace();
			}
	}
}	

子类异常抛出的范围

class A extends Exception 
{
}
class B extends Exception 
{
}
class C extends Exception 
{
}
class M 
{
	 void f() extends A, B
	 {
	 }
 }
class N extends M
{
	 void f() throws A,B //子类重写父类的f方法
	 {
	 	//可以throws A或B,也可以throws A,B,但不可以throws C
	 }
}
class Test
{
	public void k(M mm){//多态的运用
		try{
			mm.f();
		}
		catch(A aa){
		}
		catch(B bb){
		}
	}
}
class TestExtendExce
{
	public static void main(String[] args)
	{
		M m = new M();
		N n = new N();

}
  • 所有的catch只能有一个被执行,有可能所有的catch都没有被执行
  • 先catch子类异常再catch父类异常
    • 由小到大把所有异常都找出来
    • 父类可以捕获所有异常,所以如果先catch父类再catch子类,就会导致报错说已经捕获到什么啦啦啦啦
      在这里插入图片描述
  • 重写方法抛出异常的范围不能大于被重写方法抛出的异常范围

异常的优点


传统的ifelse语句无法对想不到的错误已经处理,而异常处理有很多优势:

  • 强制程序员考虑程序的安全性与健壮性
  • 增强了程序员对程序的可控性
  • 有利于代码的调试
  • 把错误处理代码从常规代码中分离出来

(八)String

Java的字符串使用Unicode字符码体系,一个字符占用2B。
这个体系不同于ASCII字符码,涵盖了几乎所有语言会出现的字符。

用十六进制编码表示为\u0000~\uFFFF,其中\u前缀标志着这是一个Unicode值

\u0061代表字符a

String类的构造器

b. String (String original):用字符串常量创建字符串对象。
a. String (char[] value):用char数组创建字符串对象。
a. String (char[] value,int offset, int count):用char数组中从下标offset开始的count个字符创建字符串对象。

字符串比较方法

b. int compareTo (String anotherString):当前字符串比anotherString大,返回正整数;小,返回小于0的整数;相等,返回0。比较的原则:在字母序中,后面的比前面的大;小写的比大写大.。
a. int compareToIgnoreCase (String anotherString):忽略大小写,比较两字符串大小。
b. boolean equals (Object anObject):当前字符串对象与anObject有相同的字符串,则返回true;否,则返回false。这个方法对于字符大小写敏感。
a. boolean equalsIgnoreCase (String anotherString):同equals (),但忽略大小写。
a. boolean startWith (String prefix):判断当前字符串是否以prefix开始。

查找字符或子字符串的方法

b. char charAt (int index)
b. int indexOf (char ch)
a. int indexOf (char ch, int fromIndex)
b. int indexOf (Sting str)
a. int indexOf (Sting str, int fromIndex)
a. int lastIndexOf (……)

基于当前字符串返回一个新字符串方法

a. String concat (String str):返回当前字符串后追加str后的新字符串。
b. String replace (char oldChar, char newChar):在当前字符串中,将字符oldChar替换为newChar。
a. String replaceAll (String regex, String replacement):在当前字符串中,将字符串regex 替换为replacement。
b. String substring (int beginIndex):返回当前字符串从beginIndex开始的尾子字符串。
b. String substring (int beginIndex, int endIndex):返回当前字符串中从beginIndex开始到endIndex的子字符串。
b. String toLowerCase ():将当前字符串全部转换为小写。
b. String toUpperCase ():将当前字符串全部转换为大写。

toString方法

class A //默认每个类都使用object作为超类
{
}
public class TestObject
{
	public static void main(String[] args)
	{
		A aa = new A();
		System.out.print("%s", aa.toString());
		//object类下面带有toString方法
	}
}

空的A类得到的返回值是AA对象在堆里面内存地址的16进制表示

class A //默认每个类都使用object作为超类
{	
	public String toString() //方法的重写
	{
		return "重写后的返回值";
	}
}
public class TestObject_1
{
	public static void main(String[] args)
	{
		A aa = new A();
		System.out.print("%s", aa.toString());
	}
}

基本类型向字符串类型的转换
基本类型与字符串进行“+”运算,运算结果为字符串类型

class Dian
{
	int x, y;
	public Dian(int x, int y)
	{
		this.x = x;
		this.y = y;
	}
	public String toString() //方法的重写
	{
		return "[" + x + "," + y+ "]";
	}
}
public class TestPoint
{
	public static void main(String[] args)
	{
		Dian d = new Dian(1,2);
		//申明一个对象时会调用这个对象的构造函数(only 1)
		System.out.print("%s", d);
		//若未重写返回d对象所在类Dian在toString方法下的内存地址
		System.out.print("%s", aa.toString());
	}
}

equals

class A
{
	public int i;
	public A(int i)
	{
		this.i = i;
	}
}
public class TestStringEquals_1
{
	public static void main(String[] args)
	{
		A aa1 = new A(2);
		A aa2 = new A(2);
	
		System.out.println( aa1.equals(aa2)); //false
		//for same 内存,方得true
		if(aa1 == aa2)
			System.out.println( "aa1和aa2相等");
		else
			System.out.println( "aa1和aa2不相等");
	}
}
class A
{
	public int i;
	public A(int i)
	{
		this.i = i;
	}
	public boolean equals(Object ob)
	{
		A aa = (A)Obj; //向下造型
		
		if (this.i == aa.i)//当前对象的i和obj代表的i相等
			return true;
		else 
			return false;
	}
}
public class TestStringEquals_2
{
	public static void main(String[] args)
	{
		A aa1 = new A(2);
		A aa2 = new A(2);
	
		System.out.println( aa1.equals(aa2)); //true
		//this aa1
		//obj aa2
	}
}

女娲补天——Java_第6张图片

printf vs println

归属于对象out的一个方法,而这个out是System类的一个static成员(属性)

  • 用static修饰的类成员可以用类名直接调用

System.out.println();
System.out.printf();

public class TestPrint
{
	public static void main(String[] args)
	{
		int i, j, k;
		i = 1;
		j = 2;
		k = 3;
		System.out.printf("%d的值+%d的值是%d\n", i, j, k);
		System.out.println(i+"的值+"+j+"的值是"+k);
	//隐式地将其后面用“+”连接的任何数据转换为字符串连接在前面的字符串后面
		int m = 1234;
		System.out.println(m);
		System.out.printf("%d",m);

		System.out.printf("%d用十六进制表示的结果是:%#X",m,m);
		System.out.println(m+"用十六进制表示的结果是:OX"+(Integer.toHexString(m).toUpperCase());
		
	}
}

StringBuffer类的由来

String类对象一旦创建就不可更改
如果经常对字符串内容进行修改而使用String的话,就会导致即消耗空间又消耗时间

String s1 = "abc";
String s2 = "123";
String s1 = s1 + s2;

上述代码并没有在s1的基础上继续增加s2的内容,而是新创建一个字符串空间存入相应的内容
StringBuffer对象的内容是可以修改的,且含有大量修改字符串的方法
public StringBuffer()创建一个空的没有任何字符的StringBuffer对象
public StringBuffer(int capacity)创建一个不带字符,但具有初始容量的字符串缓冲区
public StringBuffer(String str)创建一个包含str对象相同的字符序列

(九)数组

数组的表示与存储

数组的变量声明

数据类型 数组名[] = null;
prefer数据类型[] 数组名 = null;因为可以一看过去就知道这是数组

数组的内存分配

数组名 = new 数据类型[元素个数];
必须指明:

  • 数组元素的类型
  • 元素的长度(length),即元素个数
  • 引用变量的名称

数组的初始化

public class TestArray
{
	public static void main(String[] args)
	{
		//方式1
		//动态初始化:先声明,再赋值
		int[] arr1;
		arr1 = new int[3];
		arr1[0] = 0;
		arr1[1] = 1;
		arr1[2] = 2;
		showArr(arr1);
		System.out.println("*************");
		//方式2
		//静态初始化:在使用new操作符分配存储空间的同时进行初始化
		int[] arr2 = new int[]{0,1,2};
		showArr(arr2);
		System.out.println("*************");
		
		//静态初始化时可以不使用new操作符
		int[] arr3 = P{0,1,2};//both ok
		showArr(arr3);
		System.out.println("*************");
	}

	public static void showArr(int[] arr)
	{
		for(int i = 0; i<arr.length; ++i)
		{          //length是属性不是方法()
			System.out.println(arr[i]);
		}
	}

注意:
在静态初始化时不可以写出数组维表达式,因为编译器完全可以通过初始化值的个数自动计算出需要分配发存储空间的大小,无须画蛇添足。

数组元素的访问

  • 普通循环结构
  • 增强for遍历数组元素
    for (循环变量类型 循环变量名称: 要被遍历的集合) 循环体
	int[] a = null;
	a = new int[3];
	
	for(int e:a) {
		System.out.println(e);
	}

你可能感兴趣的:(笔记,java,多态,编程语言)