###08.02_面向对象(代码块的面试题)(掌握)
class Student {
static {
System.out.println("Student 静态代码块");
}
{
System.out.println("Student 构造代码块");
}
public Student() {
System.out.println("Student 构造方法");
}
}
class Demo2_Student {
static {
System.out.println("Demo2_Student静态代码块");
}
public static void main(String[] args) {
System.out.println("我是main方法");
Student s1 = new Student();
Student s2 = new Student();
}
}
执行结果:
Demo2_Student静态代码块
我是main方法
Student 静态代码块
Student 构造代码块
Student 构造方法
Student 构造代码块
Student 构造方法
class Demo1_Extends {
public static void main(String[] args) {
Cat c = new Cat();
c.color = "花";
c.leg = 4;
c.eat();
c.sleep();
System.out.println(c.leg + "..." + c.color);
}
}
class Animal {
String color; //动物的颜色
int leg; //动物腿的个数
public void eat() { //吃饭的功能
System.out.println("吃饭");
}
public void sleep() { //睡觉的功能
System.out.println("睡觉");
}
}
class Cat extends Animal {
}
class Dog extends Animal {
}
/*
extends是继承的意思
Animal是父类
Cat和Dog都是子类
*/
A:继承的注意事项
B:什么时候使用继承
采用假设法。
如果有两个类A,B。只有他们符合A是B的一种,或者B是A的一种,就可以考虑使用继承。
class Demo4_Extends {
public static void main(String[] args) {
Son s = new Son();
s.print();
}
}
class Father {
int num1 = 10;
int num2 = 30;
}
class Son extends Father {
int num2 = 20;
public void print() {
System.out.println(this.num1); //this既可以调用本类的,也可以调用父类的(本类没有的情况下)
System.out.println(this.num2); //就近原则,子类有就不用父类的了
System.out.println(super.num2);
}
}
因为子类会继承父类中的数据,可能还会使用父类的数据。
所以,子类初始化之前,一定要先完成父类数据的初始化。
其实:
class Demo5_Extends {
public static void main(String[] args) {
Son s = new Son();
}
}
class Father extends Object {
public Father() {
super();
System.out.println("Father 的构造方法");
}
}
class Son extends Father {
public Son() {
super(); //这是一条语句,如果不写,系统会默认加上,用来访问父类中的空参构造
System.out.println("Son 的构造方法");
}
}
class Demo6_Extends {
public static void main(String[] args) {
Son s1 = new Son();
System.out.println(s1.getName() + "..." + s1.getAge());
System.out.println("--------------------");
Son s2 = new Son("张三",23);
System.out.println(s2.getName() + "..." + s2.getAge());
}
}
class Father {
private String name; //姓名
private int age; //年龄
public Father() { //空参构造
System.out.println("Father 空参构造");
}
public Father(String name,int age) { //有参构造
this.name = name;
this.age = age;
System.out.println("Father 有参构造");
}
public void setName(String name) { //设置姓名
this.name = name;
}
public String getName() { //获取姓名
return name;
}
public void setAge(int age) { //设置年龄
this.age = age;
}
public int getAge() { //获取年龄
return age;
}
}
class Son extends Father {
public Son() { //空参构造
this("王五",25); //本类中的构造方法
//super("李四",24); //调用父类中的构造方法
System.out.println("Son 空参构造");
}
public Son(String name,int age) { //有参构造
super(name,age);
System.out.println("Son 有参构造");
}
}
看程序写结果1
class Fu{
public int num = 10;
public Fu(){
System.out.println("fu");
}
}
class Zi extends Fu{
public int num = 20;
public Zi(){
System.out.println("zi");
}
public void show(){
int num = 30;
System.out.println(num);
System.out.println(this.num);
System.out.println(super.num);
}
}
class Test1_Extends {
public static void main(String[] args) {
Zi z = new Zi();
z.show();
}
}
看程序写结果2
class Fu {
static {
System.out.println("静态代码块Fu");
}
{
System.out.println("构造代码块Fu");
}
public Fu() {
System.out.println("构造方法Fu");
}
}
class Zi extends Fu {
static {
System.out.println("静态代码块Zi");
}
{
System.out.println("构造代码块Zi");
}
public Zi() {
System.out.println("构造方法Zi");
}
}
Zi z = new Zi(); 请执行结果。
/*
1,jvm调用了main方法,main进栈
2,遇到Zi z = new Zi();会先将Fu.class和Zi.class分别加载进内存,再创建对象,当Fu.class加载进内存
父类的静态代码块会随着Fu.class一起加载,当Zi.class加载进内存,子类的静态代码块会随着Zi.class一起加载
第一个输出,静态代码块Fu,第二个输出静态代码块Zi
3,走Zi类的构造方法,因为java中是分层初始化的,先初始化父类,再初始化子类,所以先走的父类构造,但是在执行
父类构造时,发现父类有构造代码块,构造代码块是优先于构造方法执行的所以
第三个输出构造代码块Fu,第四个输出构造方法Fu
4,Fu类初始化结束,子类初始化,第五个输出的是构造代码块Zi,构造方法Zi
*/
class Demo7_Phone {
public static void main(String[] args) {
Ios8 i = new Ios8();
i.siri();
i.call();
}
}
/*
B:方法重写的应用:
* 当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法。这样,即沿袭了父类的功能,又定义了子类特有的内容。
ios7系统 siri speak English
ios8系统 siri 说中文
*/
class Ios7 {
public void call() {
System.out.println("打电话");
}
public void siri() {
System.out.println("speak English");
}
}
class Ios8 extends Ios7 {
public void siri() {
System.out.println("说中文");
super.siri();
}
}
a:父类中私有方法不能被重写
b:子类重写父类方法时,访问权限不能更低
c: 父类静态方法,子类也必须通过静态方法进行重写
子类重写父类方法的时候,最好声明一模一样。
class Demo8_双桨 {
public static void main(String[] args) {
DayOne d = new DayOne();
d.泡妞();
d.print();
}
}
class 双桨 {
public void sing() {
System.out.println("唱红歌");
}
public void 泡妞() {
System.out.println("唱红歌搞定林夕合鸟女士");
}
public static void print() {
System.out.println("Fu print");
}
}
class DayOne extends 双桨 {
public void 泡妞() {
System.out.println("霸王硬上弓");
}
public static void print() { //静态只能覆盖静态,其实不算重写,多态时候详细讲解
System.out.println("Zi print");
}
}
overload可以改变返回值类型,只看参数列表
方法重写:子类中出现了和父类中方法声明一模一样的方法。与返回值类型有关,返回值是一致(或者是子父类)的
方法重载:本类中出现的方法名一样,参数列表不同的方法。与返回值类型无关。
子类对象调用方法的时候:
class Test3_Person {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
class Student {
private String name; //姓名
private int age; //年龄
public Student() {} //空参构造
public Student(String name,int age) { //有参构造
this.name = name;
this.age = age;
}
public void setName(String name) { //设置姓名
this.name = name;
}
public String getName() { //获取姓名
return name;
}
public void setAge(int age) { //设置年龄
this.age = age;
}
public int getAge() { //获取年龄
return age;
}
public void eat() { //吃饭
System.out.println("学生吃饭");
}
public void study() { //学习
System.out.println("学生学习");
}
}
class Teacher {
private String name; //姓名
private int age; //年龄
public Teacher() {} //空参构造
public Teacher(String name,int age) { //有参构造
this.name = name;
this.age = age;
}
public void setName(String name) { //设置姓名
this.name = name;
}
public String getName() { //获取姓名
return name;
}
public void setAge(int age) { //设置年龄
this.age = age;
}
public int getAge() { //获取年龄
return age;
}
public void eat() { //吃饭
System.out.println("老师吃饭");
}
public void teach() { //学习
System.out.println("老师讲课");
}
}
class Test4_Person {
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("张三");
s1.setAge(23);
System.out.println(s1.getName() + "..." + s1.getAge());
s1.eat();
s1.study();
System.out.println("------------------");
Student s2 = new Student("李四",24);
System.out.println(s2.getName() + "..." + s2.getAge());
s2.eat();
s2.study();
}
}
/*
* 使用继承后的学生和老师案例
*/
class Person {
private String name; //姓名
private int age; //年龄
public Person() {} //空参构造
public Person(String name,int age) { //有参构造
this.name = name;
this.age = age;
}
public void setName(String name) { //设置姓名
this.name = name;
}
public String getName() { //获取姓名
return name;
}
public void setAge(int age) { //设置年龄
this.age = age;
}
public int getAge() { //获取年龄
return age;
}
public void eat() { //吃饭
System.out.println(name + "吃饭");
}
}
class Student extends Person {
public Student() {} //空参构造
public Student(String name,int age) {
super(name,age);
}
public void study() {
System.out.println(this.getName() + "学习");
}
}
class Teacher extends Person {
public Teacher() {} //空参构造
public Teacher(String name,int age) {
super(name,age);
}
public void teach() {
System.out.println(this.getName() + "讲课");
}
}
class Demo1_Final {
public static void main(String[] args) {
Son s = new Son();
s.print();
}
}
/*final class Father {
public void print() {
System.out.println("访问底层数据资源");
}
}*/
class Son /*extends Father*/ {
final int NUM = 10; //常量命名规范,如果是一个单词,所有字母大写,如果是多个单词,每个单词都大写,中间用下划线隔开
public static final double PI = 3.14; //final修饰变量叫做常量,一般会与public static共用
public void print() {
//NUM = 20;
System.out.println(NUM);
}
}
方法内部或者方法声明上都演示一下(了解)
修饰基本类型,是值不能被改变
修饰引用类型,是地址值不能被改变,对象中的属性可以改变
class Demo2_Final {
public static void main(String[] args) {
final int num = 10;
//num = 20;
System.out.println(num);
final Person p = new Person("张三",23);
//p = new Person("李四",24);
p.setName("李四");
p.setAge(24);
System.out.println(p.getName() + "..." + p.getAge());
method(10);
method(20);
}
public static void method(final int x) {
System.out.println(x);
}
}
class Person {
private String name; //姓名
private int age; //年龄
public Person(){} //空参构造
public Person(String name,int age) {
this.name = name;
this.age = age;
}
public void setName(String name) { //设置姓名
this.name = name;
}
public String getName() { //获取姓名
return name;
}
public void setAge(int age) { //设置年龄
this.age = age;
}
public int getAge() { //获取年龄
return age;
}
}
class Demo3_Final {
public static void main(String[] args) {
Demo d = new Demo();
d.print();
}
}
class Demo {
final int num; //成员变量的默认初始化值是无效值
public Demo() {
num = 10;
}
public void print() {
System.out.println(num);
}
}
1:代码块是什么?代码块的分类和各自特点?
2:静态代码块,构造代码块,构造方法的执行流程?
3:继承概述
4:继承的好处
5:Java中继承的特点
6:Java中继承的注意事项?以及我们什么时候使用继承?
7:继承中的成员访问特点
A:成员变量
在子类方法中访问一个变量
B:成员方法
在测试类中通过子类对象去访问一个方法
8:继承中构造方法的执行流程?假如父类没有无参构造方法,子类应该怎么办?
9:面试题:
方法重写和方法重载的区别?方法重载能改变返回值类型吗?
Overload
Override
this关键字和super关键字分别代表什么?以及他们各自的使用场景和作用。
10:继承案例练习
11:final关键字可以干什么?有什么特点?
12:final关键字的面试题?
A:修饰局部变量
B:初始化时机
A:为什么要有包
B:包的概述
举例:
学生:增加,删除,修改,查询
老师:增加,删除,修改,查询
…
方案1:按照功能分
com.heima.add
AddStudent
AddTeacher
com.heima.delete
DeleteStudent
DeleteTeacher
com.heima.update
UpdateStudent
UpdateTeacher
com.heima.find
FindStudent
FindTeacher
方案2:按照模块分
com.heima.teacher
AddTeacher
DeleteTeacher
UpdateTeacher
FindTeacher
com.heima.student
AddStudent
DeleteStudent
UpdateStudent
FindStudent
/*
* A:定义包的格式
* package 包名;
* 多级包用.分开即可
* B:定义包的注意事项
* A:package语句必须是程序的第一条可执行的代码
* B:package语句在一个java文件中只能有一个
* C:如果没有package,默认表示无包名
*/
package com.heima;
import com.baidu.Person;
import com.xxx.Student;
//import java.util.Scanner; //在开发中我们用的都是导入具体的类
import java.util.*; //*代表通配符,他会到该包下挨个匹配,匹配上就导入
class Demo1_Package {
public static void main(String[] args) {
Person p = new Person("张三",23);
System.out.println(p.getName() + "..." + p.getAge());
//p.print(); //在不同包下的无关类,不允许访问,因为是protected修饰的
/*Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
System.out.println(x);*/
Student s = new Student("李四",24);
System.out.println(s.getName() + "..." + s.getAge());
s.method();
}
}
本类 同一个包下(子类和无关类) 不同包下(子类) 不同包下(无关类)
private Y
默认 Y Y
protected Y Y Y
public Y Y Y Y
A:修饰符:
B:类:
权限修饰符:默认修饰符,public
状态修饰符:final
抽象修饰符:abstract
用的最多的就是:public
C:成员变量:
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
用的最多的就是:private
D:构造方法:
权限修饰符:private,默认的,protected,public
用的最多的就是:public
E:成员方法:
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
抽象修饰符:abstract
用的最多的就是:public
F:除此以外的组合规则:
class Demo1_InnerClass {
public static void main(String[] args) {
//Inner i = new Inner();
//i.method();
//外部类名.内部类名 = 外部类对象.内部类对象
Outer.Inner oi = new Outer().new Inner(); //创建内部类对象
oi.method();
}
}
class Outer {
private int num = 10;
class Inner {
public void method() {
System.out.println(num);
}
}
}
class Demo2_InnerClass {
public static void main(String[] args) {
//Outer.Inner oi = new Outer().new Inner();
//oi.method();
Outer o = new Outer();
o.print();
}
}
class Outer {
private int num = 10;
private class Inner {
public void method() {
System.out.println(num);
}
}
public void print() {
Inner i = new Inner();
i.method();
}
}
class Demo1_InnerClass {
public static void main(String[] args) {
//外部类名.内部类名 对象名 = 外部类名.内部类对象;
Outer.Inner oi = new Outer.Inner();
oi.method();
Outer.Inner2.print();
}
}
class Outer {
static class Inner {
public void method() {
System.out.println("method");
}
}
static class Inner2 {
public static void print() {
System.out.println("print");
}
}
}
要求:使用已知的变量,在控制台输出30,20,10。
class Outer {
public int num = 10;
class Inner {
public int num = 20;
public void show() {
int num = 30;
System.out.println(?);
System.out.println(??);
System.out.println(???);
}
}
}
class InnerClassTest {
public static void main(String[] args) {
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}
class Test1_InnerClass {
public static void main(String[] args) {
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}
//要求:使用已知的变量,在控制台输出30,20,10。
//内部类之所以能获取到外部类的成员,是因为他能获取到外部类的引用外部类名.this
class Outer {
public int num = 10;
class Inner {
public int num = 20;
public void show() {
int num = 30;
System.out.println(num);
System.out.println(this.num);
System.out.println(Outer.this.num);
}
}
}
class Demo1_InnerClass {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}
//局部内部类
class Outer {
public void method() {
final int num = 10;
class Inner {
public void print() {
System.out.println(num);
}
}
Inner i = new Inner();
i.print();
}
/*public void run() {
Inner i = new Inner(); //局部内部类,只能在其所在的方法中访问
i.print();
}*/
}
new 类名或者接口名(){
重写方法;
}
class Demo1_NoNameInnerClass {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}
interface Inter {
public void print();
}
class Outer {
class Inner implements Inter {
public void print() {
System.out.println("print");
}
}
public void method(){
//Inner i = new Inner();
//i.print();
//new Inner().print();
//Inter i = new Inner(); //父类引用指向子类对象
new Inter() { //实现Inter接口
public void print() { //重写抽象方法
System.out.println("print");
}
}.print();
}
}
class Demo2_NoNameInnerClass {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}
interface Inter {
public void show1();
public void show2();
}
//匿名内部类只针对重写一个方法时候使用
class Outer {
public void method() {
/*new Inter(){
public void show1() {
System.out.println("show1");
}
public void show2() {
System.out.println("show2");
}
}.show1();
new Inter(){
public void show1() {
System.out.println("show1");
}
public void show2() {
System.out.println("show2");
}
}.show2();*/
Inter i = new Inter(){
public void show1() {
System.out.println("show1");
}
public void show2() {
System.out.println("show2");
}
/*public void show3() {
System.out.println("show3");
}*/
};
i.show1();
i.show2();
//i.show3(); //匿名内部类是不能向下转型的,因为没有子类类名
}
}
//这里写抽象类,接口都行
abstract class Person {
public abstract void show();
}
class PersonDemo {
public void method(Person p) {
p.show();
}
}
class PersonTest {
public static void main(String[] args) {
//如何调用PersonDemo中的method方法呢?
PersonDemo pd = new PersonDemo ();
}
}
class Test1_NoNameInnerClass {
public static void main(String[] args) {
//如何调用PersonDemo中的method方法呢?
PersonDemo pd = new PersonDemo ();
//pd.method(new Student());
pd.method(new Person() {
public void show() {
System.out.println("show");
}
});
}
}
//这里写抽象类,接口都行
abstract class Person {
public abstract void show();
}
class PersonDemo {
//public void method(Person p) { //Person p = new Student(); //父类引用指向子类对象
/*
Person p = new Person(){
public void show() {
System.out.println("show");
}
};
*/
public void method(Person p) {
p.show();
}
}
class Student extends Person {
public void show() {
System.out.println("show");
}
}
按照要求,补齐代码
interface Inter { void show(); }
class Outer { //补齐代码 }
class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
}
}
要求在控制台输出”HelloWorld”
class Test2_NoNameInnerClass {
public static void main(String[] args) {
//Outer.method().show(); //链式编程,每次调用方法后还能继续调用方法,证明调用方法返回的是对象
Inter i = Outer.method();
i.show();
}
}
//按照要求,补齐代码
//要求在控制台输出”HelloWorld”
interface Inter {
void show();
}
class Outer {
//补齐代码
public static Inter method() {
return new Inter() {
public void show() {
System.out.println("HelloWorld");
}
};
}
}