01 面对象的特征 笔试题:面向对象的特点? 1抽象:抽象总结现实世界的信息Java语言表达。 2.包装:用一个类包装信息,私有属性,公开逻辑验证函数,实现信息包装。(控制数据访问权限) 3.继承:后面有具体内容。 4多态:背后有具体内容。
02 类的继承: Object 从父类的角度来看,一个类是可以衍生的(derive)无数的子类,但从子类的角度来看,一个Java 子类只能继承一个父类,只能继承一个父类。类可以通过继承重复使用,即类继承父类,可以继承父类的变量和函数,但不能继承父类的结构。(以类名命名结构器) control h:看一类继承关系。
03 类继承的访问控制: default private子孙类不能访问定义的方法和变量。 public 子孙可以访问。protected 同一包下的子孙可以访问。
04 方法的覆盖和重写:子类继承父类可以继承父类公开的变量和函数,子类可以重写父类方法,以满足自己的个性化需求。然而,子类重写父类的方法有以下要求:方法名称、输入参数和返回值。子类应与父类相同,子类覆盖方法的访问权限不得比父类更严格。
05 super 关键字:这个关键字在 Java 可以中指父类 super 引用父类成分,调用父类的方法和结构。
再谈结构器: 如果类中有定义参数的结构器,则无参数的默认结构器将消失。 如果父类只定义一个有参数的结构,那么子类在继承父类后需要实例化一个对象时,必须显示一个与父类结构相同的参数数数和参数类型的结构来使用,否则会报错。 父类要有默认的构造器,子类才能重载自己的构造器使用。 可用于子类重载结构器 this 也可以使用当前类别的其他结构 super 调用父类结构器。
package com.qicong.gj.c05; /** * User: 祁大聪 */ public class Person {
//alt enter public String name; public Integer age; private Integer money; public Person(){
this("sanNi",22); ///调用当前类别的构造器 } public Person(String name, Integer age){
this.name = name; this.age = age; } public void printNameAndAge(){
System.out.println("name = " name " , age = " age); } public void dance(){
System.out.println("我会跳舞");
}
public void sing(String song){
System.out.println("我会唱歌");
}
private void getMoney(){
System.out.println("取现金");
}
}
package com.qicong.gj.c05;
/** * User: 祁大聪 */
public class Girl extends Person {
@Override
public void dance() {
//重写父类的函数,满足自身个性化的需要
System.out.println("女孩子喜欢跳民族舞");
}
public void myDance(){
super.printNameAndAge(); //调用父类的函数
dance();
}
// public Girl(String name, Integer age){
// super(name, age);
// }
public static void main(String[] args) {
Girl g = new Girl();
g.name = "三妮"; //继承父类的属性
g.age = 22;
g.myDance();
}
}
06 this 关键字: static 和 this :static 指类的, this 指实例的。 引入继承关系,super 和 this :super指父类的,this指子类的。 函数中:由于就近原则,要把实例的值赋值给类的属性。
07 对象构造和初始化分析:用new关键字创建一个对象的流程,当类有父类时创造流程更复杂。 子类实例化一个对象,先初始化子类的变量,再调用当前子类的构造器,发现有父类去父类初始化变量,再调用父类的构造器,发现还有父类,就再初始化父类的父类的变量,再调用父类的父类构造器,直到它的父类是Object,就开始实现构造器,直到实现子类的构造器,创建一个对象。
09 final 关键字: final 修饰的类不可以被继承。修饰的方法不可以被覆盖重写。修饰的常量必须初始化且初始化以后常量不可以被修改。 修饰的引用对象不可以被修改,但可以修改引用对象的属性。(修饰的被实例化的对象不可以被修改,但可以修改实例化的对象的属性)
package com.qicong.gj.c09;
/** * User: 祁大聪 */
//public final class Person {
public class Person {
private final int age = 1000;
private final Boy boy = new Boy();
// public final void getName(){
//
// }
public void getName(){
}
public static void main(String[] args) {
Person p = new Person();
// p.age = 10001;
// p.boy = new Boy();
p.boy.name = "sanNi";
}
}
10 abstract 关键字:抽象命名时,一般在修饰符后面加上 abstract,抽象类不能被实例化,抽象函数没有函数体。在抽象类中可以定义有函数体的普通函数。
package com.qicong.gj.c10;
/** * User: 祁大聪 */
public abstract class AbstractPerson {
public void getAge(){
}
//抽象函数没有函数体
public abstract void getName();
}
package com.qicong.gj.c10;
/** * User: 祁大聪 */
//没有实现父类的任一抽象函数
public abstract class Boy extends AbstractPerson{
}
package com.qicong.gj.c10;
/** * User: 祁大聪 */
public class Girl extends AbstractPerson{
//实现父类中的抽象函数
public void getName(){
}
}
什么情况下类必须被定义成抽象类: 这个类中有一个抽象函数,这个类就得被声明为抽象类。 这个类是子类,继承了父类,但是没有实现父类中任何一个抽象函数,这个类就得被声明为抽象类。
11 interface 接口: 创建时直接选择创建 interface 接口,接口的命名一般在前面加I。 接口中定义的是初始化的常量(也可以不定义常量)和不用abstract 的抽象函数(接口中默认所有函数都是抽象函数),由接口的实现类以重写的方式,去实现接口中定义的抽象函数,或者声明为抽象类就可以实现接口但不重写抽象函数。
package com.qicong.gj.c11;
/** * User: 祁大聪 */
public interface IPerson {
public final String name="sanNi";
//两个没有函数体和abstract的抽象函数
public void getName();
public void getAge();
}
package com.qicong.gj.c11;
/** * User: 祁大聪 */
public class Person implements IPerson{
@Override
public void getName() {
}
@Override
public void getAge() {
}
}
package com.qicong.gj.c11;
/** * User: 祁大聪 */
public abstract class Person implements IPerson{
}
12 接口的实现: 一个类可以实现多个接口,以重写的方式实现接口,实现接口中的函数。Java中可以通过实现多个接口来模拟多继承。多个无关的类可以实现同一个接口。(uml 图:ArrayList , linkedList 实现abstract list)
package com.qicong.gj.c12;
/** * User: 祁大聪 */
//接口先继承再实现,Java类单继承和接口多实现
public class PersonImpl extends PersonTest implements IPerson, IBoy {
//重写的方式实现
@Override
public void getName() {
}
@Override
public void getAge() {
}
@Override
public void dance() {
}
}
语法上,是一个类先继承父类再实现一个或多个接口。
13 接口的继承:接口与类相似,都有继承的概念,但接口与类不同,接口可以多继承,多实现而类是单继承。
package com.qicong.gj.c13;
/** * User: 祁大聪 */
public interface IChild extends IGirl, IPerson{
public void play();
}
14 多态: 如果声明的是父类,可以以子类为实现类。但是实例化之后,只能调用子类中重写的父类的方法,调用子类自己定义的方法或属性会报错。 可以在函数中以父类为参数,调用函数时,传入子类,以子类为操作对象,当多个子类去继承这个父类,可以实现同一个函数,对传入的不同子类进行相同的操作,增加代码的灵活性。 15 instanseof 和类型转换: Java中对象类型分两种:自动类型,直接创建的对象。强制类型,强制转换的对象。 如果声明的是父类,可以以子类为实现类。 instanseof:判断对象的类型。判断实例化的对象是哪个子类,打印返回布尔类型。 对象类型的转换(Casting):转换成真实类型,用真实类型去调用函数。调整了多态中,以子类为实现类不能调用子类的函数,强制转换以后,就可以用子类去调用自定义的方法。但强制转换只用在有继承关系的对象之间。
例如,判断子类是 girl 强转成girl,调用 girl 的函数,判断子类是 boy,强转成 boy,调用 boy 的函数。
package com.qicong.gj.c15;
/** * User: 祁大聪 */
public class Test {
public void printPerson(Person p){
//返回布尔类型
System.out.println(p instanceof Girl);
System.out.println(p instanceof Boy);
if(p instanceof Girl){
Girl girl = (Girl)p;
girl.sing(); //Girl 中自己定义的函数
}
if(p instanceof Boy){
Boy boy = (Boy)p;
boy.dance(); //Boy 中自己定义的函数
}
}
public static void main(String[] args) {
Person p = new Girl();
Test t = new Test();
t.printPerson(p); //传入Girl
t.printPerson(new Boy()); //传入Boy
}
}
16 内部类: 在一个类中定义一个新类,这个类叫内部类,外面的类叫外部类。这种类在逻辑上是一个整体,删了外部类内部类也消失。内部类和外部类之间在逻辑上是从属关系。
main函数中声明内部类: 1外部类的内部类,凸显从属关系,内部类的名称,先实例化外部类再实例化内部类。定义完内部类,用内部类去调用函数。 2也可先实例化外部类,再用外部类的名称去实体化内部类。
public static void main(String[] args) {
Out.Inner inner = new Out().new Inner();
inner.doGrow();
Out out = new Out();
Out.Inner inner2 = out.new Inner();
}
17 内部类的特性: 内部类的特性和外部类相同,可以声明为抽象,可以单继承,也可以声明为 final,不被继承。
静态的内部类里,调用外部的,和定义内部的函数和变量都是静态的。不加 static 就是实例的,this关键字省略了,静态的内部类里不允许有实例的函数和变量。 但是非静态的内部类里,可以调用和定义,静态或非静态的函数和变量。
package com.qicong.gj.c17;
/** * User: 祁大聪 */
public class Outer {
private int age;
public class Inner{
public void doGrow(){
age++;
}
}
//静态的内部类调用非静态的函数?
public static class StaticInner{
private static int height;
public void doGrow(){
// age++;
}
}
public abstract class SubInner extends Inner{
}
public void testInner(){
Inner inner = new Inner();
}
public static void main(String[] args) {
Outer.Inner inner = new Outer().new Inner();
}
}
18 枚举: Java 枚举是特殊的类,可以在枚举中定义属性和函数或构造器。一般用枚举类来定义有限个数,有限数量的常量。 枚举类里都是一个个实例。各个实例用逗号来分隔,最后一个实例用分号分隔。
代码实战:创建Java类时,选择创建enum,创建一周七天的Week enum。里面定义的是一个个 instance (实例),定义两个属性,实例化时调用构造器,定义有两个参数的构造器,在定义的实例中补齐参数。构造器是特殊的函数,把实例的变量赋值给类的变量。 在 text 类中,main 函数中打印枚举类的实例,可以直接打印对象,也可以打印对象的属性,foreach遍历枚举类实例的属性。
package com.qicong.gj.c18;
/** * User: 祁大聪 */
public enum Week {
Mon(1,"星期一"),
Tue(2,"星期二"),
Wed(3,"星期三"),
Thur(4,"星期四")
;
public int no;
public String name;
Week(int no, String name){
this.no = no;
this.name = name;
}
}
package com.qicong.gj.c18;
/** * User: 祁大聪 */
public class TestWeek {
public static void main(String[] args) {
System.out.println(Week.Mon.name);
for (Week w : Week.values()){
System.out.println(w.name + "," + w.no);
}
}
}
19 serializable 关键字:在类的名称后面加上implement serializable 表示可以序列化,反序列化。加上这个关键字:对象可以通过流的形式写到磁盘,实现序列化;也可以将磁盘的数据读成 Java 对象,读到文档当中,实现反序列化。 transient 关键字:在属性的修饰符后加上 transient 的关键字,限制属性写到磁盘和传输出去。
package com.qicong.gj.c19;
import java.io.Serializable;
/** * User: 祁大聪 */
public class Person implements Serializable {
private int age;
private transient String name;
}
20 异常介绍:常见的系统升级,app 升级都是在修复bug。Java程序运行过程中,发生的异常事件可分为两类:错误(error):JVM 系统内部错误,例如,资源耗尽,出现蓝屏。异常(exception):其他编程错误,例如,空指针访问,试图读取不存在的文件,数组越界异常。和偶发的外在因素导致的一般性问题(断网)。 error 和 exception 层次说明:
throwable:error:virtualMachine error(虚拟机异常)包括堆栈异常,内存溢出异常。 exception:读写流异常,文件找不到。和运行时异常。
常见的异常:数学计算异常。造型异常,强转错误。
21 异常捕获:try catch 捕获异常,对异常进行处理,代码可以继续运行,不捕获可以抛出异常,或代码报错程序终止运行。 一段代码可以抛出多个异常,所以一个 try 可以配合多个 catch使用,catch到不同的异常类型,针对性的执行异常对应的代码块, catch捕获异常以后,代码可以继续执行。 有的代码只有一两个地方需要捕获异常,其他的代码看逻辑的紧密程度,选择放到try catch里面或者外面。 文件读完时要把 io 流关闭掉,避免导致内存溢出,用 finally 无条件执行关闭。 如果一段代码有红波浪线,才加上异常捕获。 try catch的快捷键,CTRL+ALT+T。
代码实战:写一个文件路径,用 io 流读取文件,读到byte数组当中。可能会报两个异常 file not found 和 io exception ,写一个假的文件路径和用debug 模式打断点,让try catch去分别捕获异常。(找到文件以后,再读取的代码前打断点,执行到断点就把文件粉碎掉,再接着执行就能报读写异常。)可以sout 演示一下 finally 的强制执行。捕获完异常以后代码能继续执行。
package com.qicong.gj.c21;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/** * User: 祁大聪 */
public class S21 {
public static void testArr(){
try{
int[] arr = {
1,2,3,4,5,6};
System.out.println(arr[2]);//下标最大是5
}catch (Exception e){
e.printStackTrace();
}finally {
System.out.println("finally is called");
}
System.out.println("==================");
} //数组越界异常不会提示
public static void testFile() {
// ctrl + alt + t
FileInputStream fis = null;
try {
String filePath = "E://a.log";
fis = new FileInputStream(filePath);
byte[] b = new byte[1024];
while(fis.read(b) != -1){
}
fis.close();
}catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println("-------------------- FileNotFoundException");
} catch (IOException e) {
e.printStackTrace();
System.out.println("------------------------- IOException");
} finally {
System.out.println("finally is called");
}
System.out.println("==================");
}
public static void main(String[] args) {
testFile();
}
}
22 异常抛出:就是在方法中 throws exception。 当不知道在方法过程中捕获异常以后,如何处理异常(除了打印异常以外不知道如何处理),就可以用抛出替代捕获,让调用该方法的人,在调用这个函数时,去处理可能出现的异常,让使用这个方法的人去try catch。
异常抛出的场景: 在方法中,把系统检查可能会出现的异常抛出,比如,将红波浪线读写异常的警告抛出。 在程序运行的过程中抛出一个自定义的异常,再将抛出的异常显示的写出来。
一般什么异常不抛出: 内存溢出异常,不用抛出自行处理。 空指针异常,判断内容不为空来避免空指针异常。
一般什么异常抛出: 读写异常,句柄错误,系统找不到该文件的异常。
异常的捕获和抛出可以一起使用,可以 throws 多个异常。
package com.qicong.gj.c22;
import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/** * User: 祁大聪 */
public class S22 {
public static void readFile() throws IOException {
String filePath = "E://a.log";
FileInputStream fis = new FileInputStream(filePath);
byte[] b = new byte[1024];
while(fis.read(b) != -1){
}
}
public<