//super演示
public class SuperDemo { }
/**
2.继承:
1)作用:有利于代码的重用
2)通过extends实现继承
3)父类:共有的属性和方法
子类:特有的属性和方法
4)子类继承父类后,子类具有:
4.1)父类所共有的
4.2)子类所特有的
5)一个父类可以有多个子类
一个子类只能有一个父类---单一继承
6)继承具有传递性
*/
class Aoo{}
class Boo extends Aoo{}
/**
* 继承中构造方法: *
java规定:构造子类之前必须先构造父类
子类的构造方法中是必须要通过super关键字来调用父类的构造方法的,
这样才可以保证妥善的初始化继承自父类的成员变量。
若自己不写则编译默认默认提供super()调父类的无参构造
若父类没有提供无参的构造方法,则会出现编译错误。
若自己写了则不再默认提供 super()必须位于子类构造的第一句 .
2. 用子类构造来初始化子类对象时,父类构造总会在子类构造之前执行。
3.super:指代当前对象的父类对象
1)super.成员变量名---访问父类的成员变量
2)super.方法名()-----调用父类的方法
3)super()------------调用父类的构造方法
*/
class Foo {
int value;
Foo(int value) {
this.value = value;
}
}
class Goo extends Foo {
int num;
/*
* 有两种解决方案,方案一为在父类中添加无参的构造方法.
* 方案二为在子类构造方法中显示调用父类的有参构造方法(常常使用),
* 这样可以保证父类的成员变量均被初始化,
*/
//Goo(int num) {this.num = num;}//父类没有提供无参的构造方法,则会出现编译错误。
Goo(int value, int num) {
super(value);
this.num = num;
}
}
package oo.day03;
/*
* 向上造型:
* 1)父类型的引用指向子类的对象
* 2)能点出来什么,看引用的类型
*/
//向上造型的演示
public class UpTypeDemo {
public static void main(String[] args) {
Coo o1 = new Coo(); //父只能调父的
o1.c = 1;
o1.show();
Doo o2 = new Doo(); //子既能调子的也能调父的
o2.d = 1;
o2.say();
o2.c = 2;
o2.show();
Coo o3 = new Doo(); //向上造型
o3.c = 1;
o3.show();
/*
* 当用父类型引用指向了子类对象后,java编译器会根据引用的类型(Coo),
* 而不是对象的类型(Doo)来检查调用的方法是否匹配。
*/
//o3.d = 2; //编译错误,能点出来什么,看引用的类型
}
}
class Coo{
int c;
void show(){}
}
class Doo extends Coo{
int d;
void say(){}
}
5.final的演示
/**
final:最终的
1)修饰变量:变量不能被改变
2)修饰方法:方法不能被重写 意义在于:防止子类在定义新方法时造成的“不经意”重写。
3)修饰类: 类不能被继承但是final修饰的类可以继承别的类
*/
//final的演示
public class FinalDemo {public static void main(String[] args) { }}
final class Poo{}
//修饰类: 类不能被继承但是final修饰的类可以继承别的类
//class Qoo extends Poo{} //编译错误,final的类不能被继承
class Roo{}
final class Soo extends Roo{}
//修饰方法:方法不能被重写
class Noo{
void show(){}
final void say(){}
}
class Ooo extends Noo{
void show(){}
//void say(){} //编译错误,final的方法不能被重写
}
/*final可以修饰成员变量,也可以修饰局部变量:
* final修饰成员变量:
* 1)声明同时初始化或者在构造方法中初始化
* final修饰局部变量:
* 1)用之前初始化即可(不用可以不初始化)
*/
//修饰变量:变量不能被改变
class Moo{
final int a = 5;
final int b;
Moo(){
b = 5;
}
void show(){
final int c;
//System.out.println(c); //编译错误,使用之前必须初始化
//a = 55; //编译错误,final的变量不能被改变
}
}
6.package 包名演示
/**
1.package: package 包名;
1)作用:避免类的命名冲突
2)包名可以有层次结构(常常有)
3)类的完全限定名:包名.类名
4)包名建议:所有字母小写
建议: 域名反写 . 项目名称 . 模块名称 . 类名
cn.tedu . tmooc . course .
com.taobao . tts8 . student .
2. import:语法:import 类的全局限定名(即包名+类名);想直接访问 不同包中的类
为了方便起见,在Eclipse中,可以使用“Ctrl+Shift+O”,自动完成import语句。
1)作用:声明类/引入类
2)同包之内的类可以直接访问
3) 不同包中的类,想直接访问:
3.1)先import声明类,再直接访问类
3.2)类的完全限定名---不推荐
3.3)import 包名+*(意味着声明该包中所有类的全称)
3. 访问控制修饰符:封装访问的权限
1)public:公开的,任何类
2)private:私有的,本类
3)protected:受保护的,本类、子类、同包类
4)默认:什么也不写,本类,同包类
说明:
1)类的访问修饰符只能是public和默认的(protected和private访问修饰符可以修饰内部类)
2)类中的成员如上4种修饰符都可以
*/
public class Foo {
public int a; //所有
protected int b; //本,子,同包
int c; //本,同包
private int d; //本
void show(){
a = 1;
b = 2;
c = 3;
d = 4;
}
}
class Goo{ //private
void show(){
Foo o = new Foo();
o.a = 1;
o.b = 2;
o.c = 3;
//o.d = 4;
}
}
/**
重写与重载的区别----常见面试题
1)重写:
1.1)发生在父子类中,方法名相同,参数列表相同,方法体不同
1.2)遵循"运行期绑定",看对象的类型调用方法
2)重载:
2.1)发生在一个类中,方法名相同,参数列表不同
2.2)遵循"编译期绑定",看引用的类型绑定方法
*/
//重写与重载的区别
public class OverrideOverloadDemo {
public static void main(String[] args) {
//重写:看对象的类型 重载:看引用的类型
Eoo eoo = new Eoo();
Coo o = new Doo(); //向上造型
eoo.test(o);==父类型参数 子类--show
}
}
class Coo{
void show(){
System.out.println("父类--show");
}
}
class Doo extends Coo{
void show(){
System.out.println("子类--show");
}
}
class Eoo{
void test(Coo o){
System.out.println("父类型参数");
o.show();
}
void test(Doo o){
System.out.println("子类型参数");
o.show();
}
}
9.static的演示
/**
1.static存在的意义就是不需要实例化某个类就可以调用.
被static修饰的成员变量和成员方法独立于该类的任何对象。
也就是说,它不依赖类特定的实例,被类的所有实例共享。
只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。
因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。
2.静态的存在方法区中,属于类的直到程序停止才消失。静态的可以直接调用静态的,
而非new来访问格式:类名. 静态的不可以直接调用非静态的(实例变量和方法),非
静态可以直接调用静态的。
*/
//static的演示
public class StaticDemo {
public static void main(String[] args) {
Joo o1 = new Joo();
o1.test();//a=1 b=1
Joo o2 = new Joo();
//静态变量:属于类,存在方法区中,只有一份
o2.test();//a=1 b=2
System.out.println(Joo.b); //2 常常通过类名.来访问
System.out.println(o1.b); //2 也可以通过对象.来访问
//Koo.say();
//在类被加载时自动执行,因类只被加载一次, 所以静态块也只执行一次
Loo o3 = new Loo();
Loo o4 = new Loo();
Loo o5 = new Loo();
}
}
10.静态块演示
class Loo{
/**
3)静态块:类实例化或者有静态初始化需求的时候才被加载,JVM加载类时会执行这些静态的代码块。
3.1)由static修饰
3.2)在类被加载时自动执行,因类只被加载一次, 所以静态块也只执行一次
3.3)何时用:常常用于初始化静态资源(图片、音频、视频...)
*/
static{
System.out.println("静态块");
}
Loo(){
System.out.println("构造方法");
}
}
class Koo{
int a;
static int b;
void show(){
a = 1;
b = 2;
}
/**
2)静态方法:
2.1)由static修饰
2.2)属于类,存在方法区中,只有一份
2.3)常常通过类名.来访问
2.4)静态方法没有隐式的this传递,
所以静态方法中不能直接访问实例成员
2.5)何时用:方法的操作仅与参数有关而与对象无关时使用
调用一个静态方法就是“类名.方法名”,静态方法的使用很简单。一般来说,
静态方法常常为应用程序中的其它类提供一些实用工具所用
*/
static void say(){
/*
*静态方法没有隐式this传递,没有this意味着没有对象,
*而实例变量a必须通过对象点来访问,所以此处编译错误
*/
//a = 1; //编译错误
b = 2;
}
}
class Joo{
/**static:静态的
1.静态变量:
1.1)由static修饰
1.2)属于类,存在方法区中,只有一份
1.3)常常通过类名.来访问
1.4)何时用:所有对象数据都一样时使用
2.成员变量:分为实例变量和静态变量
1)实例变量:属于对象的,存在堆中,必须通过对象.来访问
2)静态变量:属于类的,存在方法区中,通过:类名.来访问也可以对象.来访问
3.static变量前可以有private修饰,表示这个变量可以在类的静态代码块中,
或者类的其他静态成员方法中使用(当然也可以在非静态成员方法中使用–废话),
但是不能在其他类中通过类名来直接引用,这一点很重要。
*/
int a;
static int b;
Joo(){
a++;
b++;
}
void test(){
System.out.println("a="+a);
System.out.println("b="+b);
}
}
代码块:
用{}括起来的代码。
根据{}的位置可以分为
局部代码块:方法中,局部位置,作用:限定变量作用范围和生命周期。
构造代码块:在类中方法外(成员位置),用{}括起来的代码。
每次调用构造方法执行前,都会执行构造代码块,
作用:把类中不同构造方法中相同的部分提取出来定义到构造代码块中,以后无论调用哪个构造方法都会执行相同操作。可以理解对对象初始化。
静态代码块:在类中方法外(成员位置),用{}括起来,用static修饰。作用:给类进行初始化。
代码块执行顺序:
静态代码块》构造代码块》构造方法
静态代码块:只执行一次
构造代码块:每次创建该类对象,调用构造方法就执行,先于构造方法。
被JVM装载->执行父类的相关代码->如果有静态初始化,先执行静态初始化,且只执行一次,以后即使有该类实例化,也不会再执行->如果有静态代码块,以与静态初始化一样的方式执行->如果有new语句带来的实例化,先为成员变量分配空间,并绑定参数列表,隐式或显式执行super(),即父类的构造方法,->执行非静态代码块-〉执行本类的构造函数-〉执行其他代码
下面通过一个案例进行解析:
package day08;
public class DaiMaKuai {
static {
System.out.println("大家好我是静态代码块!");
}
{
System.out.println("大家好我是构造代码块!");
}
public DaiMaKuai(){
System.out.println("大家好我是构造方法!");
}
}
public class DaiMaKuaiDemo {
static {
System.out.println("河南科技大学!");
}
public static void main(String[] args) {
System.out.println("洛阳牡丹甲天下!");
//创建DaiMaKuai类对象
System.out.println("-------------------------");
DaiMaKuai dmk = new DaiMaKuai();
System.out.println("-------------------------");
DaiMaKuai dmk1 = new DaiMaKuai();
}
}
输出:
河南科技大学!
洛阳牡丹甲天下!
-------------------------
大家好我是静态代码块!
大家好我是构造代码块!
大家好我是构造方法!
-------------------------
大家好我是构造代码块!
大家好我是构造方法!
11.接口演示
/**
1.接口:也是单根性继承的扩展(类只能继承一个)
1)是一个标准、规范-----制定方 遵守这个标准,就能干某件事-----API后
2)由interface定义:只能包含常量和抽象方法
3)接口不能被实例化
4)接口是需要被实现的,实现类/子类(遵循标准、规范的类):
必须重写接口中的所有抽象方法并且前面必须加public修饰
5)一个类可以实现多个接口,用逗号分隔.若既继承又实现时,应先继承后实现
6)接口可以继承接口
6.1)类和接口之间实现(implements)
6.2)接口和接口之间为继承(extends)
6.3)类和类之间为继承(extends)
2.定义接口语法: interface +接口名{
常量(public static final)可省略也可以写public
抽象方法 (public abstract)可省略
}
*/
public class InterfaceDemo {
public static void main(String[] args) {
//Inter5 o1 = new Inter5(); //编译错误,接口不能被实例化
Foo o2 = new Foo();
Inter6 o3 = new Foo(); //向上造型
Inter5 o4 = new Foo(); //向上造型
}
}
//接口间的继承
interface Inter5{ void a();}
interface Inter6 extends Inter5{ void b();}
class Foo implements Inter6{public void b(){}public void a(){}}
//接口的多实现
interface Inter3{ void a();}
interface Inter4{ void b();}
abstract class Doo{ abstract void c();}
class Eoo extends Doo implements Inter3,Inter4{//先继承后实现
public void a(){}
public void b(){}
void c(){}
}
//接口的实现
interface Inter2{ void a(); void b();}
class Coo implements Inter2{ public void a(){} public void b(){}}
//演示接口的基础语法
interface Inter1{
public static final double PI=3.14159;
public abstract void show();
int NUM=2; //默认public static final
void say(); //默认public abstract
//int num2; //编译错误,默认常量,必须声明同时初始化
//void sayHi(){} //编译错误,默认抽象方法,不能有方法体
}
12.抽象类演示
/**
抽象类:
1)由abstract修饰
2)包含抽象方法的类必须是抽象类
没有抽象方法的类也可以声明为抽象类--我愿意
3)抽象类不能被实例化(new对象)但是可以声明抽象类数组Shape[] shapes = new Shape[4];
4)抽象类都是需要被继承的,子类:
4.1)重写抽象类中的所有抽象方法
4.2)也声明为抽象类---一般不这样做
5)抽象类的意义:
5.1)父类的意义:
5.1.1)封装所有子类共有的属性和方法
5.1.2)为所有子类提供一种公共的类型--向上造型( 抽象类名 引用=new 子类();
5.2)可以包含抽象方法,由子类来做不同的实现,但是入口一样(父类都能点出来/方法名)
*/
abstract class Shape{ //抽象类-不完整
protected double c; //周长
/**
抽象方法:也可以将抽象方法理解为不完整的方法。
1)由abstract修饰
2)只有方法的定义,没有方法的具体实现(连大括号都没有)
*/
public abstract double area(); //抽象方法-不完整
}
class Square extends Shape{
public Square(double c){
this.c = c;
}
public double area(){ //重写--变不完整为完整
return 0.0625*c*c;
}
}
class Circle extends Shape{ //0.0796
public Circle(double c){
this.c = c;
}
public double area(){
return 0.0796*c*c;
}
}
package oo.day05;
//求一组图形中的最大面积
public class ShapeTest {
public static void main(String[] args) {
//Shape s1 = new Shape(); //编译错误,抽象类不能被实例化
Shape[] shapes = new Shape[4]; //创建Shape数组对象
shapes[0] = new Circle(1); //向上造型
shapes[1] = new Circle(2);
shapes[2] = new Square(1);
shapes[3] = new Square(2);
maxArea(shapes);
}
public static void maxArea(Shape[] shapes){ //求最大面积
double max = shapes[0].area(); //最大面积
int maxIndex = 0; //最大面积下标
for(int i=1;i<shapes.length;i++){
double area = shapes[i].area();
if(area>max){
max = area;
maxIndex = i;
}
}
System.out.println("最大面积为:"+max+",所在索引为:"+maxIndex);
}
}
/**
可以总结出如下几点抽象类和接口的区别:
1.一个类只能继承一个抽象类,但可以实现多个接口。
2.抽象类中可以包含抽象方法和非抽象方法,而接口中的所有方法均为抽象的。所以的变量都是常量必须声明时初始化。
3.子类继承抽象类必须实现抽象类中所有抽象方法,否则子类也必须是抽象类。
而子类实现接口则必须实现接口中的所有抽象方法。
设计规则:
1)将公共的属性和行为,抽到父类中
2)所有子类行为都一样,做成普通方法 所有子类行为不一样,做成抽象方法
3)符合既是也是的规则,使用接口(部分子类共有的行为)
4)将程序的任务,流程,步骤写到测试类中
*/
13.static final常量的演示
/**
static final:修饰的成员变量称为常量
1)必须声明同时初始化
2)由类名点来访问,并且不能改变
3)建议:常量名所有字母大写
4)常量在编译期被直接替换为具体的值--效率高可以节约不必要的开支
*/
//static final常量的演示
public class StaticFinalDemo {
public static void main(String[] args) {
System.out.println(Aoo.PI); //通过类名点来访问
//Aoo.PI = 3.1415926; //编译错误,常量不能被改变
/*
1.方法区中加载Boo.class
2.num2存储在方法区中
3.到方法区中获取num2的值并输出
*/
System.out.println(Boo.num2);
//在编译期被直接替换为具体的值,效率高
//相当于System.out.println(100);
System.out.println(Boo.NUM);
}
}
class Boo{
public static final int NUM = 100; //常量
public static int num2 = 200; //静态变量
}
class Aoo{
public static final double PI=3.14159;
//public static final int NUM; //编译错误,必须声明同时初始化
}
14.成员内部类演示
/**
成员内部类:
1)类中套类,里面的称为内部类类称之为Inner,外面的称为外部类称之为Outer
2)内部类通常只服务于外部类,对外不具备可见性(不能实例化在其它类中)
一般情况下,Inner对象会在Outer对象中创建(构造方法或其他方法);
3)内部类对象通常是在外部类中创建
4)内部类中可以直接访问外部类中的成员(包括私有的)
内部类中有一个隐式的引用指代创建它的外部类的对象
外部类名.this.----eg: Mama.this.
*/
//成员内部类演示
public class InnerClassDemo {
public static void main(String[] args) {
Mama m = new Mama();
//Baby b = new Baby(); //编译错误,内部类对外不具备可见性
}
}
class Mama{
private String name;
Baby createBaby(){
Baby b = new Baby();
return b;
}
class Baby{
void showMamaName(){
System.out.println(name);
System.out.println(Mama.this.name);
//System.out.println(this.name); //this为当前对象,即Baby类对象,而Baby类没有name属性
}
}
}
15.多态的演示
/**
1.多态:(都造了型向上造型)
1)多态的意义:
1.1)同一类型的引用指向不同对象时,有不同的实现 ----行为的多态: cut()
1.2)同一个对象被造型为不同类型时,有不同的功能 ----对象的多态: 我
2)向上造型:
2.1)父类型的引用指向子类的对象
2.2)能向上造型为的类型: 父类、所实现的接口
2.3)能点出来什么,看引用的类型 重写方法被调用时,看对象的类型
3)强制类型转换,成功的条件:
3.1)引用所指向的对象,就是该类型
3.2)引用所指向的对象,实现了该接口
4)强转若不符合如上两个条件,则发生类型转换异常,(Class cast Exception)
建议:强转之前先通过instanceof来判断,而后再强转
instanceof判断引用的对象是否是某类型,返回boolean型结果
强转成功的条件就是它为true的条件
cut()行为就是多态的
人 p1 = new 理发师();
人 p2 = new 外科医生();
人 p3 = new 演员();
p1.cut(); //剪发
p2.cut(); //开刀
p3.cut(); //停止表演
abstract class 人{
abstract cut();
}
class 理发师{
cut(){ 剪发 }
}
class 外科医生{
cut(){ 开刀 }
}
class 演员{
cut(){ 停止表演 }
}
*/
//多态的演示
public class MultiTypeDemo {
public static void main(String[] args) {
Aoo o1 = new Boo(); //向上造型
Boo o2 = (Boo)o1; //o1指向的对象就是Boo类型
Inter1 o3 = (Inter1)o1; //o1指向的对象实现了Inter1接口
//Coo o4 = (Coo)o1; //类型转换异常
if(o1 instanceof Coo){ //false
Coo o5 = (Coo)o1;
}
}
}
interface Inter1{}
class Aoo{}
class Boo extends Aoo implements Inter1{}
class Coo extends Aoo{}
水作为不同形态时,所能干的事也是不一样的
我这个对象是多态的
我 me = new 我();
讲师 o1 = me; //向上造型
孩子他妈 o2 = me;
老公的老婆 o3 = me;
o1.讲课();
o2.揍他();
o3.咬他();
o3.收工资();
interface 讲师{ 讲课();}
interface 孩子他妈{ 揍他();}
interface 老公的老婆{ 咬他(); 收工资();}
class 我 implements 讲师,孩子他妈,老公的老婆{ 讲课(){} 揍他(){} 咬他(){} 收工资(){}}
run()行为也是多态的
动物 a1 = new 老虎();
动物 a2 = new 鱼();
动物 a3 = new 鸟();
a1.run();
a2.run();
a3.run();
abstract class 动物{ abstract run();}
class 老虎 extends 动物{ run(){ 在地上跑 }}
class 鱼 extends 动物{ run(){ 在水里游 }}
class 鸟 extends 动物{ run(){ 在天上飞 }}
cut()行为就是多态的
人 p1 = new 理发师();
人 p2 = new 外科医生();
人 p3 = new 演员();
p1.cut(); //剪发
p2.cut(); //开刀
p3.cut(); //停止表演
16.匿名内部类演示
/**
匿名内部类:
1.如果在一段程序中需要创建一个类的对象(通常这个类需要实现某个接口或者继承某个类),
而且对象创建后,这个类的价值也就不存在了,这个类可以不必命名,称之为匿名内部类。
1)想创建一个类的对象,并且对象只创建一次, 该类不必命名,称之为匿名内部类
2)匿名内部类中访问外面的变量,该变量必须是final的
3)内部类有独立的.class
2.匿名内部类的结构:Inter2 o2 = new Inter2(){ };
2.1)用匿名类所实现的接口或所继承的父类类型声明的引用;
2.2)new 后面的为匿名类所要实现的接口或继承的父类;
2.3)小括号()中为构造方法参数;
2.4)大括号中为匿名中定义的成员变量或方法。
(如果父类中有抽象方法子类必须重写抽象方法)
*/
//匿名内部类演示
public class NstClassDemo {
public static void main(String[] args) {
//Inter2 o1 = new Inter2(); //编译错误,接口不能被实例化
/**
1.创建了Inter2的一个子类,没有名字
2.为该子类创建了一个对象,名为o1
3小括号()中为构造方法参数
4.大括号中的为子类的类体(为匿名中定义的成员变量或方法。)
*/
Inter2 o1 = new Inter2(){ };
//1.创建了Inter2的一个子类,没有名字
//2.为该子类创建了一个对象,名为o2
//3.大括号中的为子类的类体
Inter2 o2 = new Inter2(){
};
final int num=250;
/*o3为Inter3子类的对象
* run()为Inter3子类的方法
*/
Inter3 o3 = new Inter3(){
public void run(){
System.out.println("abc");
System.out.println(num); //num必须是final的
}
};
/*o3为Inter3子类的对象,run()为Inter3子类的方法
* o3.run()为调用子类的方法
*/
o3.run();
}
}
interface Inter3{ public void run();}
interface Inter2{}
/**
4.面向对象三大特征:封装、继承、多态
1)封装:
1.1)类:封装对象的属性和行为
1.2)方法:封装具体的功能的实现
1.3)访问控制修饰符:封装访问的权限
2)继承:
2.1)作用:有利于代码的复用
2.2)父类/基类:共有的
子类/派生类:特有的
2.3)子继承父后,具有:父的+子的
3)多态:
3.1)意义:行为的多态、对象的多态
3.2)向上造型、强制类型转换、instanceof
3.3)表现形式:
重写、重载
*/