1、父类到子类的转换
向下转换(强制类型转换)
Pet pet = new Dog("aa", 20); Dog dog = (dot) new Pet()
报错,必须转换为父类指向的真实子类类型
2、接口
java中的继承关系是单继承,如果拥有多个父类的时候,可以考虑使用接口进行实现
java中的接口具备广泛的使用
用法:
1、使用interface来修饰
2、接口中可以包含多个方法,且方法跟抽象类中的抽象方法一致,可以不写实现,子类在实现的时候必须要实现代码逻辑
3、子类实现接口实现使用implements关键字
特征:
1、接口中的所有方法都是抽象方法,不能包含方法的实现
2、接口中的所有方法与常量的访问修饰权限都是public,不写并不是默认访问权限,而是public, 系统默认会添加public;
3、接口不能被实例化
4、接口的子类必须实现接口中的所有方法,跟抽象类有所不同,抽象类中的抽象方法必须被子类实现
5、子类可以实现多个接口
6、接口中的变量都是静态常量(相当于加上static final)
7、jdk8后,接口中可以定义方法,但是需要添加default进行修饰, 可以被继承的进行重写
接口:
package com.yfbill.test;
public interface ITest {
//静态常量
public static final String abc = "are you ok???";
//需要子类实现的方法
public int getUniqueId();
public String getName();
}
实现子类:
package com.yfbill.utils;
import com.yfbill.test.ITest;
public class Test implements ITest { //如果是多个接口的话,用“,”来隔开
@Override
public int getUniqueId() {
return 0;
}
@Override
public String getName() {
return Test.abc;
}
}
抽象类中可以实现接口,并且不实现接口中的方法,而接口只能继承接口,不能实现接口
在实际的项目开发过程中,如果可以使用接口,尽量使用接口,将单继承的父类留在最关键的地方
3、内部类
一个java文件中可以包含多个class,但是只能有一个public class
如果一个类定义在另一个类的内部,此时可以称之为内部类
使用:
创建内部类的时候,跟之前的方法不一样,需要在内部类的前面添加外部类进行修饰
InnerClassDemo.InnerClass inner = new InnerClassDemo().new InnerClass();
特点:
1、内部类可以方便的访问外部类的私有属性
2、外部类不能访问内部类的私有属性,但是如果创建了内部类的对象, 此时可以在外部类中访问私有属性
3、内部类不能定义静态属性或静态方法
4、当内部类和外部类具有相同的私有属性的时候,在外部类中访问的时候,可以直接访问内部类的属性,如果需要访问外部类的属性,那么需要添加 外部类名.this.属性。
内部类以及外部类(以下是成员内部类)
package com.yfbill.test;
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void say() {
System.out.println(this.name + "可以say anything");
}
public void printInnerClass() {
Teacher t = new Teacher(1122); //在外部类中访问内部类,必须实例化出内部类,此时的内部类,可以访问外部类的属性
t.info(); //会输出 name:bill
}
public class Teacher { //内部类
private int count;
public Teacher(int count) {
this.count = count;
}
public String getCount() {
return "the teacher's count is " + this.count;
}
public void info() {
System.out.println("name:" + Person.this.name);
}
}
}
调用:
package com.yfbill.test;
public class Test {
public static void main(String[] args) {
Person p = new Person("bill", 30);
p.say(); //输出 bill可以say anything
p.printInnerClass(); //输出 name:bill
Person.Teacher t = p.new Teacher(9527);
System.out.println(t.getCount()); //输出 the teacher's count is 9527
t.info(); //输出 name:bill
}
}
分类
1、匿名内部类 =》 当定义了一个类,实现了某个接口的时候,在使用过程中只需要使用一次,没有其他用途,其实考虑到代码编写的简洁,可以考虑不创建具体的类,而采用new interface(){ 添加未实现方法 } 叫做匿名内部类
package com.yfbill.test;
//定义接口
interface IPerson {
public void run ();
}
//定义类
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void say() {
//匿名内部类,匿名的实现了IPerson接口
//隐藏的class声明
new IPerson() {
@Override
public void run() {
System.out.println("我的名字是" + Person.this.name + "我今年的年龄是:" + Person.this.age + "我很喜欢跑步");
}
}.run(); //直接调用方法
}
}
调用:
package com.yfbill.test;
public class Test {
public static void main(String[] args) {
Person p = new Person("bill", 30);
p.say();
}
}
2、静态内部类 =》 关键字static可以修饰成员变量、方法、代码块、其实还可以修饰内部类,使用static修饰的内部类我们称之为静态内部类,静态内部类和非静态内部类之间存在一个最大的区别,非静态内部类在编译完成之后会隐含的保存着一个引用,该引用是指向创建它的外围类,但是静态类没有。没有这个引用就意味着:
1.静态内部类的创建不需要依赖外部类可以直接创建。
2.静态内部类不可以使用任何外部类的非static类(包括属性和方法),但可以存在自己的成员变量。
package com.yfbill.test;
public class Person {
private String password;
private static String username = "admin";
public static String getUsername() {
return username;
}
public String getPassword() {
return password;
}
//静态内部类
public static class Teacher {
private int code;
//静态内部类的构造方法
public Teacher (int code) {
this.code = code;
}
//静态内部类不能访问外部类的非静态方法和属性
public void showCode () {
System.out.println("code:" + this.code);
System.out.println(Person.username);
System.out.println(Person.getUsername());
}
}
public static void main(String[] args) {
Person p = new Person();
//静态内部类的实例化以及调用方式
Person.Teacher t = new Person.Teacher(9527);
t.showCode();
}
}
3、方法内部类 =》 方法内部类顾名思义就是定义在方法里的类
1.方法内部类不允许使用访问权限修饰符(public、private、protected)均不允许。
2. 方法内部类对外部完全隐藏,除了创建这个类的方法可以访问它以外,其他地方均不能访问 (换句话说其他方法或者类都不知道有这个类的存在)方法内部类对外部完全隐藏,出了创建这个类的方法可以访问它,其他地方均不能访问。
3. 方法内部类如果想要使用方法形参,该形参必须使用final声明(JDK8形参变为隐式final声明)
class Outer{
private int num =5;
//普通方法
public void dispaly(int temp)
{
//方法内部类即嵌套在方法里面
class Inner{
public void fun()
{
System.out.println(num);
temp++;
System.out.println(temp);
}
}
//方法内部类在方法里面创建
new Inner().fun();
}
}
public class Test{
public static void main(String[] args)
{
Outer out = new Outer();
out.dispaly(2);
}
}
4、包装类
包装类的作用
a、作为 和基本数据类型对应的类 类型存在,方便涉及到对象的操作。
b、包含每种基本数据类型的相关属性如最大值、最小值等,以及相关的操作方法。
字符串与Integer的互相转换
public class FirstJava {
public static void main(String[] args) {
// 把字符串转成Integer类型
Integer count = Integer.valueOf("12");
// 把字符串转成Integer类型
Integer count1 = Integer.parseInt("12");
System.out.println(count);
// 输出int数值
System.out.println(count.intValue());
// 把int类型转成string类型
String str = String.valueOf(12);
// 把int类型转成string类型方式二
String str1 = "" + 12;
System.out.println(str);
}
}
总结,在使用包装类的时候,需要进行类型转换可以使用valueOf进行转换, 如果需要转成int则可以使用intValue()相关的方法,以些类推,如果是由内往外转可以使用parseInt()类似的方法,以些类推
包装类与基本类型的不同点:
a、包装类是对象,拥有方法与字段,对象的调用都是通过引用对象地址,基本类型不是
b、声明方式不同: 基本类型不需要new关键字,包装类型需要new在堆内存中进行new来分配内存空间
c、存储位置不同: 基本类型是存储在栈中, 包装类型是把对象放在在堆中,然后通过对象的引用来调用
d、初始值不同:int的初始值为0,boolean的初始值, 包装类的初始值为null
e、包装类型是引用的传递,基本类型是值的传递
拆箱与装箱
public class FirstJava {
public static void main(String[] args) {
Integer num = 60; // 60 为int类型, 声明把60赋值给Integer类型num相当于装箱,底层调用了valueOf方法
int num1 = num; // num是Integer类型,num1是int类型,相当于把Integer类型赋值给int就相当于拆箱底层调用到intValue方法
// 以下涉及于装箱与拆箱的过程,
Integer n = 0; // 装箱
n+=1; // 拆箱相加后又进行装箱
}
}
5、异常处理
java中的异常处理是通过5个关键字来实现的: try catch finally throw throws;
程序在运行过程中如果出现了问题,会导致后面的代码无法正常运行,而使用异常机制,可以对异常情况进行处理,同时后续代码会继续执行。
异常处理方式
1、捕获异常
try{ 代码逻辑 }catch( Exception e ) { 异常处理逻辑 }
package com.yfbill.test;
import java.util.Scanner;
public class Person {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
try{
System.out.println("请输入被除数:");
int num1 = scan.nextInt(); //假如本程序出现异常,那么该行代码下的的不能被执行,但是异常外的代码会被执行
System.out.println("请输入除数");
int num2 = scan.nextInt();
System.out.println(String.format("结果是:%d", num1/num2));
}catch(Exception e) {
System.out.println("出现异常");
e.printStackTrace(); //打印堆栈信息(常用)
System.out.println(e.getMessage()); //打印错误提示
}
System.out.println("感觉使用本程序");
}
}
注意:在使用的过程中,尽量在少的代码处且易发生异常的地方使用异常捕获
2、try{ 代码逻辑 }catch( Exception e ) { 异常处理逻辑 }catch(具体的异常); =》 可以针对每一个具体的异常做更丰富的处理
public class DealException
{
public static void main(String args[])
{
try
//要检查的程序语句
{
int a[] = new int[5];
a[0] = 3;
a[1] = 1;
//a[1] = 0;//除数为0异常
//a[10] = 7;//数组下标越界异常
int result = a[0]/a[1];
System.out.println(result);
}
catch(ArrayIndexOutOfBoundsException ex)
//异常发生时的处理语句
{
System.out.println("数组越界异常");
ex.printStackTrace();//显示异常的堆栈跟踪信息
}
catch(ArithmeticException ex)
{
System.out.println("算术运算异常");
ex.printStackTrace();
}
finally
//这个代码块一定会被执行
{
System.out.println("finally语句不论是否有异常都会被执行。");
}
System.out.println("异常处理结束!");
}
}
注意:在使用多重catch的时候要注意多重异常的顺序,将子类异常放在异常最前面,而父类放在异常的后面
3、finally => 在程序运行过程中,如果处理异常的部份包含finally的处理,那么无论代码是否发生异常,finally中的代码总会执行
finally包含的处理逻辑: 1:IO流的关闭操作一般设置在finally中; 2、数据库的连接关闭操作设置在finally中
package com.yfbill.test;
public class Person {
private static int init() {
int num = 10;
try {
num += 20;
return num;
} catch(Exception e) {
e.printStackTrace();
return num - 10;
} finally {
System.out.println("this is finally"); //会输出结果
// return num + 30;
}
}
public static void main(String[] args) {
System.out.println(Person.init()); //返回30,如果finally中的return 存在,那么就返回60,finally中的代码会被执行
}
}
4、抛出异常:在异常情况出现的时候,可以使用try...catch...finally的方式对异常进行处理,除此之外,可以将异常向外抛出
1、在方法调用过程中可能存在N多个方法的调用,此时假如每个方法中都包含了异常情况,
那么就需要在每个方法中进行try...catch...,另外一种比较简单的方式,就是在方法的最外层调用处理一次即可,
使用throws的方法,对所有执行过程中的所有方法出现的异常进行统一集中处理。
2、如何判断是使用throws还是使用try...catch...,最稳妥的方式是在每个方法中都进行异常处理,偷懒的方式是在判断在整个调用过程中,最外层的调用方法是否对异常处理,如果有就直接使用throws,如果没有就直接使用try...catch...进行处理
package com.yfbill.test;
public class Person {
public void init () { //在最外层调用的时候使用try...catch...进行处理
try{
this.test3();
}catch(Exception e) {
e.printStackTrace();
}finally {
System.out.println("这个是执行完成了哈");
}
}
private void test1() throws Exception {
System.out.println(1/0);
}
private void test2() throws Exception {
this.test1();
System.out.println(1/0);
}
private void test3() throws Exception {
this.test2();
System.out.println(1/0);
}
public static void main(String[] args) {
Person p = new Person();
p.init();
}
}
5、常见的异常类型
6、抛出异常
package com.yfbill.test;
public class Person {
public void init () {
try{
this.test1();
}catch(Exception e) {
e.printStackTrace();
}finally {
System.out.println("这个是执行完成了哈");
}
}
private void test1() throws Exception {
throw new Exception("现在发生错误了哈"); //主动抛出异常
}
public static void main(String[] args) {
Person p = new Person();
p.init();
}
}
也可以主动抛出具体的异常
7、可以自已定义异常类
package com.yfbill.test;
public class TestException extends Exception{
public TestException () {
super();
}
public TestException (String s) {
super(s);
}
}