异常
异常分为受查异常和非受查异常。(https://blog.csdn.net/csj50/article/details/79605171)
异常处理机制:try-catch-finally
try{}语句块中放的是要检测的java代码,可能有会抛出异常,也可能会正常执行。
catch(异常类型){}块是当java运行时系统接收到try块中所抛出异常对象时,会寻找能处理这一异常catch块来进行处理(可以有多个catch块)。
finally{}不管系统有没有抛出异常都会去执行,一般用来释放资源。除非在之前执行了System.exti(0)。
import java.util.Scanner;
class Person
{
String name;
}
public class Test {
public static void main(String[] args) {
Person p = null;
int a = 10;
int b;
double c = 0;
Scanner sc = new Scanner(System.in);
System.out.println("请输入除数");
b = sc.nextInt();
try{//try中放语句块,初始化定义不要放
c = (double)a/b;
//p.name = "wang";//尽管此处异常,finally依然可以执行
}
catch(java.lang.ArithmeticException e){
System.out.println("除数是0,请重新输入");
b = sc.nextInt();
c = a/b;
System.out.println("c = "+c);
}
catch(java.lang.NullPointerException e){
System.out.println("空指针");
}
// finally{
// System.out.println("end");
// }
System.out.println("c = "+c);
System.out.println("end1");
}
}
throw和throws(throw和throws用法_每天进步一点点。。。-CSDN博客_throw和throws的用法)
throw用在方法内,后面跟上要抛出的异常类对象
throws修饰在方法上,告诉调用者此方法可能会抛出异常,后面跟上可能要抛出的异常类名
class Bar
{
public int age;
public Bar(int age){
this.age = age;
}
// void check()throws Agehdfghdjks{
// if(age < 18){
// throw new Agehdfghdjks("未成年");//抛出异常
// }
// }
void check()throws IllegalArgumentException{
if(age < 18){
throw new IllegalArgumentException("未成年");//抛出异常
}
}
}
//class Agehdfghdjks extends Exception//自定义异常
//{
// String message;
// public Agehdfghdjks(String message){//构造方法
// this.message = message;
// }
//}
public class hngd {
public static void main(String[] args) {
Bar b = new Bar(15);
try{
b.check();
}catch(IllegalArgumentException e){
System.out.println(e.getMessage());//处理异常
e.printStackTrace();//打印异常信息
}
System.out.println("end");
}
}
泛型:
class Cls1
{
int a;
public Cls1(int a){
this.a = a;
}
public int getData()
{
return a;
}
}
class Cls2
{
String a;
public Cls2(String a){
this.a = a;
}
public String getData()
{
return a;
}
}
public class Test {
public static void main(String[] args) {
Cls1 cls1 = new Cls1(5);
System.out.println(cls1.getData());
Cls2 cls2 = new Cls2("地方");
System.out.println(cls2.getData());
}
}
经过对以上两个类的分析,提出问题:若需要产生多个对象,每个对象逻辑完全一样,只是成员变量类型不同,如何做?泛型(我用的是eclipse,编译可能会出错-Syntax error, parameterized types are only available if source level is 1.5 or greater;解决方法:右击项目,修改properties,找到java compiler修改compiler compliance level为1.6)
class Cls1<T>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
}
public class Test {
public static void main(String[] args) {
Cls1<Integer> cls1 = new Cls1<Integer>(10);
System.out.println(cls1.getData());
Cls1<String> cls2 = new Cls1<String>("地方");
System.out.println(cls2.getData());
}
}
泛型可以理解为把类型当作变量,以下是它的特点:
1、泛型的类型参数可以是泛型类 |
2、泛型类可以同时设置多个类型参数 |
3、泛型类可以继承泛型类 |
4、泛型类可以实现泛型接口 |
//特点1
class Cls1<T>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
}
public class Test {
public static void main(String[] args) {
Cls1<Cls1<Integer>> cls1 = new Cls1<Cls1<Integer>>(new Cls1<Integer>(10));
System.out.println(cls1.getData().getData());
}
}
//特点2
class Cls2<T,T2>//可设置多个参数
{
T a;
T2 b;
public Cls2(T a,T2 b){
this.a = a;
this.b = b;
}
public T getData(){
return a;
}
public T2 getData2(){
return b;
}
}
public class Test {
public static void main(String[] args) {
Cls2<Integer,String> cls3 = new Cls2<Integer,String>(1,"hao");
System.out.println(cls3.getData()+","+cls3.getData2());
}
}
//特点3
abstract class Cls1<T>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
abstract void printInfo();
}
//特点4
interface Cls3<T>
{
abstract void printInfo2(T t);
}
/*这里可以发现泛型的一个小bug,就是继承的抽象类和接口如果泛型变量都是同一个字母,会产生类型上的冲突
只能把给他们命名不同的变量,并在子类Cls2的泛型参数再加上一个即可*/
class Cls2<T,T2> extends Cls1<T> implements Cls3<T>
{
T2 b;
public Cls2(T a,T2 b){
super(a);
this.b = b;
}
public T2 getData2(){
return b;
}
@Override
void printInfo() {
// TODO Auto-generated method stub
System.out.println("抽象类");
}
@Override
public void printInfo2(T t) {
// TODO Auto-generated method stub
System.out.println("接口"+t);
}
}
public class Test {
public static void main(String[] args) {
Cls2<Integer,String> cls = new Cls2<Integer,String> (10,"五十三东方");
cls.printInfo();
cls.printInfo2(6);
}
}
其实系统在处理类似以上代码定义的泛型时,是这样的:
abstract class Cls1<T extends Object>
只不过单独写T,系统默认以上格式。如果在使用泛型时,要限制使用泛型类型就需要extends某个类或者接口。
//示例:限制使用泛型的类型,继承某个抽象类
class Animal
{
}
class Dog extends Animal
{
}
abstract class Cls1<T extends Animal>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
abstract void printInfo();
}
interface Cls3<T>
{
abstract void printInfo2(T t);
}
class Cls2<T extends Animal,T2> extends Cls1<T> implements Cls3<T>
{
T2 b;
public Cls2(T a,T2 b){
super(a);
this.b = b;
}
public T2 getData2(){
return b;
}
@Override
void printInfo() {
// TODO Auto-generated method stub
System.out.println("抽象类");
}
@Override
public void printInfo2(T t) {
// TODO Auto-generated method stub
System.out.println("接口"+t);
}
}
public class Test {
public static void main(String[] args) {
Cls2<Dog,String> cls = new Cls2<Dog,String> (new Dog(),"五十三东方");
}
}
interface Move
{
abstract void test();
}
class A implements Move
{
public void test() {
}
}
abstract class Cls1<T extends Move>//这里不能用implements
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
abstract void printInfo();
}
interface Cls3<T>
{
abstract void printInfo2(T t);
}
class Cls2<T extends Move,T2> extends Cls1<T> implements Cls3<T>
{
T2 b;
public Cls2(T a,T2 b){
super(a);
this.b = b;
}
public T2 getData2(){
return b;
}
@Override
void printInfo() {
// TODO Auto-generated method stub
System.out.println("抽象类");
}
@Override
public void printInfo2(T t) {
// TODO Auto-generated method stub
System.out.println("接口"+t);
}
}
public class Test {
public static void main(String[] args) {
Cls2<A,String> cls = new Cls2<A,String> (new A(),"五十三东方");
}
}
同一泛型类,若实例化时给定的实际类型不同,则这些实例的类型是不兼容的,不能相互赋值。但可以使用泛型通配符(?)声明泛型类的变量就可以解决这个问题
“?”代表一个类型。
Cls<String> cls = new Cls<String>(11);
Cls<?> cls1 = cls;
和限制泛型的上限相似,同样可以使用extends关键字限定通配类型上限:
Cls<Dog> cls = new Cls<Dog>();
Cls<? extends Animal> cls1 = cls;
还可以使用super关键字将通配符匹配类型限定为某个类型
Cls<Animal> cls = new Cls<Animal>();
Cls<? super Dog> cls1 = cls;
不仅类可以声明泛型,类中的方法也可以声明仅用于自身的泛型,这种方法叫做泛型方法。定义格式为:访问修饰符<泛型列表> 返回类型 方法名(参数列表){ 实现代码 }
在泛型列表中声明的泛型,可用于该方法的返回类型声明、参数类型声明和方法代码中的局部变量的类型声明。
类中其他方法不能使用当前方法生命的泛型。
class A<T>
{
public void printInfo(T t){
System.out.println(t);
}
}
//泛型方法更灵活,比方法重载更好
class B
{
public<T> T printInfo(T t){
System.out.println(t);
return t;
}
//泛型方法的重载
public<T,T2> void printInfo(T t,T2 t2){
System.out.println(t);
System.out.println(t2);
}
}
public class Test {
public static void main(String[] args) {
A<String> a = new A<String>();
a.printInfo("你好");
B b = new B();
b.printInfo("你好");
b.printInfo('d');
b.printInfo(5456);
b.printInfo(12.3);
}
}
class Animal
{
public void eat(){
System.out.println("我是动物");
}
}
class Dog extends Animal
{
public void eat(){
System.out.println("我是dog");
}
}
class Cat extends Animal
{
public void eat(){
System.out.println("我是cat");
}
}
class A<T>
{
public void printInfo(T t){
System.out.println(t);
}
}
//泛型方法更灵活,比方法重载更好
class B
{
public<T> T printInfo(T t){
System.out.println(t);
return t;
}
//泛型方法的重载
public<T,T2> void printInfo(T t,T2 t2){
System.out.println(t);
System.out.println(t2);
}
public<T extends Animal> void printInfo1(T t){
t.eat();
}
public static <T extends Animal> void printInfo2(T t){
t.eat();
}
}
public class Test {
public static void main(String[] args) {
B b = new B();
b.printInfo1(new Dog());
B.printInfo2(new Cat());
}
}