day10
01_private关键字
封装手机类测试
/*
按照刚才写法,完成手机类测试
手机类:
品牌brand,价格price,颜色color--->属性加入私有修饰!
打电话callPhone(),发短信sendMsg()
在PhoneTest中进行 手机类的测试,给属性赋值,并且调用成员方法,打印信息!
*/
//定义一个手机类
classPhone{
//属性私有化
privateStringbrand ; //品牌
privateintprice ; //价格
privateStringcolor ; //颜色
//对外提供公共setXXX(赋值的参数)/getXXX()
//给品牌赋值
publicvoidsetBrand(Stringb){ //"华为p40"
brand=b;
}
//获取品牌的值
publicStringgetBrand(){
returnbrand ;
}
//给价格赋值
publicvoidsetPrice(intp){//6799
price=p ;
}
//获取价格的值
publicintgetPrice(){
returnprice ;
}
//给颜色赋值
publicvoidsetColor(Stringc){ //"天空灰"
color=c ;
}
//获取颜色的值
publicStringgetColor(){
returncolor ;
}
//其他成员方法
publicvoidcallPhone(){
System.out.println(brand+"可以打电话了") ;
}
publicvoidsendMsg(StringtoName){
System.out.println("给"+toName+"可以发短信了") ;
}
}
//手机类的测试类
classPhoneTest{
publicstaticvoidmain(String[] args){
//创建手机类对象
Phonep=newPhone() ;
p.setBrand("华为p40") ;
p.setPrice(6799) ;
p.setColor("天空灰") ;
System.out.println(p.getBrand()+"---"+p.getPrice()+"---"+p.getColor()) ;
p.callPhone() ;
p.sendMsg("高圆圆") ;
}
}
private关键字的特点
/*
private关键字的特点:
1)被private修饰的成员变量/成员方法(非静态),
只能在本类中访问,外界类不能访问!
2)虽然被私有修饰的成员变量以及成员方法(非静态)不能直接访问,但是
都可以间接的通过"public"公共访问访问!
*/
//定义Demo类
classDemo{
//成员变量:类中方法外
publicintnum=10 ;
privateintnum2=20 ;
//定义一个公共的方法
publicvoidshow(){
System.out.println(num) ; //10
System.out.println(num2) ;//20
}
//其他成员方法
publicvoidmethod(){
System.out.println("method Demo") ;
System.out.println("-------------------------") ;
function() ;
}
//私有的成员方法
privatevoidfunction(){
System.out.println("function Demo") ;
}
}
//测试类
classPrivateDemo{
publicstaticvoidmain(String[] args){
//需求:访问Demo类中num和num2变量?
//创建Demo类对象
Demod =newDemo() ;
System.out.println(d.num) ;
System.out.println("---------------------------") ;
//System.out.println(d.num2) ; //num2 在 Demo 中是 private 访问控制
//要访问num2这个变量:间接访问了
d.show() ;
d.method() ;
//d.function() ; // function() 在 Demo 中是 private 访问控制
}
}
学生封装例子
/*
学生有姓名,年龄两个属性;
将姓名和年龄属性私有化,加入private,外界类不能直接使用(保证数据的安全性!)
定义一个学生类,然后在StudentTest中进行测试,成员变量赋值,打印成员信息;
封装:
一个事物的私有化(private),外界类不能直接使用,
对外需要通过公共的访问setXXX(参数)/getXXX()赋值(成员变量赋值)
获取值(获取成员变量的值)
*/
//学生类
classStudent{
//属性私有化:全部private
privateStringname ; //姓名
privateintage ; //年龄
//对外提供公共的访问方法setXXX()/getXXX():才能赋值/获取值
//1)给成员变量 name赋值
publicvoidsetName(Stringn){ //"高圆圆" n:局部变量
name=n ;
}
//获取成员变量name 的值
publicStringgetName(){
returnname ; //成员变量
}
//2)给成员变量 年龄age赋值
publicvoidsetAge(inta){//44 a:局部变量
age=a ; //44
}
publicintgetAge(){
returnage ;
}
//成员方法:学习
publicvoidstudy(){
System.out.println(name+"正在学习JavaSE") ;
}
}
//学生类的测试类
classStudentTest{
publicstaticvoidmain(String[] args){
//类名 对象名 = new 类名() ; //创建一个学生
Students=newStudent() ;
//对象名.成员变量 = 赋值;
//s.name = "高圆圆" ;//name 在 Student 中是 private 访问控制
//访问setXXX(xxx)/getXXX()
s.setName("高圆圆") ;
s.setAge(44) ;
System.out.println("该学生的姓名是:"+s.getName()+
",年龄是:"+s.getAge()) ;
//其他成员方法
s.study() ;
}
}
02一个标准类的写法加入private_this
/*
手机类:
品牌brand,价格price,颜色color--->属性加入私有修饰!
打电话callPhone(),发短信sendMsg()
在PhoneTest中进行 手机类的测试,给属性赋值,并且调用成员方法,打印信息!
(加入this:局部变量给成员变量赋值,局部变量--见名知意)
*/
//定义一个手机类
classPhone{
//成员变量
privateStringbrand ;
privateintprice ;
privateStringcolor ;
//setXXX(xx)赋值
publicvoidsetBrand(Stringbrand){ //局部变量
this.brand=brand ;
}
publicvoidsetPrice(intprice){
this.price=price ;
}
publicvoidsetColor(Stringcolor){
this.color=color ;
}
//getXXX()获取值
publicStringgetBrand(){
returnbrand ;
}
publicintgetPrice(){
returnprice ;
}
publicStringgetColor(){
returncolor ;
}
}
//测试类
classPhoneTest{
publicstaticvoidmain(String[] args){
//使用 类 对象名 = new 类名() ;
Phonep=newPhone() ;
p.setBrand("华为p40") ;
p.setPrice(4599) ;
p.setColor("翡翠绿") ;
System.out.println(p.getBrand()+"---"+p.getPrice()+"---"+
p.getColor()) ;
}
}
学生类加入this关键代码改进
/*
学生有姓名,年龄两个属性;
将姓名和年龄属性私有化,加入private,外界类不能直接使用(保证数据的安全性!)
定义一个学生类,然后在StudentTest中进行测试,成员变量赋值,打印成员信息;
按需上面的测试:
通过setXXX(xx)给成员变量赋值,问题:变量并没有"见名知意"
给成员变量name/age进行赋值,局部变量名称也是name,age;
优化之后:成员变量 姓名name ,年龄age 都赋值不了
原因:局部变量名称 和成员变量名称一致,导致出现的问题;
Java提供了一个关键字:(局部变量名称隐藏了成员变量名称)this--->
代表当前类的对象的地址值引用!
this.成员变量名 = 局部变量名;
*/
//学生类
classStudent{
//属性私有化:全部private
privateStringname ; //姓名
privateintage ; //年龄
//对外提供公共的访问方法setXXX()/getXXX():才能赋值/获取值
//1)给成员变量 name赋值
//public void setName(String n){ //"高圆圆" n:局部变量
//name = n ;
//}
//优化
publicvoidsetName(Stringname){//"高圆圆"
//name = name ;错误的
this.name=name ;
}
//获取成员变量name 的值
publicStringgetName(){
returnname ; //成员变量
//return this.name ; //this可以省略
}
//2)给成员变量 年龄age赋值
/*
public void setAge(int a){//44 a:局部变量
age = a ; //44
}
*/
//优化
publicvoidsetAge(intage){
//age = age ;//错误的
this.age=age ;
}
publicintgetAge(){
//return this.age ;//this可以省略
returnage ;
}
//成员方法:学习
publicvoidstudy(){
System.out.println(name+"正在学习JavaSE") ;
}
}
//测试类
classStudentTest{
publicstaticvoidmain(String[] args){
//测试学生类
Students=newStudent() ;
s.setName("高圆圆") ;
s.setAge(44) ;
System.out.println(s.getName()+"---"+s.getAge()) ;
}
}
0_3成员变量和局部变量的区别
面试题
/*
面试题:(理解并去识记)
局部变量和成员变量的区别?
区别:
1)类中的书写位置不同
成员变量:在类中,方法外
局部变量:在方法定义中或者方法声明上
2)jvm内存位置不同
成员变量:在堆内存中
局部变量:在栈内存中
3)生命周期不同:
成员变量:随着对象的创建而存在,随着对象的创建完毕并且使用完
等待垃圾回收器回收(不会立即回收)而消失!
局部变量:随着方法调用而存在,随着方法调用结束而消失
4)初始化值不同:
成员变量:存在系统默认初始化,也可以显示初始化
局部变量:总之:在使用局部变量之前,必须赋值,不赋值不行!
*/
//定义一个类Variable
classVariable{
//成员变量
intnum ; //系统默认初始化就是0
publicvoidshow(Stringy){ //y
//int x = 100 ; //x 局部变量
intx ;
x=100 ;
System.out.println(x+y) ;
}
}
//测试类
classVariableDemo{
publicstaticvoidmain(String[] args){
//访问show方法
//创建Variable类对象
Variablev=newVariable() ;
System.out.println(v.num) ;
v.num=100 ;
System.out.println(v.num) ;
v.show("hello") ;
}
}
04引入构造方法
/*
一个类的成员:
成员变量
成员方法(非静态)
构造方法:
什么是构造方法?
1)方法名和类名一致
2)没有具体返回值类型
3)连void都没有
构造方法是可以重载!
构造方法的作用:
给类的成员进行数据初始化!
注意事项:
1)一个类中,如果没有任何构造方法,那么系统(jvm)自动会给我们提供无参构造方法!
2)一个类中,只提供有参构造方法,那么系统不会无参构造方法,此时,建议我们永远给出无参构造方法!否则,就出现问题!
创建对象的时候固定格式:
类名 对象名 = new 类名() ;
*/
classStudent{//学生类
//带两个参数
privateStringname ;//姓名
privateintage ; //年龄
/*
1)方法名和类名一致
2)没有具体返回值类型
3)连void都没有
*/
//无参构造方法
/*
public Student(){
System.out.println("这是Student的无参构造方法") ;
}
*/
//带有一个String类型的参数的构造方法
publicStudent(Stringname){ //姓名:局部变量---成员变量
System.out.println("这是一个带有String参数的构造方法") ;
this.name=name ;
}
//带有String类型,以及int类型的构造方法
publicStudent(Stringname,intage){
System.out.println("这是一个带两个参数的构造方法") ;
}
}
//测试类
classConstructorDemo{
publicstaticvoidmain(String[] args){
//创建一个学生类对象
Students=newStudent();
System.out.println(s) ;//堆内存地址
System.out.println("-------------------") ;
Students2=newStudent("高圆圆") ;
System.out.println(s2) ;//新的堆内存空间
System.out.println("-------------------") ;
//在创建第三个学生对象
Students3=newStudent("高圆圆",44) ;
System.out.println(s3) ;
}
}
手机类加入构造方法的优化
/*
手机类:
品牌brand,价格price,颜色color--->属性加入私有修饰!
打电话callPhone(),发短信sendMsg()
在PhoneTest中进行 手机类的测试,给属性赋值,并且调用成员方法,打印信息!
(加入this:局部变量给成员变量赋值,局部变量--见名知意)
一个标准类的写法:
类的成员
成员变量:属性私有化
成员方法:公共访问setXXX(xx)/getXXX()
构造方法:无参构造方法:永远给出
有参构造方法
*/
//定义一个手机类
classPhone{
//成员变量
privateStringbrand ;
privateintprice ;
privateStringcolor ;
//无参构造方法
publicPhone(){
}
//有参构造方法
publicPhone(Stringbrand,intprice ,Stringcolor){ //"Iphone14",12999,"土豪金"
//局部变量给成员变量赋值
this.brand=brand ;
this.price=price ;
this.color=color ;
}
//setXXX(xx)赋值
publicvoidsetBrand(Stringbrand){ //局部变量
this.brand=brand ;
}
publicvoidsetPrice(intprice){
this.price=price ;
}
publicvoidsetColor(Stringcolor){
this.color=color ;
}
//getXXX()获取值
publicStringgetBrand(){
returnbrand ;
}
publicintgetPrice(){
returnprice ;
}
publicStringgetColor(){
returncolor ;
}
}
//测试类
classPhoneTest{
publicstaticvoidmain(String[] args){
//使用 类 对象名 = new 类名() ;
//无参构造方法+setXXX(xx)+getXXX()
Phonep=newPhone() ;
p.setBrand("华为p40") ;
p.setPrice(4599) ;
p.setColor("翡翠绿") ;
System.out.println(p.getBrand()+"---"+p.getPrice()+"---"+
p.getColor()) ;
System.out.println("-----------------------") ;
//方式2:手机类的有参构造方法+getXXX()
/*
public Phone(String brand,int price ,String color){
//局部变量给成员变量赋值
this.brand = brand ;
this.price = price ;
this.color = color ;
}
*/
Phonep2=newPhone("Ipho
ne14",12999,"土豪金") ;
System.out.println(p2.getBrand()+"---"+p2.getPrice()+"---"+
p2.getColor()) ;
}
}
day12
static静态关键字
packagecom.qf.static_01;
/**
* 关于static关键字--->被多个对象"共享,共用"的意思
*
*
* 特点:
* 1)被static修饰的成员(变量/方法)随着类的加载而加载,优先于对象存在! (对象创建: 类名 对象名 = new 类名() ;)
* 某个类要先被编译产生-->类名.class--->类在运行的时候,加载过程要将静态的成员都先进入方法区的静态区中!
* 2)static和this不能共存!
* this:代表是当前类对象的地址值引用---说明对象创建完毕,才能使用this.变量名 -->访问成员变量 (对象成员)
* static:随着类的加载而加载,被static修饰的成员--->"类成员"
* 3)如果有一个变量体现出被共享,被共用--->此时用"static"修饰
*
* 举例:
* 水杯中的水 (不行)
* 饮水机的水(可以被共享)
* 4)访问方式:(必须记住)
* 类成员--->被static修饰的,特有访问 方式
* 类名.变量名; //在访问本类中静态变量
* 类名.方法名() ;//在访问本类中的静态方法
*
* 注意:
* 我们所说的成员变量/成员方法---->默认 非静态的!
*
*/
//定义一个Demo类
classDemo{
//定义一个非静态成员变量
publicintnum=100 ;
//静态的变量(静态成员变量)
publicstaticintnum2=50 ;
//非静态的成员方法
publicvoidmethod(){
System.out.println("method Demo...");
}
//静态的成员方法(类方法)
publicstaticvoidfunction(){
System.out.println("function Demo...");
// method() ; //这个方法非静态的
// System.out.println(num);
// System.out.println(num2) ;
}
}
//测试类
publicclassStaticDemo {
publicstaticvoidmain(String[] args) {
//需求:要访问Demo类中num和num2这个变量?
//创建Demo类对象
Demod=newDemo() ;
System.out.println(d.num) ;
//System.out.println(d.num2) ; //可以访问,不建议这种方式
System.out.println(Demo.num2);//静态--都被类名访问
System.out.println("------------------------------------") ;
//访问method方法
d.method();
// d.function() ;//可以访问,不建议这种方式
Demo.function(); //访问静态方法
//jdk提供的Math:针对数学运算的工具类
//double random = Math.random();//静态发那个发
}
}
static的使用注意事项
packagecom.qf.static_01;
/**
*静态static的使用注意事项:
* 1)非静态的成员方法里面,皆可以访问静态的变量/方法,也可以访问非静态的变量/方法!
*
* 2)静态的方法只能访问静态的成员,不能访问静态的
*
*
* 记住: 静态只能访问静态!
*/
//定义类Code
classCode{
//非静态变量
publicintx=10 ;
//静态变量:
publicstaticinty=20 ;
//非静态的成员方法
publicvoidshow(){
//访问x
System.out.println(x) ;
//静态变量
System.out.println(y) ;
}
//静态方法
publicstaticvoidfunction(){
System.out.println("function Code...");
}
//静态的方法
publicstaticvoidmethod() {
//访问非静态变量x
// System.out.println(x) ;
//访问静态的变量y
System.out.println(y);
System.out.println("-------------下面调用方法了--------------");
//show() ; //非静态方法
function();//静态方法
}
}
//测试类
publicclassStaticDemo2 {
publicstaticvoidmain(String[] args) {
//创建Code类对象
Codecode=newCode() ;
code.show();
System.out.println("------------------------------");
//直接调用静态方法
Code.method();
Code.function();
System.out.println("------------------------------");
//int add = sum(10,20) ;
}
/*public static int sum(int a,int b){
return a+b ;
}*/
}
static的举例
packagecom.qf.static_01;
/**
*静态static的使用注意事项:
* 1)非静态的成员方法里面,皆可以访问静态的变量/方法,也可以访问非静态的变量/方法!
*
* 2)静态的方法只能访问静态的成员,不能访问静态的
*
*
* 记住: 静态只能访问静态!
*/
//定义类Code
classCode{
//非静态变量
publicintx=10 ;
//静态变量:
publicstaticinty=20 ;
//非静态的成员方法
publicvoidshow(){
//访问x
System.out.println(x) ;
//静态变量
System.out.println(y) ;
}
//静态方法
publicstaticvoidfunction(){
System.out.println("function Code...");
}
//静态的方法
publicstaticvoidmethod() {
//访问非静态变量x
// System.out.println(x) ;
//访问静态的变量y
System.out.println(y);
System.out.println("-------------下面调用方法了--------------");
//show() ; //非静态方法
function();//静态方法
}
}
//测试类
publicclassStaticDemo2 {
publicstaticvoidmain(String[] args) {
//创建Code类对象
Codecode=newCode() ;
code.show();
System.out.println("------------------------------");
//直接调用静态方法
Code.method();
Code.function();
System.out.println("------------------------------");
//int add = sum(10,20) ;
}
/*public static int sum(int a,int b){
return a+b ;
}*/
}
package com.qf.static_02;
/**
* 定义数组工具类ArrayTool
* 工具类中方法都是静态的,而且构造方法私有的
*
*/
public class ArrayTool {
//提供无参构造方法,无参构造私有化---目的就是为了让外界类不能创建对象!
private ArrayTool(){}
//遍历功能--->全部加入static
public static void printArray(int[] array){
System.out.print("[") ;
//遍历数组
for (int i = 0; i < array.length; i++) {
if(i == array.length-1){
System.out.println(array[i]+"]");
}else{
System.out.print(array[i]+", ");
}
}
}
}
static例子的改写
packagecom.qf.static_03;
importjava.lang.reflect.Array;
/**
* 需求:
* 已知一个数组,静态初始化,给数组中加入遍历功能,进行测试!
* 从最早开始定义方法--->面向对象的访问方式的过程!
*
*
* 自定义一个类工具类,构造方法私有化,对外提供静态的功能,对这个工具类产生 "文档说明书"
* 找到ArrayTool.java文件所在的目录
* 在dos窗口中输入指令
* javadoc -d 目录名称 -author -version java源文件名称 (前提条件是这个ArrayTool类必须是public修饰)
*
* 举例:
* javadoc -d doc -author -version ArrayTool.java
*
*
*
*/
//测试类
publicclassArrayTest {
publicstaticvoidmain(String[] args) {
//已知一个数组,静态初始化
int[] arr= {54,87,29,32,13} ;
//调用ArrayTool类的所有静态功能
intmax=ArrayTool.getArrayMax(arr);
System.out.println("最大值是:"+max);
System.out.println("------------------------------");
ArrayTool.bubleSort(arr) ;
//遍历
ArrayTool.printArray(arr );
System.out.println("-------------------------------");
ArrayTool.reverseArray(arr);
//遍历
ArrayTool.printArray(arr);
System.out.println("--------------------------------");
//逆序值,查询13这个元素第一次出现的角标
intindex=ArrayTool.getIndex(arr, 13);
System.out.println(index);
intindex2=ArrayTool.getIndex(arr,300) ;
System.out.println(index2);
}
}
packagecom.qf.static_03;
/**
* ArrayTool这个类是自定义针对数组操作的工具类
* 里面提供了数组遍历,求数组最值,查询指定元素第一次索引值,逆序,冒泡排序等等这些功能
* @author 高圆圆
* @version V1.0
* */
publicclassArrayTool {
//提供无参构造方法,无参构造私有化---目的就是为了让外界类不能创建对象!
privateArrayTool(){}
/**
* 这功能是对数组进行遍历的功能,
* 最终数组以[元素1, 元素2, 元素3, ...元素n]形式出现
* @param array 传递的数组
*
* */
public static voidprintArray(int[] array){
System.out.print("[") ;
//遍历数组
for (inti=0; i<array.length; i++) {
if(i==array.length-1){
System.out.println(array[i]+"]");
}else{
System.out.print(array[i]+", ");
}
}
}
/**
*该方法是针对数组的求最大值的功能
* @param array 指定数组
* @return 返回值是表示数组中出现的最大值
* */
publicstaticintgetArrayMax(int[] array){
//定义中参照物
intmax= array[0] ;
for(intx=1 ; x<array.length ;x++){
if(array[x] >max){
max=array[x] ;
}
}
return max ;
}
/**
* 该功能是查询数组中的元素第一次出现索引值
* @param array 需要在指定数组中查询
* @param key 要查询指定的数组中的元素
* */
publicstaticintgetIndex(int[] array,intkey){
//假设
intindex=-1 ;
//遍历数组
for(intx=0 ; x<array.length ; x++){
if(key==array[x]){
index=x ;
break ;
}
}
return index ;
}
/***
* 该功能是针对数组进行冒泡排序,两两比较,将较大的值往后放,
* 第一次比较完毕,最大值出现在最大索引处!
* @param array 要输入指定数组进行冒泡排序
*/
publicstaticvoidbubleSort(int[] array){
for(intx=0 ;x<array.length-1 ;x++){
for(inty=0 ; y<array.length-1-x;y++){
if(array[y] >array[y+1]){
inttemp=array[y] ;
array[y] =array[y+1] ;
array[y+1] =temp ;
}
}
}
}
/***
* 该功能是将数组逆序,将第一个元素和最后一个元素进行互换,第二个元素和倒数第二个元素互换
* 依次这样操作,将数组逆序
* @param array 传入指定数组进行逆序
*/
publicstaticvoidreverseArray(int[] array){
for(intstart=0 ,end=array.length-1 ;start<end ;start++,end--){
inttemp=array[start] ; //array[0]
array[start] =array[end] ; //array[array.lengtt-1]
array[end] =temp ;
}
}
}
java中的代码块
packagecom.qf.code_04;
importcom.sun.xml.internal.ws.addressing.WsaActionUtil;
/**
*什么是Java中的代码块?
*
* Java中的代码块是一个{}包裹起来的内容!
* 分类:
* 局部代码块--->方法定义中 作用:限定局部变量的生命周期
* 构造代码块--->类的成员位置定义的{}
* 作用:在执行构造方法之前,如果存在构造代码块,先执行构造代码块,
* 然后在执行构造方法 ,就是给数据进行初始化的!
* 静态代码块--->类的成员位置定义的
* static{
*
* }
* 特点:跟类相关,类一加载,先执行,而且只执行一次(因为类就加载一次)
* 优先级最大
*
*
*
* 优先级:
* 静态代码块 > 构造代码块 > 构造方法!
*
*/
//定义一个Code类
classCode {
//静态代码块
static{
intx=1000 ;
System.out.println(x) ;
}
publicCode() {
System.out.println("code的无参构造方法");
}
//构造代码块
{
intx=100 ;
System.out.println(x) ;
}
//构造代码块
{
inty=200;
System.out.println(y);
}
//有参构造
publicCode(Stringname){
System.out.println("code"+name) ;
}
static{
inty=2000 ;
System.out.println(y) ;
}
}
//测试类
publicclassCodeDemo {
publicstaticvoidmain(String[] args) {
//方法中 {},局部代码块
/* {
int x = 100 ;
System.out.println(x) ;
}*/
//System.out.println(x);
// System.out.println("------------------------------") ;
//创建Code类的对象---无参构造方法创建
Codecode=newCode() ;
System.out.println("------------------") ;
Codecode2=newCode("helloworld") ;
}
}
代码块的面试题
packagecom.qf.code_04;
/**
*看程序,写结果
*
* 优先级
* 静态代码块 > 构造代码块 > 构造方法
*/
classStudent{
static{
System.out.println("Student的静态代码块1");
}
publicStudent(){
System.out.println("Student的无参构造方法");
}
{
System.out.println("student的构造代码块1");
}
publicStudent(Stringname){
System.out.println("Student的有参构造方法"+name);
}
static{
System.out.println("Student的静态代码块2");
}
{
System.out.println("student的构造代码块2");
}
}
publicclassMainTest {
static{
System.out.println("MainTest的静态代码块");
}
publicstaticvoidmain(String[] args) {
Students=newStudent() ;
Students2=newStudent("高圆圆") ;
}
}
继承(重点)
继承的概念
packagecom.qf.extends_05;
/**
* 继承的概念:
* 将多个类的共性内容抽取到一个独立的类中,这个独立的类和这多个类产生一种关系 "继承"
*
* 继承的格式:
* class 父类名{}
* class 子类名 extends 父类名{}
*
* 继承的好处:
* 1)可以提高代码的复用性
* 2)可以增强代码的后期维护
* 3)类与的类关系:继承关系 是多态的前提条件!
*
*
* 使用"继承"的时机:什么时候使用继承?
*
* class A{
* public void show(){}
* public void show2(){}
* }
* class B{
* //public void show(){}
* public void show3(){}
* }
*
* ---->优化 class B extends A{}
* 不能为了使用部分功能就使用继承!
* 使用继承的前提条件:
* 如果一个类A是类B一种,或者是类B是类A的一种,才能使用继承,继承的核心思想体现出一种"is a"的关系
* 举例:
* 水果:
* 橘子
* 苹果
* 西瓜..
* 人:
* 工人
* 学生
* 军人
* 老师....
*
* 实际开发中:
* 所有的开发原则都必须遵循 "低耦合,高内聚"
*
* 耦合:类和类的关系越少越好,耦合性只能降低,不能避免!
* 内聚:解决某件事情(功能)的执行力!(一个类能够完成的尽量一个类完成,不能产生过多关系!)
*
*/
//没有使用继承之前
//学生类
/*class Student{
//学生要学习
public void study(){
System.out.println("任何人都要学习");
}
//学累了就要休息
public void sleep(){
System.out.println("学习困了就需要休息");
}
}
//老师类
class Teacher{
//学习
//学生要学习
public void study(){
System.out.println("任何人都要学习");
}
//学累了就要休息
public void sleep(){
System.out.println("学习困了就需要休息");
}
}*/
//将共性内容抽取到独立类中
//使用继承
classPerson{ //人
//学生要学习
publicvoidstudy(){
System.out.println("任何人都要学习");
}
//学累了就要休息
public voidsleep(){
System.out.println("学习困了就需要休息");
}
}
//定义学生类
classStudentextends Person{}
//定义老师类
classTeacherextends Person{}
//测试类
publicclassExcetendsDemo {
publicstaticvoidmain(String[] args) {
//测试
//创建学生类对象
Students=newStudent() ;
s.study();
s.sleep();
System.out.println("--------------------------------") ;
//创建老师类对象
Teacher t=newTeacher() ;
t.study() ;
t.sleep() ;
}
}
继承的特点
packagecom.qf.extends_05;
/**
* 继承的特点:
* 1)在Java语言中,类与类的关系,只支持单继承 (类是Java中最基本的单元)
* 举例:
* class Fu{}
* class Fu2{}
* class Zi extends Fu,Fu2{} 这种写法错误格式
* 2)类与类之间虽然不支持多继承,但是可以多层继承!
*
*/
//爷爷
classGrandFather{ //在Java中最顶层的类:Object(所有类的父类) ,可以省略不写!
publicvoidmethod(){
System.out.println("我是爷爷");
}
}
//父类
classFatherextendsGrandFather{
publicvoidshow(){
System.out.println("我是老子");
}
}
/*class Mother{
}*/
//子类
//class Son extends Father,Mother{} //多继承(类的关系,Java不支持!)
classSonextendsFather{
publicvoidfunction(){
System.out.println("function Son");
}
}
//测试类
publicclassExtendsDemo2 {
publicstaticvoidmain(String[] args) {
//创建具体的子类
Sons=newSon() ;
s.function(); //访问自己的功能
s.show(); //继承 父类的功能
s.method(); //间接继承了他爷爷的功能
}
}
继承的注意事项
packagecom.qf.extends_05;
/**
* 继承的注意事项:
* 1)子类继承父类,是可以继承父类所有的东西,只不过父类的私有的属性以及方法只能在本类中访问
*子类是不能直接访问到的,但是可以间接的通过公共方法来访问!
* 2)子类继承父类,不能继承父类的构造方法(无参/有参构造),可以通过 "super"来访问父类的构造方法!
*
*/
//父类
classFu{
//私有的
privateintnum=100 ;
//非私有的
publicintnum2=200 ;
//定义一个成员方法
publicvoidshow(){
System.out.println(num) ;
System.out.println(num2) ;
}
//私有方法
privatevoidmethod(){
System.out.println("method Fu...");
}
//非私有
publicvoidmySelfMethod(){
method(); //调用了私有方法
}
}
//子类
classZiextends Fu{
//子类的成员方法
publicvoidfunction(){
System.out.println(num2);
// System.out.println(num);
}
}
//测试类
publicclassExtendsDemo3 {
publicstaticvoidmain(String[] args) {
//创建Zi类对象
Ziz=newZi() ;
z.function(); //使用自己的成员方法
z.show(); //继承父类的, 父类的show方法里面有一个父类私有属性
//z.method();//父类的私有方法,不能直接访问
System.out.println("------------------------");
z.mySelfMethod();
}
}
继承关系中的成员问题
packagecom.qf.extends_06;
/**
*
* 继承关系中成员问题:
* 一个类的成员:
* 成员变量
* 成员方法
* 构造方法
*
*
* 1)子类继承父类,子类中 成员变量如果父类中的成员变量名称不一致的情况:比较简单,分别访问即可!
* 2)子类继承父类,如果子类的成员变量名称和父类的成员变量名称一致,如何访问呢?
*
* a)先在子类的局部位置(子类的成员方法中定义变量:局部变量)找,如果存在,就使用
* b)如果子类的局部位置没有,然后才在子类的成员位置找,如果存在,就使用
* c)如果子类的成员位置没有,然后在父类的成员位置找,如果存在,就使用
* d)如果父类的成员位置也没有,说明当前没有这个变量,就访问报错!
*
* 一句话:就近原则!
*/
//父类
classFu{
//父类的成员变量
intnum=20 ;
}
//定义一个子类
classZiextends Fu{
//子类的成员变量
//int num2 = 30 ;
intnum=100 ;
//子类的成员方法
publicvoidshow(){
intnum=30 ; //局部变量
System.out.println(num) ;
//System.out.println(num2);
}
}
//测试类
publicclassExtendsDemo4 {
publicstaticvoidmain(String[] args) {
//创建子类对象
Ziz=newZi() ;
z.show();
}
}
继承关系中: 子类继承父类,子类如何访问父类的构造方法?
packagecom.qf.extends_06;
/**
* 继承关系中:
* 子类继承父类,子类如何访问父类的构造方法?
* 通过super关键字
*
* 1)子类继承父类,不能继承父类的构造方法,但是可以通过super访问,子类的所有构造方法默认访问父类的无参构造方法!
* 子类的构造方法的第一句话:都有super() ; 访问父类的无参构造方法
* 原因:
* 子类继承父类,可能用到父类的属性(成员变量)这些数据,必须让父类先初始化,然后子类才能初始化(构造方法,就是给数据初始化的)
* 这种过程----继承中 "分层初始化"
* 2)永远建议把父类的无参构造方法给出来,可能户导致子类的构造方法报错!
*
*/
//定义一个父类
classFu3{
//假设:姓名,年龄,性别...属性(成员变量)
//父类给一个无参构造方法
publicFu3(){
System.out.println("这是Fu3的无参构造方法");
}
/*public Fu3(String name){
System.out.println("Fu3的有参构造方法,"+name);
}*/
}
//子类
classZi3extends Fu3{
//子类的无参构造方法
publicZi3(){
// super() ;//可以隐藏不写
System.out.println("Zi3的无参构造方法");
//super() ; 放在后面,可能初始化多次,jvm编译不让通过! 必须在第一句话
}
//子类的有参构造方法
publicZi3(Stringname){
//super() ;//可以隐藏不写
System.out.println("Zi3的有参构造方法,"+name);
}
}
//测试类
publicclassExtendsDemo5 {
publicstaticvoidmain(String[] args) {
//通过子类的无参构造方法,创建子类对象
Zi3z=newZi3() ;
System.out.println("--------------------") ;
//通过子类的有参构造放,创建子类对象
Zi3zz=newZi3("hello") ;
}
}
继承关系中的构造方法的注意事项
packagecom.qf.extends_06;
/**
* 继承关系中的构造方法的注意事项
*
* 子类继承父类,子类的所有构造方法第一句话都隐藏了默认 super() ;访问父类的无参构造方法,只存在父类的有参构造方法
* 那么,如果父类中并没有给出无参构造方法,子类会出现什么情况?如何解决?
*
* 子类的所有构造方法都会报错!默认都要访问父类无参构造方法(默认机制)
* 解决方案:
* 1)自己手动给出父类的无参构造方法(推荐)
* 2)不给出父类的无参构造方法,怎么解决?
* 让子类的所有构造方法都直接来访问父类的有参构造方法,只要父类初始化即可!
* 3)所有的子类的构造方法只要有一个让父类初始化即可!
* 在子类的无参构造方法中第一句话: this(xxx) ; 访问本类(子类)的有参构造方法
* 在通过子类的有参构造方法的第一句话:super(xxx) ;访问父类的有构造方法---->父类先初始化完毕完毕
*
*
* 实际开发中:(写继承代码的时候)
* 子类继承父类,子类的无参构造方法访问父类的无参!
* 子类的有参构造方法访问父类的有参!
*/
//定义一个父类
classFather{
//手动给出Father的无参
/* public Father(){
System.out.println("Father的无参构造方法");
}*/
//Facther的有参构造
publicFather(intnum){
System.out.println("Father的有参构造方法:"+num) ;
}
}
//定义一个子类
classSonextends Father{
//Son类的无参构造方法
publicSon(){
super(100) ; //访问父类的有参构造方法
//this(100) ;//访问本类的有参构造方法
System.out.println("Son的无参构造方法");
}
//Son的有参构造方法
public Son(intnum){
//super(20) ; //访问父类的有参构造方法
this() ;//访问本类无参构造方法
System.out.println("Son的有参构造方法:"+num);
}
}
//测试类
publicclassExtendsDemo6 {
publicstaticvoidmain(String[] args) {
// Son s = new Son() ;
Sons=newSon(50) ;
}
}
继承的面试题
packagecom.qf.extends_06;
/**
* 面试题
*看程序,补全代码,分别在控制台打印-- 30 20 10
* super:代表的是父类的空间标识(父类对象的地址值引用)
* this:代表本类对象的地址值引用
*/
classFu2{
intnum=10 ;
}
classZi2extends Fu2{
intnum=20 ;
publicvoidshow(){
intnum=30;
//补全代码
System.out.println(num) ;
System.out.println(this.num); //访问的是本类的成员变量
System.out.println(super.num); //访问父类的成员变量
}
}
//测试类
publicclassExtendsTest {
publicstaticvoidmain(String[] args) {
Zi2z=newZi2() ;
z.show();
}
}
看程序写结果(面试题)
packagecom.qf.extends_06;
/**
* 看程序,写结果
* 考点:
* 代码块的优先级
* 静态代码块 > 构造代码块 > 构造方法
* 继承关系问题
* 子类的所有构造方法默认父类的无参构造方法,目的就是让父类初始化的,然后在子类初始化!
*/
classPerson{
publicPerson(){
System.out.println("这是Person类的无参构造方法");
}
static{
System.out.println("Person的静态代码块");
}
{
System.out.println("Person的构造代码块");
}
}
//子类
classStudentextends Person{
publicStudent(){
//super();
System.out.println("Student的无参构造方法");
}
publicStudent(Stringname){
System.out.println("Student的有参构造方法");
}
{
System.out.println("Student的构造代码块");
}
static{
System.out.println("Student的静态代码块");
}
}
publicclassExtendsTest2 {
publicstaticvoidmain(String[] args) {
Students=newStudent() ;
Students2=newStudent("高圆圆") ;
}
}
继承的例题
packagecom.qf.extends_07;
/**
* 猫狗案例---继承版
*
* 猫和狗--都有姓名,年龄,毛色
* 猫和狗---吃和睡的功能
*
* 现在使用面向对象的方式,加入继承,在AnimalTest测试猫和狗
* 分析:
* 猫类--描述 猫事物
* 属性:name,age,color---私有化
* setXXX(xx)/getXXX()
* 行为:eat(),sleep() , 特有功能:catchMouse()
* 狗类--描述 狗事物
* 属性 :name,age,color---私有化
* setXXX(xx)/getXXX()
* 行为:eat(),sleep(),特有功能:lookDoor()
*
* 将猫和狗的共性内容---抽取到一个独立的类中 "动物类"---描述动物的
* 属性:name,age,color---私有化
* setXXX(xx)/getXXX()
* 行为:eat(),sleep()
*/
//测试类
publicclassAnimalTest {
publicstaticvoidmain(String[] args) {
//创建一只狗
//无参构造方法+ setXXX(xx)/getXXX()
Dogd=newDog() ;
d.setName("拉布拉多") ;
d.setAge(5) ;
d.setColor("棕色") ;
System.out.println(d.getName()+"---"+d.getAge()+"---"+d.getColor());
d.eat();
d.sleep();
d.lookDoor();
System.out.println("--------------------------------") ;
//方式2:有参构造方法直接赋值+getXXX()
Dogd2=newDog("二哈",3,"白色") ;
System.out.println(d2.getName()+"---"+d2.getAge()+"---"+d2.getColor());
d2.eat();
d2.sleep();
d2.lookDoor();
}
}
packagecom.qf.extends_07;
/**
* 动物类
* 属性:name,age,color---私有化
* setXXX(xx)/getXXX()
* 行为:eat(),sleep()
*/
publicclassAnimal {
//属性--私有化
privateStringname ; //姓名
privateintage ; //年龄
privateStringcolor ; //毛色
//无参构造方法
//alt+ins--->constructor--->select none
publicAnimal() {
}
//有参构造方法
//alt+ins--->constructor--->cltr+a--->回车
publicAnimal(Stringname, intage, Stringcolor) {//"哆啦A梦",5,"蓝色"
this.name=name;
this.age=age;
this.color=color;
}
//公共访问方法setXXX(xx)/getXXX()
//alt+ins--->getter and setter--->altr+a--->回车
publicStringgetName() {
returnname;
}
publicvoidsetName(Stringname) {
this.name=name;
}
publicintgetAge() {
returnage;
}
publicvoidsetAge(intage) {
this.age=age;
}
publicStringgetColor() {
returncolor;
}
publicvoidsetColor(Stringcolor) {
this.color=color;
}
//其他成员方法
publicvoideat(){
System.out.println("动物都需要吃饭") ;
}
publicvoidsleep(){
System.out.println("动物累了就需要休息");
}
}
packagecom.qf.extends_07;
/**
* 猫类
*/
publicclassCat extendsAnimal{
//猫的无参构造方法
/* public Cat(){ //Cat cat = new Cat() ;
//super();
}*/
//猫的有参构造方法
/* public Cat(String name,int age,String color){ //Cat c = new Cat("哆啦A梦",5,"蓝色");
super(name,age,color); //访问父类的有参构造方法
}*/
//alt+ins--->constructor--->将两个构造方法全部提供
publicCat() {
}
publicCat(Stringname, intage, Stringcolor) {
super(name, age, color);
}
//猫的特有功能
publicvoidcatchMouse(){
System.out.println("猫会抓老鼠");
}
}
packagecom.qf.extends_07;
/**
* 狗类
*/
publicclassDog extendsAnimal{
//无参/有参构造方法
publicDog() {
super();
}
publicDog(Stringname, intage, Stringcolor) {
super(name, age, color);
}
//狗的特有功能
publicvoidlookDoor(){
System.out.println("狗会看门");
}
}
面向对象的例题
packagecom.qf.test_08;
/**
* .(面向对象基础)写一个Worker 类,并创建多个Worker 对象。
* 1) 为Worker 类添加三个属性,1)String 类型的name,表示工人的姓名;
* int 类型的age,表示工人的年龄;3)double 类型的salary,表示工人
* 的工资。
* 2) 为Worker 类添加两个work 方法,一个无参,另一个带整数参数,表示
* 工人工作的时间(为多少小时)。
*
*
* Worker如下的属性的类型以及构造方法相关的参数
* name:String
* age:int
* salary:double
* Worker()
* work(hours:int)
*
* 在测试类中进行测试 工人类(属性私有化)
*/
publicclassTest1 {
publicstaticvoidmain(String[] args) {
//无参构造+setxxx(xx)/getXX()
Workerworker=newWorker() ;
worker.setName("唐伯虎9527");
worker.setAge(30) ;
worker.setSalary(10000.0) ;
worker.work(25);
System.out.println("---------------------");
//有参构造方法直接赋值
Workerw2=newWorker("秋香",25,8000.0) ;
w2.work(8);
}
}
packagecom.qf.test_08;
/**
* 定义一个工人类
*/
publicclassWorker {
privateStringname ; //姓名
privateintage ; //年龄
privatedoublesalary ;//工资
//定义无参构造方法
publicWorker(){
}
publicWorker(Stringname,intage, doublesalary){
this.name=name ;
this.age=age ;
this.salary=salary ;
}
publicStringgetName() {
returnname;
}
publicvoidsetName(Stringname) {
this.name=name;
}
publicintgetAge() {
returnage;
}
publicvoidsetAge(intage) {
this.age=age;
}
publicdoublegetSalary() {
returnsalary;
}
publicvoidsetSalary(doublesalary) {
this.salary=salary;
}
//Worker 类添加两个work 方法,一个无参,另一个带整数参数,表示
// 工人工作的时间(为多少小时)。
publicvoidwork(inthours){
System.out.println(name+",年龄是"+age+",工资是:"+salary+",已经工作了"+hours);
}
}
day13
晨写
#晨写
##1.静态代码块,构造代码块,构造方法的优先级
```markdown
优先级
静态代码块>构造代码块>构造方法
```
##2.static关键字的特点
```markdown
1.被static修饰的变量/方法,随着类的加载而加载,优先于对象存在
2.staitc关键字不能和this共存
3.具有"共享,共用"的意思
4.特有访问方法,使用类名访问 (类成员)
类名.变量名;
类名.方法名();
```
##3.什么是继承?继承的好处
```markdown
继承:
将多个类的共性内容抽取到一个独立的类中,让这个独立的类和这多个类产生一种关系,"extends"
好处:
1)可以提高代码的复用性
2)可以增强代码的维护性
3)类与类的关系,是多态前提条件!
所有开发原则必须遵循"低耦合,高内聚"
```
##4.继承的特点
```markdown
特点:
1)类与类之间,在Java语言中,只支持单继承,不支持多继承
2)不支持多继承.可以多层继承
```
##5.继承中,子类和父类出现的成员变量名称一致的情况,如何访问
```markdown
继承关系中,成员变量一致:
1)在子类的局部位置先找,如果有就使用;
2)如果子类局部位置没有,会在子类的成员位置中找,有就使用;
3)如果子类的成员位置也没有,会在父类的成员位置找,有就使用
4)如果父类中的成员位置也没有,访问了不存在的变量(编译报错)
classFu{}
classZiextendsFu{}
//测试
Ziz=newZi() ;
```
##6.继承中,子类继承父类,构造方法如何访问?
```markdown
子类继承父类,构造方法的访问:
构造方法是不能继承的!
构造方法目的为了给类的成员进行初始化;
继承关系中,子类继承父类,默认所有的子类的构造方法通过super() ;访问父类的构造方法
建议:描述一个事物,使用"类"来进行定义,永远给无参构造方法;
如果没有给出父类的构造方法,但是给了父类的有参构造方法,那么默认子类的所有构造方法都会报错!
解决方案:
1)要么直接手动给出父类无参
2)假设不给给出父类无参构造方法,直接让子类的所有构造方法通过super(xxx);来访问父类的有参
3)子类所有的构造方法中只要有一个能够父类初始化!
```
```java
classFu{
//公共的属性
publicFu(){}
}
classZiextendsFu{
publicZi(xxxx){
//子类的有参构造方法
}
}
```
---
---
#今日内容
##1.作业相关
##2.继承成员方法的访问
```
成员方法:
是否带参
是否有返回值
```
##3.方法重写:override /overload方法重载区别?--面试题
##4.引入关键字----final(特点:记住)
```
final特点
```
##5.多态(重点)
```
概念
能够使用多态的前提条件
多态成员访问特点
成员变量
成员方法:非静态的
构造方法:分层初始化(因为继承关系)
多态的好处:
多态的弊端:
```
-----
----
##面试题
###方法重写和方法重载的区别
```markdown
override和overload的区别
方法重载:
在定义方法的时候,为了提高功能的扩展性,同一个方法名,可以使用不同的参数进行传递!
方法名相同,参数列表不同,与返回值无关!
参数列表不同:
1)参数个数
2)参数类型
3)类型的先后顺序
方法重写:
是在继承关系中使用的;
子类继承父类,子类的功能想沿用父类的功能,同时使用自己的功能,子类出现了和父类一模一样的方法,--方法重写(覆盖/复写)
子类继承父类,如果要重写父类的功能,访问权限不能够更低,最起码跟父类的成员方法一致,要么永远public!
举例:
人:
eat() 吃的功能
员工:
work() 都需要工作
程序员也是员工 ---->日日夜夜敲带
项目奖经理也是员工---->吃饭喝酒谈项目
```
###this和super的区别
```markdown
概念区别
this:代表是当前类对象的地址值引用
super:代表父类的对象的地址值引用(父类的空间标识)
成员访问的区别:
this.变量名; 访问本类的成员变量
super.变量名; 访问父类的成员变量
this.方法名() ; 访问本类成员方法
super.方法名() ;访问的父类的成员方法
this() ; 访问本类的无参构造方法
this(xxx); 访问的本类的有参构造方法
super() ;访问的是父类的无参构造方法
super(xxx) ; 访问的是父类的有参构造方法
```
###final修饰基本数据类型和修饰引用数据类型的区别?
```markdown
final修饰的引用数据类型,当前不能在开辟堆内存(不能重新new),里面的成员变量依然可以进行赋值
final修饰的基本数据类型,基本数据数据值不能在改变!
```
###final,finalize,finally的区别?
```markdown
final是一个状态修饰符.最终的,无法更改的!
修饰类,该类不能被继承
修饰成员方法,该方法不能被重写
修饰变量,此时变量是一个常量;
finalize:是一个方法名,是后面jvm当前确定堆内存中对象没有更多引用的时候,来通过垃圾器来调用进行回
收的方法!
finally:是关键字,是后面Java中去处理"异常"的一种格式:捕获异常
标准格式
try{
//可能出现问题代码
}catch(异常类名变量名){
处理异常
}finally{
//释放相关的系统资源 (后面学习IO流,读取文件/写文件等等)
}
```
变量--->成员变量/局部变量什么时候将一个变量定义为成员变量?
packagecom.qf.variable_02;
/**
* 变量--->成员变量/局部变量
* 什么时候将一个变量定义为成员变量?
*
* 需求:
* 定义一个类,定义成员方法,对两个数据求和!
*
* 将一个变量定义为成员变量的时机:
* 如果这个变量能够描述现实世界事物的属性--->定义为成员变量,否则都是"局部变量"
*/
classDemo{
//成员变量
/*
int a ;
int b ;
//定义一个成员方法
public int sum(){
return a + b ;
}
*/
publicintsum(inta,intb){
return a+b;
}
}
//测试类
publicclassVariableDemo {
publicstaticvoidmain(String[] args) {
//访问Demo类中的sum方法
/* Demo d = new Demo() ;
d.a = 10 ;
d.b = 20 ;
int result = d.sum();
System.out.println(result);*/
Demod=newDemo() ;
intreuslt=d.sum(10, 20);
System.out.println(reuslt);
}
}
方法重写
packagecom.qf.extends_03;
/**
* 继承关系中,成员方法的访问
* 子类继承父类,如果子类和父类的方法名不一致,分别调用即可! (简单)
*
* 如果子类出现了和父类一模一样的方法,如何访问呢?
* 子类会将父类的功能进行覆盖(复写/重写)--->override:方法重写
*/
classFu{
//父类的成员方法
publicvoidshow(){
System.out.println("show Fu...");
}
}
//子类
classZiextendsFu{
//成员方法
publicvoidmethod(){
System.out.println("method Zi....") ;
}
publicvoidshow(){
super.show(); //既沿用了父亲的功能,还有自己的功能!
System.out.println("show zi...");
}
}
//测试类
publicclassExtendsDemo {
publicstaticvoidmain(String[] args) {
//创建子类对象
Ziz=newZi() ;
z.show() ;
z.method() ;
}
}
利用方法重写对手机举例
packagecom.qf.extends_03;
/**
* 需求:
* 有个一个手机,具备打电话的功能;
*公司后期研发了新手机,这个手机不仅能够打电话,还能看天气预报
*
*
* 子类继承父类,在有的时候,子类想沿用父类的功能,但是使用的自己的功能,
* 子类出现了和父类一模一样的方法,这种叫 "方法重写--override"
*/
//手机
classPhone{
//具备打电话的功能
publicvoidcall(){
System.out.println("手机打电话了...");
}
}
//新手机 ---属于手机
classNewPhoneextends Phone{
//这个手机不仅能够打电话,还能看天气预报
publicvoidcall() {
super.call(); //访问父类的call方法
System.out.println("该手机还可以看天气预报!");
}
}
//测试类
publicclassExtendsDemo2 {
publicstaticvoidmain(String[] args) {
//创建具体的子类
NewPhonenp=newNewPhone() ;
np.call();
}
}
final关键字
packagecom.qf.final_04;
/**
*
* 定义一个父类,子类重写父类的某个成员方法,通过方法重写,最终子类将父类将父类方法覆盖
* 但是有的时候,父类不让子类将自己的某个成员方法进行重写(为了父类的方法的安全性!),Java提供了关键字--->final
*
* final:是一个状态修饰符 (最终的,无法更改的)
*
*
*/
//定义一个父类
classFu{
//成员方法
publicfinalvoidshow(){ //加入final,这个show方法 最终的方法/无法更改的方法
System.out.println("这是一个绝密文件,任何不得更改!");
}
/* public void show(){
System.out.println("这是一个绝密文件,任何不得更改");
}*/
}
//定义一个子类
classZiextends Fu{
/* public void show(){
System.out.println("这一堆垃圾...");
}*/
}
//测试类
publicclassFinalDemo {
publicstaticvoidmain(String[] args) {
//创建子类对象
Ziz=newZi() ;
//调用show方法
z.show() ;
}
}
final关键字的特点
packagecom.qf.final_04;
/**
*final关键字特点:
* 基本概念:最终的/无法更改的
*
* 1)修饰类,该类不能够被继承!(当前这个类是最终类,无法来提供派生类(子类))
* 2)修饰成员方法,该成员方法不能重写(保证父类的方法安全性!)
* 3)修饰变量,此时该变量一个常量,不能在重新赋值!
*
*
*
* 常量:
* 编译时期常量---->基本数据类型:四类八种 (jvm不需要加载)
* public static final int a = 10 ;
* 运行时期常量---->引用数据类型: (jvm进行加载,引用类型 除过String)
* int类型--->包装类 类型 Integer类
* public static final Integer i = new Integer(10) ;
* //i = new Integer(100) ;//报错
*
* 开发中自定义常量:
* public static final 数据类型 变量名 = 初始化值;
*
*/
//定义一个类
//final class Animal{} //动物类
//子类:猫类
//class Cat extends Animal{}
//父类
classFather{
publicstaticfinalintage=20 ; //final修饰成员变量,必须给值,此值不能更改!
publicfinalvoidmethod(){
System.out.println("method Father..");
}
}
//子类
classSonextends Father{
/*public void method(){//不能重写
System.out.println("method Son");
}*/
publicvoidshow(){
finalinta=100 ; //局部变量
//a = 200 ;//数据值不能在更改
System.out.println(a) ;
}
}
//测试类
publicclassFinalDemo2 {
publicstaticvoidmain(String[] args) {
System.out.println(Father.age); //访问父类中静态常量
}
}
final面试题
packagecom.qf.final_04;
/**
* 面试题:
* final修饰基本数据类型和修饰引用数据类型 的区别?
* final修饰的引用数据类型,当前不能在开辟堆内存(不能重新new),里面的成员变量依然可以进行赋值
* final修饰的基本数据类型,基本数据数据值不能在改变!
*/
//定义一个学生类
classStudent{
intage=20;
}
//测试类
publicclassFinalDemo3 {
publicstaticvoidmain(String[] args) {
//创建学生类
//学生对象s没有加入任何修饰符
Students=newStudent() ;
System.out.println(s.age) ;
s.age=30 ;
System.out.println(s.age);
System.out.println("----------------------------") ;
//创建一个新的学生对象
finalStudents2=newStudent() ; //final修饰的引用数据类型,当前不能在开辟堆内存(不能重新new)
System.out.println(s2.age) ;
s2.age=40 ;
System.out.println(s2.age) ;
//s2 = new Student() ;
System.out.println("----------------------------") ;
inta=100 ;
a=200 ;
System.out.println(a) ;
System.out.println("-------------加入final修饰基本类型-------------------") ;
finalintnum=200 ;
//num = 50 ;
}
}
多态
packagecom.qf.duotai_05;
/**
* 什么是多态?
* 从宏观角度去说:一个事物(能看到真实存在的)体现出的不同形态!
* 举例:
* 水--->固态 气态 液态
* 从内存角度去说:一个对象它的所在的类型的变化
* 举例:
* Cat c = new Cat() ; //创建一个只猫 从右边--->左边:猫是猫
* Animal a = new Cat() ; //堆内存是猫 从右边--->左边:猫是动物
*
* 前提条件:
* 1)必须存在继承关系,才能使用多态
* 2)必须存在方法重写,子类继承父类,部分功能将父类进行重写,比如:
* 动物都要吃和睡,具体的动物类:猫/狗/猪,吃和睡的动作不一样
* 3) 必须存在 父类引用指向子类对象 ----->多态的 "向上转型"
* class 父类名{}
* class 子类名 extends 父类名{}
* //多态测试---
* 父类名 对象名 = new 子类名() ;
*
*
*
* 父类名 对象名 = new 子类名() ;
* 多态的成员访问特点:
* 成员变量:编译看左,运行看左!
*
* 成员方法(默认都是非静态): 如果子类重写了父类的方法,编译看左,运行看右!
* 静态方法算不上重写,和静态的都是类成员! (访问方式都是类名来调用的)
*
* 构造方法:继承是多态的前提条件,所以在使用父类引用指向子类对象:Fu fu = new Zi() ;
* 还是要遵循"分层初始化",先让父类构造初始化,然后在是子类构造初始化!
*
*/
//父类
classFu{
//成员变量
intage=40 ;
publicFu(){
System.out.println("Fu的无参构造方法");
}
//成员方法
publicvoidshow(){
System.out.println("show Fu");
}
publicvoidmethod(){
System.out.println("method Fu");
}
publicstaticvoidfunction(){
System.out.println("function Fu");
}
}
//子类
classZiextends Fu{
//成员变量
intage=20 ;
publicvoidshow(){
System.out.println("show Zi");
}
publicZi(){
System.out.println("Zi的无参构造方法");
}
publicvoidplayGame(){
System.out.println("儿子会玩游戏");
}
//静态算不上重写
publicstaticvoidfunction(){
System.out.println("function Zi");
}
}
//测试类
publicclassDuoTaiDemo {
publicstaticvoidmain(String[] args) {
//父类引用指向子类对象 --->格式 父类名 对象名 = new 子类名() ;
Fuf=newZi() ;
//Zi zi = new Zi() ;
//System.out.println(zi.age) ;
System.out.println(f.age) ;
f.show() ;
//f.show2() ; //show2()在Fu类中不存在,编译看左
f.method() ;
//f.function() ;
//Fu.function();
//Zi.function();
//f.playGame() ;编译报错:父类中没有playGame方法
}
}
多态的好处
package com.qf.duotai_05;
/**
* 多态的好处:
* 1)可以提供代码的复用性(由继承保证的)
* 2)可以提高代码的扩展性(健壮性)--->由多态保证
* 父类引用指向子类对象
*/
//动物类
class Animal{
public void eat(){
System.out.println("动物需要吃饭");
}
public void sleep(){
System.out.println("动物困了就需要休息");
}
}
//子类
class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void sleep() {
System.out.println("猫趴着睡");
}
}
//狗类
class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃骨头");
}
@Override
public void sleep() {
System.out.println("狗侧着睡");
}
}
//子类
class Pig extends Animal{
@Override
public void eat() {
System.out.println("猪吃白菜");
}
@Override
public void sleep() {
System.out.println("猪躺着睡");
}
}
//优化方案2:定义一个动物工具类
class AnimalTool{
//为了让外界不能new,无参构造方法私有化
private AnimalTool(){}
//定义一个方法: 使用猫的功能
/* public static void useCat(Cat c){//形式参数是猫类型
c.eat();
c.sleep();
}
//定义一个方法:使用狗的功能
public static void useDog(Dog d){//形参参数是狗类型
d.eat();
d.sleep();
}
//定义一个方法:使用猪的功能
public static void usePig(Pig p){
p.eat();
p.sleep();
}*/
public static void useAnimal(Animal a){ //形式参数是引用类型--->父类指向子类对象
// 实际参数:Animal animal = new Cat();
a.eat(); //animal.eat() ;
a.sleep(); //animal.sleep() ;
}
}
//测试类
public class DuoTaiDemo2 {
public static void main(String[] args) {
//使用具体的子类操作
//养了一只狗--创建狗
Dog dog = new Dog() ;
dog.eat();
dog.sleep();
System.out.println("-------------------------------------------------");
//优化:在测试类中提供两个静态方法,方法形式参数传递狗或者猫
//有一只猫对象
Cat cat = new Cat() ; //有名字的对象
useCat(cat) ;
useDog(new Dog());
System.out.println("----------------------优化方案2------------------------------");
//上面代码不好: 随着具体的类越来越多,useXXX(具体的动物类型)方法就会很多,代码量很多!
//定义一个动物工具类 AnimalTool
//AnimalTool at = new AnimalTool();
/* AnimalTool.useCat(new Cat());
AnimalTool.useDog(new Dog());
Pig pig = new Pig() ;
AnimalTool.usePig(pig);*/
//上面代码继续优化:随着具体类型增加,AnimalTool中的静态功能,越来越多
//多态的特点:父类引用指向子类对象:可以提高代码的扩展性
Animal animal = new Cat() ; //堆内存指向的是猫 (猫是的动物)
AnimalTool.useAnimal(animal);
animal = new Dog(); //堆内存是狗 (狗是动物)
AnimalTool.useAnimal(animal);
}
//定义一个方法: 使用猫的功能
public static void useCat(Cat c){//形式参数是猫类型
c.eat();
c.sleep();
}
//定义一个方法:使用狗的功能
public static void useDog(Dog d){//形参参数是狗类型
d.eat();
d.sleep();
}
}
多态的弊端
package com.qf.duotai_06;
/**
* 多态的弊端:
* 不能访问子类的特有功能 父类名 对象名 = new 子类名() ; "向上转型"
*
* 如何解决呢?
* 方案1:
* 直接创建具体的子类对象 子类名 对象名 = new 子类名() ;
* 虽然可以这种方式可以,但是从内存角度考虑:消耗资源,浪费空间,又需要去开辟堆内存!
* 方案2:
* 多态本身:父类引用指向子类对象,能不能将父类的引用转换成子类型?
* "向下转型"---->强转类型转换的格式 ,前提必须有"向上转型"
* 数据类型 变量名 = (目标数据类型)(初始化值或者表达式) ;
*
*
*/
//父类
class Fu{
public void show(){
System.out.println("show Fu");
}
}
//子类
class Zi extends Fu{
public void show(){
System.out.println("show Zi");
}
//特有功能
public void playGame(String gameName){
System.out.println("会玩"+gameName+"游戏");
}
}
//测试类
public class DuoTaiDemo3 {
public static void main(String[] args) {
//父类引用指向子类对象
Fu fu = new Zi() ;
fu.show() ;
//fu.playGame("csgo") ;无法使用playGame方法()父类没有
System.out.println("-----------------------------") ;
//访问子类特有功能
// Zi z = new Zi() ;
//z.playGame("战地5");
System.out.println("------------------------------");
/**
* "向下转型"---->强转类型转换的格式 ,前提必须有"向上转型"
* * 数据类型 变量名 = (目标数据类型)(初始化值或者表达式) ;
*/
Zi z2 = (Zi)fu;
z2.playGame("战地5");
}
}
package com.qf.duotai_06;
/**
* 多态的弊端:不能访问子类特有方法,通过向下转型来访问,这种方式节省内存;
* 但是向下转型使用不当,会出现运行时期的异常
*
*/
//动物类
class Animal{
public void eat(){
System.out.println("eat");
}
}
//猫
class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
//狗
class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃骨头");
}
}
//测试类
public class DuoTaiDemo4 {
public static void main(String[] args) {
//多态的测试:父类引用指向子类对象
Animal a = new Cat() ;//堆内存是猫 (猫是动物)
//向下转型: 还原猫 (猫是猫)
Cat c = (Cat) a;
a = new Dog () ; //堆内存是狗 (狗是动物)
Dog d = (Dog) a; //还原成狗 (狗是狗)
a = new Cat() ;
//Dog dd = (Dog) a; //ClassCastException:类转换异常
Cat cc = (Cat) a;
}
}
day14
晨写,今日内容
# 晨写
## 1.方法重写和方法重载的区别?
```markdown
方法重写:override
继承体系中,子类继承父类,子类想沿用父类的功能,还是使用自己的功能,出现了和父类一模一样的方法(复写/重写/覆盖),在重写的时候,子类的方法的权限不能更低!
方法重载:overload
在定义的方法是,为了提供功能扩展性,同一个方法名,可以传递不同的参数!
方法名相同,参数列表不同,与返回值无关;
参数列表不同:
1)参数个数
2)参数类型
2)考虑参数顺序
```
## 2.this和super的区别?
```markdown
概念上的区别
this:代表当前类对象的地址值引用
super:代表的父类的空间标识(父类对象的地址值引用)
访问成员变量的区别
this.变量名; 访问的本类中的成员变量
super.变量名; 访问的是父类成员变量
访问构造方法的区别
this(); 访问的是本类的无参构造方法
super() ;访问的父类的无参构造方法
this(xx) ; 访问的是本类的有参构造方法
super(xx) ;访问的是父类的有参构造方法
访问成员方法的区别:
this.方法名() ;访问本类的成员方法
super.方法名() ;访问的是父类的成员方法
```
## 3.final关键字的特点
```markdown
final关键字特点:(状态修饰符,最终的,无法更改的!)
final修饰类,该类不能被继承!
final修饰成员方法,该方法不能被重写
final修饰一个变量,此时变量一个常量;
编译时期常量:基本类型数据类型,jvm不需要加载
运行时期常量:引用数据类型,jvm需要加载
开发中,传统方式自定义常量
public final static 数据类型 变量名 = 初始化值;
```
## 4.什么是多态?多态的前提条件?
```markdown
多态:
一个事物体现的不同形态;(内存中,类型的变化:前提,继承体现中)
多态的前提条件:
1)必须有继承关系
2)存在重写
3)必须父类引用指向子类对象 : "向上转型"
父类名 对象名 = new 子类名() ;
```
## 5.多态的成员访问特点以及多态的好处
```markdown
多态的成员访问特点:
父类名 对象名 = new 子类名() ;
成员变量:编译看左,运行看左!
成员方法:编译看左,运行看右(子类存在方法重写)
静态的方法:编译看左,运行看左! (静态的方法算不上重写,它是跟类相关,随着类的加载而加载!)
构造方法:因为继承关系,先让父类进行构造初始化,然后在是子类初始化,"分层初始化操作"
```
## 6.多态的弊端?如何解决
```markdown
多态的弊端:
Fu fu = new Zi() ; 向上转型
无法子类的特有功能!
解决方案:
1)可以创建Zi zi = new Zi(); 创建子类自己的实例(创建对象)---在重新开辟堆内存空间,消耗资源!
2)推荐: 向下转型 ,前提有向上转型!
Zi z = (Zi)fu; 数据类型 变量名 = (目标数据类型)(表达式或者初始化值) ;
向下转型使用不当:
会出现运行时期异常:ClassCastExeption:类转换异常!
```
----
-----
# 今日内容
## 1.作业
## 2.关于抽象abstract(关键字)--->理解
```
一类事物:看到具体事物,才能里面的行为---->抽取父类的时候不能直接定义 具体类
class 类名{}
--->定义格式:
abstract class 类名{}
概念:
书写格式:
抽象类的本质:
abstract和哪些关键字不能共存!
```
## 3.什么是接口
```
比抽象类更抽象的一种概念!
接口的本质:事物额外的扩展功能!
接口的使用书写格式:
```
## 4.面试题:抽象类和接口的区别?
## 5.关于package 包的真实含义 (理解)
```markdown
开发中:包--->就是目录(文件夹)
代码要进行分层
每一个层:有自己的特殊含义
```
## 6.权限修饰的范围(识记)
```
同一个包/不同包
private
默认修饰符
protected
public
```
## 7.了解 内部类
```
类中类
了解的分类以及构造以及访问方式!
主要jdk原码中,看到懂类的结构!
```
----
---
## 面试题:抽象类和接口的区别?
```markdown
区别:
1)成员的区别
抽象类:
成员变量:既可以常量(定义final修饰的),也可以是变量
成员方法:既可以存在抽象方法,而且也可以存在非抽象方法
如果定义抽象方法,abstract不能省略!
构造方法:存在,无参构造/有参构造方法,让类的数据进行初始化(构造初始化)
接口:
成员变量:只能是常量,存在隐藏的默认修饰符:public static final'
成员方法:只能是抽象方法
构造方法:没有
2)关系区别:
类与类:继承关系,只支持单继承,不支持多继承
类接口:实现关系,一个类继承另一个类的同时,可以实现多个接口
接口与接口:继承关系,可以单继承,也可以多继承以及多层继承
3)设计理念的区别
抽象类:有继承关系,抽象类不能创建对象,借助于抽象类多态(子类是具体类),进行实例化;
体现的核心思想: "is a"的关系
A类是B类的一种或者B类是A列的一种
水果:
橘子
香蕉
接口:体现的是事物的一种额外的扩展功能,本身不具备,需要实现接口才能具备这个功能!
体现的核心思想:
"like a"的关系
猫"跳高" -->
狗"做计算"---> 跳高以及做计算都是额外功能;
```
```markdown
一个类中没有任何抽象方法,将这个类定义为抽象类的意义?
意义:不让创建对象! 肯定会有具体的子类;
```
台灯的问题
packagecom.qf.test_05;
/**
* 设计一个台灯类(Lamp)其中台灯有灯泡类(Buble)这个属性,
* * 还有开灯(on)这个方法
*/
publicclassLamp {
//有一个灯泡类属性
privateBublebuble;
/**
* 开灯的方法
* 请设计出一段代码可以使台灯开启灯泡发亮
*/
/* public void on(RedBuble redBuble){
redBuble.shine() ;
}
public void on(GreenBuble greenBuble){
greenBuble.shine() ;
}*/
//多态:父类引用指向子类对象,on这个方法形式参数传递父类型,
publicvoidon(Bublebuble){//Buble b = new RedBuble() ;
System.out.println("台灯开启...");
buble.shine() ;
}
}
packagecom.qf.test_05;
/**
* 有一个灯泡类
*
* 抽象的灯泡类
*/
publicabstractclassBuble {
//灯泡类有发亮的方法
/* public void shine(){
System.out.println("灯泡会亮");
}*/
//发亮的方法需要被子类进行重写
publicabstract voidshine() ;
}
packagecom.qf.test_05;
/**
* 绿灯泡
*/
publicclassGreenBuble extendsBuble{
@Override
publicvoidshine() {
System.out.println("灯泡可以发绿光了...");
}
}
packagecom.qf.test_05;
/**
* 红灯泡
*/
publicclassRedBuble extends Buble{
@Override
publicvoidshine() {
System.out.println("灯泡可以发红光了");
}
}
packagecom.qf.test_05;
importcom.sun.org.apache.regexp.internal.RE;
/**
* 设计一个台灯类(Lamp)其中台灯有灯泡类(Buble)这个属性,
* 还有开灯(on)这个方法。设计一个灯泡类(Buble),
* 灯泡类有发亮的方法,其中有红灯泡类(RedBuble)和绿灯泡类(GreenBuble)
* 他们都继承灯泡类(Buble)一个发亮的方法,请设计出一段代码可以使台灯开启灯泡发亮
* 红灯泡发红光,绿灯泡发绿光!
*
*
*/
publicclassTest5 {
publicstaticvoidmain(String[] args) {
//创建一个台灯
Lamplamp=newLamp() ;
//多态测试红灯泡
// Buble b = new RedBuble() ;
//lamp.on(b) ;
//匿名对象
lamp.on(newRedBuble());
System.out.println("-----------------------------");
Bubleb=newGreenBuble() ;//抽象类多态
lamp.on(b) ;
System.out.println("----------------------------------");
lamp.on(newGreenBuble()) ;
}
}
抽象
什么是抽象
packagecom.qf.abstract_06;
/**
* 什么是抽象?
* 举例:
* 将猫和狗的共性内容,抽取到了动物(本身就是统称,概括性的)了中,比如:吃和睡的功能,但是在动物了中
* 将吃和睡给出了具体体现,只有看到具体的事物才能知道它具体吃和睡的行为!所以在父类将这些行为,只是给出一个方法声明即可!
* 仅仅给出方法的声明---->含义没有方法体{},抽象功能---->
*
* 有抽象的方法的必须为抽象类
* 抽象类中不一定都是抽象方法!(部分的功能,抽象功能,必须让子类必须重写!)
*
* 抽象方法(成员方法)的格式:
* 权限修饰符 abstract 返回值类型 方法名(空参/带参) ;
*
* 抽象类的本质:
* 强制子类必须将父类的所有的抽象方法,必须实现(重写)
*抽象类的特点:
* 1)不能实例化(不能new 创建对象)
* 2)抽象类的子类一定有具体类,否则无法进行实例化的!
*
*
*
*/
//定义动物类
abstractclassAnimal{
/*public void eat(){
System.out.println("动物都需吃饭");
}*/
//将动物的吃的功能,给出一个声明即可,没有方法体{}
publicabstractvoideat() ;
publicvoidshow(){
System.out.println("show Animal");
}
}
//子类
//abstract class Cat extends Animal{//子类也是一个抽象类,肯定是有个具体的类的,进行父类的实例化!
classCatextends Animal{
@Override
publicvoideat() {
System.out.println("猫吃鱼");
}
}
classDogextends Animal{
@Override
publicvoideat() {
System.out.println("狗吃骨头");
}
}
//测试类
publicclassAbstractDemo {
publicstaticvoidmain(String[] args) {
//创建父类对象
//Animal a = new Animal() ; //不能new ,抽象类
//如何实例化:通过子类(最底层的子类:可以new的)进行实例化
Animala=newCat() ;//父类引用指向子类对象 (抽象类多态!)
a.eat() ;
}
}
抽像类的成员特点
packagecom.qf.abstract_06;
/**
* 抽象类的成员特点:
* 1)成员变量:
* 可以是变量也可以自定义的常量
* 2)成员方法
* 既可以有抽象方法,也可以有非抽象方法!
* 3)构造方法
* 还存在继承关系,分层初始化--->先父类构造初始化,然后是子类构造初始化!
* 无参构造方法/有参构造方法都可以存在,目的都是为了数据进行初始化!
*/
//定义一个父类
abstract classFu{
//定义一个成员变量
publicintnum=20 ;
//自定义常量
publicstaticfinalintnum2=30 ;
//非抽象方法
publicStringshow(){
return"hello,Show Fu!" ;
}
//抽象方法
publicabstract voidfunction() ;
publicFu(){
System.out.println("Fu的无参构造方法");
}
}
//子类
classZiextends Fu{
//重写function
@Override
publicvoidfunction() {
System.out.println("function Zi...");
}
publicZi(){
System.out.println("Zi的无参构造方法");
}
publicZi(Stringstr){
System.out.println("Zi的有参构造方法");
}
}
//测试类
publicclassAbstractDemo2 {
publicstaticvoidmain(String[] args) {
//抽象类多态测试
Fufu=newZi() ; //父类引用指向子类对象
System.out.println(fu.num) ;
System.out.println(Fu.num2) ;
System.out.println("--------------------------------") ;
Stringresult=fu.show() ;
System.out.println(result) ;
fu.function() ;
System.out.println("-----------------------------------");
Fufu2=newZi("hello") ;
}
}
抽象关键字不能和那些关键字共存
package com.qf.abstract_06;
/**
* 抽象abstract关键字不能和哪些关键字共存?
*
* abstract不能和private共用:
* 被private修饰的只能在当前类访问,而abstract修饰的方法,它需要强制子类进行重写;
* abstract不能和static共用:
* abstract修饰的成员方法,需要被子类重写,还是抽象类多态进行实例化Fu fu = new Zi() ;
* 而static随着类的加载而加载(静态方法算不上重写),跟类相关的!
* abstract不能和final共用:
* 被final修饰的成员方法不能被重写,而abstract修饰的成员方法,强转子类重写!
*
*
* abstract:用在类上,标记这个类----抽象类
* 用在方法上,标记这个方法是一个抽象方法!
* 结合public使用居多
*/
//定一个类
abstract class Animal2{
//定义一个抽象方法
//动物都需要吃
public abstract void eat() ;
//private abstract void eat() ;
//public static abstract void show() ;
//public final abstract void show() ;
}
class Cat2 extends Animal2{
@Override
public void eat() {
System.out.println("猫吃鱼") ;
}
}
//测试类
public class AbstractDemo3 {
public static void main(String[] args) {
}
}
抽象类的举例
package com.qf.abstract_07;
/**
* 动物类
*/
public abstract class Animal {//抽象类
private String name ; //动物名称
private int age ; //年龄
private String color ;//颜色
public Animal() {
}
public Animal(String name, int age, String color) {
this.name = name;
this.age = age;
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
//eat和sleep仅仅给出声明
public abstract void eat () ;
public abstract void sleep() ;
}
package com.qf.abstract_07;
/**
* 猫类
*/
public class Cat extends Animal{
public Cat() {
}
public Cat(String name, int age, String color) {
super(name, age, color);
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void sleep() {
System.out.println("猫趴着睡");
}
//特有功能
public String catchMouse(){
return "猫会抓老鼠" ;
}
}
package com.qf.abstract_07;
/**
*狗类
*/
public class Dog extends Animal{
public Dog() {
}
public Dog(String name, int age, String color) {
super(name, age, color);
}
@Override
public void eat() {
System.out.println("狗吃骨头");
}
@Override
public void sleep() {
System.out.println("狗侧着睡");
}
//特有功能
public void lookDoor(){
System.out.println("狗看门");
}
}
package com.qf.abstract_07;
/**
* 猫狗案例---自己分析属性和行为,加入方法重写,使用多态进行测试
* 猫和狗的共性属性:
* name,age,color
* setXXX(xx)/getXXX
* 猫特有功能:
* 抓老鼠
* 狗特有功能:
* 看门
*
* ---->抽取动物类中--抽象类
* eat()和sleep()---仅仅给出一个声明,此时抽象方法
*
* 使用多态进行测试(抽象类多态)
*/
public class AnimalTest {
public static void main(String[] args) {
//有参构造直接赋值
Animal a = new Dog("藏獒",6,"黑色") ;
System.out.println(a.getName()+"---"+a.getAge()+"---"+a.getColor());
a.eat();
a.sleep();
Dog d = (Dog) a;
d.lookDoor();
//无参构造方法+setXXX(xx)/getxx()展示信息 自己测试
}
}
接口
什么是接口
package com.qf.interface_08;
/**
* 什么是接口?
*
* 举例:
* 猫或者狗本身这个事物不具备"跳高"的功能,经过后天 驯养员的培养,猫和狗就具备了"跳高的功能"
*
* 接口体现的是这个事物本身不具备的功能,是一种额外的扩展功能!
* 只要这个事物实现了接口,它就具备这个功能!
* 如何定义接口
* java定义接口
* interface 接口名{}
*
* 接口的子类(子实现类) implements 接口名{
* 强制子实现类必须将接口中所有抽象方法必须重写!(实现)
* }
*
* 接口的特点:
* 1)接口不能实例化(不能创建对象)
* 2)接口如何实例化?
* 接口多态
* 接口名 对象名 = new 接口的子实现类名() ; (前提:子实现类是非抽象的,就是一个具体类)
*
*
*开发中:
* 接口名和子实现类的命名规范(开发项目中)
* 举例:
* 接口名: interface Inter{}
* 接口的子实现类命名: 接口名 +Impl
* class InterImpl implements Inter{}
*
*
*
*/
//定义一个接口
interface Jump{
//定义一个跳高的功能
/*public void jump(){
System.out.println("可以跳高");
}*/
public abstract void jump() ;
}
//有一个动物类
abstract class Animal{
public abstract void eat() ;//抽象方法
}
//猫类
class Cat extends Animal implements Jump{ //猫 具备跳高的功能,必须实现接口
@Override
public void eat() {
System.out.println("猫吃鱼");
}
//跳高功能
@Override
public void jump() {
System.out.println("猫可以跳高了...") ;
}
}
//测试类
public class InterfaceDemo {
public static void main(String[] args) {
//创建接口Jump对象
// Jump jump = new Jump() ; //接口不能实例化(不能创建对象new)
// 接口名 对象名 = new 接口的子实现类名() ;
Jump jump = new Cat() ;//接口多态
jump.jump();
//jump.eat( );
//向下转型
Cat c = (Cat) jump;
c.eat();
}
}
接口中的成员特点
package com.qf.interface_08;
/**
* 接口中的成员特点:
* 成员变量:只能是常量 存在默认修饰符 public static final
* 成员方法:(非静态):只能是抽象方法,存在默认修饰符 public abstract
* 在接口中是可以定义静态方法,必须有方法体(特例)
* 构造方法: 没有构造方法! 因为子实现类和接口的关系是implements实现关系,
* 只是将接口暴露的额外功能进行实现!
*
*
*/
//定义一个接口
interface Inter{
/*public Inter(){
}*/
// public int num = 10 ;
public static final int num = 10 ;
//public static int num2 = 20 ;
public static final int num2 = 20 ;
/*void show(){//接口只能抽象方法
}*/
public abstract void show() ;
void show3() ;
//静态方法
public static void show2(){
System.out.println("show2()...");
}
}
//接口的子实现类 InterImpl实现Inter接口
class InterImpl implements Inter{
int num = 100 ;
@Override
public void show() {
System.out.println("show InterImpl");
}
@Override
public void show3() {
System.out.println("show3 InterImpl");
}
}
//测试类
public class InterfaceDemo2 {
public static void main(String[] args) {
//接口多态的测试
Inter inter = new InterImpl() ;
System.out.println(inter.num) ;//多态的成员变量的访问
System.out.println(Inter.num);
// inter.num = 200 ;
System.out.println(Inter.num2) ;
//inter.num2 = 300 ; final修饰的变量是一个常量,不能在赋值
Inter.show2();
}
}
接口与接口,类与类,类与接口的关系
package com.qf.interface_08;
/**
* 在Java中,
* 类与类:
* 继承关系,extends,而且只支持单继承,不支持多继承,但是可以多层继承!
* 类与接口
* 实现关系,implements,而且一个类继承另一个类的同时,是可以实现多个接口的!接口名和接口名直接逗号隔开
* class LoverImpl extends Lover implements Love,Study{
* 接口与接口
* 继承关系,extends,不仅支持单继承,也支持多继承,也可以多层继承!
*
*/
//定义一个接口
interface Speak{
public abstract void speakEnglish() ;//会说英语
}
interface Study{
public abstract String study() ;//学习的功能
}
//接口
interface Love extends Study,Speak{
public abstract void love() ;
}
class Lover{
public void show(){
System.out.println("show Lover");
}
}
//实现类
//子实现类 实现接口
class LoverImpl extends Lover implements Love,Study{
@Override
public void love() {
System.out.println("爱生活,爱Java,爱高圆圆!");
}
//实现另一个接口的的功能
@Override
public String study() {
return "学习JavaEE!";
}
@Override
public void speakEnglish() {
System.out.println("会说英语....");
}
}
//测试类
public class InterfaceDemo3 {
public static void main(String[] args) {
//创建具体的子类对象
LoverImpl ll = new LoverImpl() ;
ll.show() ;//父类的方法
ll.love();
ll.study() ;
}
}
day15
水果榨汁实例
packagecom.qf.test_01;
importcom.sun.org.apache.xpath.internal.operations.Or;
/**
* 定义榨汁机JuiceMachine 有榨汁方法makeJuice,传入相应的水果。
* 如果传入的是Apple 输出 "流出苹果汁"
* 传入的是Orange 输出 "流出橙汁"
* 传入的是Banana 输出 "流出香蕉酱"
*/
publicclassTest1 {
publicstaticvoidmain(String[] args) {
/* //创建一个榨汁机
JuiceMachine jm = new JuiceMachine() ;
Fruit f = new Apple() ;
//f = new Orange() ;
// f = new Banana() ;
jm.makeJuice(f) ;
System.out.println("-------------------------------");
jm.makeJuice(new Banana());*/
System.out.println("--------------方式2------------------");
JuiceMachine.makeJuice(newOrange());
}
}
packagecom.qf.test_01;
/**
* 榨汁机
*/
publicclassJuiceMachine {
//构造方法私有化:外界类不能创建对象
privateJuiceMachine(){
}
/**
* 榨汁方法makeJuice,传入相应的水果
*/ //new Apple();
//new Orange();
//new Banana() ;
publicstaticvoidmakeJuice(Fruitfruit){
//传入水果 --形式参数是一个抽象类型,调用该方法,需要传递当前抽象类的子类对象
/**
* 如果传入的是Apple 输出 "流出苹果汁"
* 传入的是Orange 输出 "流出橙汁"
* 传入的是Banana 输出 "流出香蕉酱"
*/
//变量名 instanceof 数据类型:判断前面变量名是否为这个后面这个类型的实例
if(fruitinstanceofApple){
//fruit是Apple的实例
fruit.juice() ;
}elseif(fruitinstanceofOrange){
//fruit是Orange类的实例
fruit.juice() ;
}else{
fruit.juice(); //流出香蕉酱
}
}
}
packagecom.qf.test_01;
/**
* 水果类
*/
publicabstractclassFruit {
//只有看到具体的水果---才能流出对应的水果汁,仅仅给出一个方法声明
publicabstractvoidjuice() ;
}
packagecom.qf.test_01;
/**
* 橙子
*/
publicclassOrange extendsFruit{
@Override
publicvoidjuice() {
System.out.println("流出橙汁!");
}
}
packagecom.qf.test_01;
/**
* 香蕉类
*/
publicclassBanana extendsFruit{
@Override
publicvoidjuice() {
System.out.println("流出香蕉酱!");
}
}
packagecom.qf.test_01;
/**
* 苹果类
*/
publicclassApple extendsFruit{
@Override
publicvoidjuice() {
System.out.println("流出苹果汁");
}
}
宠物商店实例
packagecom.qf.test_02;
/**
* 定义一个动物类,里面有一个方法voice(),
* 定义一个类Cat,实现voice方法
* 然后增加一种新的动物类型:Pig(猪),实现voice()方法。
* 定义一个Dog类,实现voice方法
* 定义一个Store(宠物店)类的getInstance方法:
* 如果传入的参数是字符串dog,则返回一个Dog对象;
* 如果传入pig,则返回一个Pig对象;否则,返回一个Cat对象。
*
* 提示:字符串进行判断 通过equals(字符串)方法
*/
publicclassTest2 {
publicstaticvoidmain(String[] args) {
//创建一个宠物店
/*Store store = new Store() ;
Animal animal = store.getIntance("dog");//方法本质就是 创建一只狗 new Dog() ;
animal.voice() ;
animal = store.getIntance("cat") ;
animal.voice();
animal = store.getIntance("pig") ;
animal.voice();*/
Animalan=Store.getIntance("monkey");
an.voice();
}
}
packagecom.qf.test_02;
/**
* 宠物店
*/
publicclassStore {
//构造方法私有化:外界不能new
privateStore(){}
/**
* 提供getInstance方法:
* 如果传入的参数是字符串dog,则返回一个Dog对象;
* 如果传入pig,则返回一个Pig对象;否则,返回一个Cat对象。
*/
//利用多态:提高代码扩展性!
//方法的返回值是一个类:抽象类--->需要返回该抽象类的子类对象
publicstaticAnimal getIntance(Stringtype){
//字符串进行比较:必须使用
// 当前字符串.equals(另一个字符串):比较两个字符串的内容是否相同
// 相同,true;否则false---
//String类:字符串:进行equals的时候,将常量放前面,否则可能出现空指针异常
if("dog".equals(type)){
returnnewDog() ;
}elseif("pig".equals(type)){
return newPig() ;
}else{
return newCat() ;
}
}
//创建Stroe对象 Stroe s = new Store() ;
// Animal a = s.getInstance("dog") ; //Animal a = new Dog();
}
package com.qf.test_02;
/**
* 动物类
*/
public abstract class Animal {
//面有一个方法voice():每一个具体动物才有具体的行为---抽象
public abstract void voice() ;
}
package com.qf.test_02;
/**
* 猫
*/
public class Cat extends Animal{
@Override
public void voice() {
System.out.println("猫发出喵喵喵的声音");
}
}
package com.qf.test_02;
/**
*狗类
*/
public class Dog extends Animal{
@Override
public void voice() {
System.out.println("狗发出汪汪汪叫的声音");
}
}
package com.qf.test_02;
/**
* 猪类
*/
public class Pig extends Animal{
@Override
public void voice() {
System.out.println("猪发出哼哼叫的声音");
}
}
方法的形式参数问题: 只研究引用类型
package com.qf.args_01;
/**
* 方法的形式参数问题: 只研究引用类型
*
* 方法形式参数:
* 具体类:调用该方法,此时实际参数需要的是当当前类的对象!
* 抽象类
* 接口
*
*/
class Student{
public void studyJavaEE(){
System.out.println("正在学习JavaEE之JavaSE") ;
}
}
//定义一个StudentDemo类
class StudentDemo{
public void show(Student s){//方法的形式参数是一个学生类型
s.studyJavaEE() ;
}
}
//测试类
public class ArgsDemo1 {
public static void main(String[] args) {
//访问StudentDemo类中的show方法
StudentDemo sd = new StudentDemo() ;
Student student = new Student() ;
sd.show(student) ;
System.out.println("---------------------------------------") ;
//另一种方式:匿名对象
new StudentDemo().show(new Student());
}
}
package com.qf.args_01;
/**
* 方法的形式参数问题: 只研究引用类型
*
* 方法形式参数:
* 具体类:调用该方法,此时实际参数需要的是当当前类的对象!
* 抽象类:调用该方法,此时实际参数需要的是当前抽象类的子类对象!
* 接口
*
*/
//定义一个Person类
abstract class Person{
/*public void work(){
System.out.println("人都需要工作");
}*/
public abstract void work() ;
}
//定义一个PersonDemo类
class PersonDemo{
public void function(Person p){//方法的形式参数是引用类型--抽象类,抽象类不能new,需要传递抽象类的子类对象!
p.work() ;
}
}
//定义抽象类的子类(具体类)
class Worker extends Person{
@Override
public void work() {
System.out.println("爱工作,爱Java,爱高圆圆!");
}
}
//测试类
public class ArgsDemo2 {
public static void main(String[] args) {
//访问PersonDemo类中的function方法?
PersonDemo pd = new PersonDemo() ;
//Person p = new Person() ;抽象类不能实例化(不能创建对象)
Person person = new Worker() ;
pd.function(person) ;
System.out.println("----------------------------------") ;
new PersonDemo().function(new Worker());
}
}
package com.qf.args_01;
/**
* 方法的形式参数问题: 只研究引用类型
*
* 方法形式参数:
* 具体类:调用该方法,此时实际参数需要的是当当前类的对象!
* 抽象类:调用该方法,此时实际参数需要的是当前抽象类的子类对象!
* 接口类型:调用该方法,此时实际参数需要的是接口的子实现类对象!
*
* 开发中:方法形式参数是具体类以及接口情况居多的!
*/
//定义一个接口
interface Love{
public abstract void love() ;
}
//定义一个类:LoveDemo
class LoveDemo{
public void method(Love love) {//方法的形式参数是一个接口? 接口不能new,需要接口的子实现类对象
love.love();
}
}
//需要有定义接口的子实现类,实现Love接口
class LoveImpl implements Love{
@Override
public void love() {
System.out.println("love Java!");
}
}
//测试类
public class ArgsDemo3 {
public static void main(String[] args) {
//要访问LoveDemo类中的method方法?
LoveDemo ld = new LoveDemo() ;
// Love l = new Love() ;//接口不能实例化
// ld.method(l);
//接口多态:接口名指向子实现类
Love l = new LoveImpl() ;
ld.method(l);
System.out.println("--------------------------");
new LoveDemo().method(new LoveImpl()) ;
}
}
权限修饰符的范围
package com.qf.permission_03;
/**
* 权限修饰符的范围
*
* 同一个包下的同一个类中 同一个包下的子类中/同一个包下的无关类中 不同包下的子类中 不同包下的无关类中
* private:私有 Y
* 默认修饰符 Y Y
* protected:受保护的 Y Y Y
* public:公共的/公开的 Y Y Y Y
*
*
*/
public class PermissionDemo {
public static void main(String[] args) {
PermissionDemo pd = new PermissionDemo() ;
pd.show() ;
pd.show2() ;
pd.show3() ;
pd.show4();
}
//私有
private void show(){
System.out.println("show PermissionDemo");
}
//默认修饰符
void show2(){
System.out.println("show2 PermissionDemo");
}
//受保护的
protected void show3(){
System.out.println("show3 PermissionDemo");
}
//公共的
public void show4(){
System.out.println("show4 PermissionDemo");
}
}
package com.qf.permission_03;
/**
* PeermissionDemo的子类
*/
public class PermissionDemo2 extends PermissionDemo{
public static void main(String[] args) {
//创建子类对象
PermissionDemo2 pd2 = new PermissionDemo2() ;
// pd2.show() ; 私有用不了
pd2.show2() ; //默认修饰符
pd2.show3() ; //受保护的
pd2.show4() ;//公共的
}
}
package com.qf.permission_03;
/**
* 同一个包下的无关类中
*/
public class PermissionTest {
public static void main(String[] args) {
//创建PermissionDemo类对象
PermissionDemo pd = new PermissionDemo() ;
pd.show2() ;//默认修饰符
pd.show3(); //受保护的
pd.show4(); //公共开的
}
}
-----------------------------另一种写法
package com.qf.permission_04;
import com.qf.permission_03.PermissionDemo;
/**
* 不同包下的子类中
*/
public class PermissionDemo3 extends PermissionDemo {
public static void main(String[] args) {
//创建PermissionDemo3类对象
PermissionDemo3 pd3 = new PermissionDemo3() ;
// pd3.show2() ; //默认修饰符用不了
pd3.show3(); //受保护的
pd3.show4();
}
}
package com.qf.permission_04;
import com.qf.permission_03.PermissionDemo;
/**
* 不同包下的无关类中
*/
public class PermissionTest2 {
public static void main(String[] args) {
//创建PermissionDemo类对象
PermissionDemo pd = new PermissionDemo() ;
// pd.show() ;//私有的
//pd.show2();//默认修饰符
//pd.show3() ;//受保护的
pd.show4() ;
}
}
方法的返回值问题
package com.qf.return_02;
/**
* 方法的返回值问题:
* 要么基本类型/引用数据类型
* 基本类型:简单,要什么类型,使用指定的类型接收即可!
*
*
* 研究的方法的返回值引用类型:
* 方法的返回值如果是引用类型:
* 具体类:需要返回该具体类的对象!
* 抽象类:
* 接口:
*/
class Demo{
//对两个数据求和
public int sum(int a,int b){
return a+ b;
}
}
//定义学生类
class Student{
public void study(){
System.out.println("好好学习,天天向上!");
}
}
//StudentDemo类
class StudentDemo{
public Student show(){
//?补全代码
//return Student ; 错误
//方式1:
// Student s = new Student() ;
//return s ;
//方式2:匿名对象
return new Student() ;
}
}
//测试类
public class ReturnDemo1 {
public static void main(String[] args) {
Demo d = new Demo() ;
int result = d.sum(10, 15);
System.out.println(result);
System.out.println("-------------------------");
//访问StudentDemo类中的方法
StudentDemo sd = new StudentDemo() ;
Student student = sd.show(); //show方法就是new Student()
student.study();
}
}
研究的方法的返回值引用类型:
package com.qf.return_02;
/**
* 研究的方法的返回值引用类型:
* 方法的返回值如果是引用类型:
* 具体类:需要返回该具体类的对象!
* 抽象类:需要返回该抽象类的子类对象!
* 接口:
*/
//定义一个Person类
abstract class Person{
public abstract void work() ;
}
//PersonDemo类
class PersonDemo{
public Person function(){//方法的返回值是一个抽象类
//?
// return new Person() ; 抽象类不能实例化
//方式1:抽象类多态
//Person p = new Programmer() ;
//return p;
//方式2:直接匿名对象 (创建子类对象)
return new Programmer() ;
}
}
//定义一个类,继承Person
//程序员
class Programmer extends Person{
@Override
public void work() {
System.out.println("程序员日日夜夜敲代码!");
}
}
//测试类
public class ReturnDemo2 {
public static void main(String[] args) {
//访问PersonDemo类的function方法
PersonDemo pd = new PersonDemo() ;
Person person = pd.function(); //funciton方法 本质--->创建了子类对象
person.work();
}
}
package com.qf.return_02;
import sun.util.resources.ms.CalendarData_ms_MY;
/**
* 研究的方法的返回值引用类型:
* 方法的返回值如果是引用类型:
* 具体类:需要返回该具体类的对象!
* 抽象类:需要返回该抽象类的子类对象!
* 接口:需要返回接口子实现类对象!
*/
//定义一个接口
interface Mary{ //结婚的接口
public abstract void mary() ;
}
//定义一个MaryDemo
class MaryDemo{
public Mary method(){
//?
//return new Mary() ;//接口不能new
//方式1:
//Mary mary = new MaryImpl() ;
// return mary ;
//方式2:
return new MaryImpl() ;
}
}
//需要定义接口的子实现类
class MaryImpl implements Mary{
@Override
public void mary() {
System.out.println("要结婚了,很开心...");
}
}
//测试类
public class ReturnDemo3 {
public static void main(String[] args) {
//需求:访问MaryDemo类中的method方法?
MaryDemo md = new MaryDemo() ;
Mary mary = md.method();
mary.mary();
System.out.println("--------------------------");
Mary mary2 = new MaryDemo().method();
mary2.mary();
}
}
day16
回顾&今日内容
#回顾
##形式参数问题
```markdown
研究的引用数据类型:数组,类,接口
publicvoidshow(int[] arr){} //如果数组,需要有一个数组对象
publicviodshow(具体类型变量名){//调用方法,实际参数需要创建当前这个类的对象
使用这个变量名
}
publicvoidshow(抽象类型变量名){//调用方法,实际参数需要传递当前抽象类的子类对象
///
}
publicvoidshow(接口类型变量名){//调用方法,实际参数需要传递的是当前接口的子实现类对象!
//
}
```
##返回值问题
```markdown
研究的时候引用类型:数组,类,接口
publicint[] method(int[] arr) { //返回是数组类型,需要返回数组对象
//完成了各种排序
return数组对象;
}
public具体类 method(){//返回值是具体类型,需要返回的是当前具体类的对象!
//?
//1)创建具体类对象
//return 对象名;
//2)直接使用匿名对象
returnnew类名() ;
}
public抽象类method(){//返回值是抽象类型,需要返回的是该抽象类的子类对象!
//抽象不能实例化
抽象类对象名=new子类名() ; //抽象类多态
return对象名;
//return new 子类名() ;
}
public接口method(){//返回值是接口类型,需要返回的是当前接口的子实现类对象!
//接口不能实例化
//接口多态
接口名对象名=new子实现类名() ;
return对象名 ;
//return new 接口子实现类名();
}
```
##包的含义(了解)
```
package:在真实开发中,代码需要分层,借助包名
公司域名反写.pojo:存储的实体类 举例:商品类/用户类/订单类/购物车/医生等等
Order订单类
.service:存储业务接口层 OrderService
.service.impl:业务接口实现层 OrderServiceImpl:订单业务接口实现
.dao: 存储数据访问接口(DataAccessObject:数据访问对象) OrderDao
.dao.impl: 数据访问接口实现---->访问数据库:获取数据库
.utils :存储的工具代码(自定义的工具,jdk提供/第三方提供的)
.test :测试代码-----单元测试 junit.jar包
```
##权限修饰符的范围
| |在同一个包下的同一个类中|在同一个包下的子类中/同一个包下的无关类中|在不同包下的子类中|不同包下的无关类中|
|-----------------|------------------------|-----------------------------------------|------------------|------------------|
|private私有 |Y | | | |
|默认修饰符 |Y |Y | | |
|protected受保护的|Y |Y |Y | |
|public公共的 |Y |Y |Y |Y |
----
----
----
#今日内容
##1.内部类(了解的格式)
```
分类有哪些
成员内部类
局部内部类
内部类的一些注意事项
```
##2.内部类的一种简写:针对接口/抽象类:匿名内部类(重点)
##3.数组高级排序---选择排序
##4.预习Object/String类重点功能
```
常用类
Object -->hashCode()/equals():引用类型比较
StringtoString():默认就是对象名地址值(没有意义)
clone():克隆
String 重点类(使用最多)
StringBuffer 重点
Integer 重点
Character
Random:伪随机数生成器
BigDecimal:针对小数进行精确计算
Math
Scanner:提供类判断功能
System:
java.util.Date:日期 重点类
```
内部类
什么是内部类
packagecom.qf.innerclass_01;
/**
* 什么是内部类?
* 在Java中,在一个类中定义另一个类:
* 举例
* 在类A中,定义一个类B,将类B称为类A的内部类,类A是类B的外部类!
*
* 分类:
* 成员内部类:在类中,方法外定义的类
* 局部内部类:在方法定义中定义的类
*/
classOuter{
//成员内部类
/*class Inner{
public void show(){
System.out.println("show Inner");
}
}*/
//Outer的成员方法
publicvoidmethod(){
//局部内部类
classInner{
publicvoidshow(){
System.out.println("show Inner");
}
}
System.out.println("method Outer");
}
}
//测试类
publicclassInnerClassDemo {
}
成员内部类
packagecom.qf.innerclass_01;
/**
*成员内部类:
* 在外部类中,在外部类的成员方法外
*
* 特点:
* 可以访问外部类的成员包括私有!
*
*
* 直接去访问外部类的中的成员内部类的成员方法:特有方式 (成员内部类没有private以及static修饰!)
* 外部类.内部类名 对象名 = new 外部类名().new 内部类名() ;
*/
//外部类
classOuter2{
//成员变量
public intnum=20 ;
private intnum2=50 ;
//成员内部类
classInner2{
//成员方法
publicvoidshow(){
System.out.println(num) ;
System.out.println(num2) ;
}
}
//外部类的成员方法
publicvoidmethod(){
// show() ; Outer2自己的show方法
//访问成员内部类的成员方法
//创建Inner2类对象
Inner2in=newInner2() ;
in.show() ;
}
}
//测试类
publicclassInnerClassDemo2 {
publicstaticvoidmain(String[] args) {
//创建外部类对象
//访问外部类的成员方法,间接的调用了成员内部类的成员方法
Outer2ou=newOuter2() ;
ou.method() ;
System.out.println("--------------------------------------------------") ;
//测试类中:想直接去访问外部类里面的成员内部类的show
//外部类.内部类名 对象名 = new 外部类名().new 内部类名() ;
Outer2.Inner2oi=newOuter2().newInner2() ;
oi.show() ;
}
}
成员变量所涉及的修饰符的问题
packagecom.qf.innerclass_01;
/**
* 成员内部类所涉及到的修饰符的问题:
* 有的时候不想让外部类直接去访问内部类的成员,为了保证内部类的成员安全,加入private
* 举例:
* 人有身体,身体有心脏;
* 伪代码
* class Body{
* //身体内有心脏
* //为了保证安全性,加入private修饰
* private class Heart{
* //成员方法
* public void operator(){
* System.out.println("心脏搭桥") ;
* }
* }
*
* //外部类的成员方法
* public void method(){
* if(你是外科医生){
* //创建Heart对象,去调用operator方法
* }
* }
*
*
* }
*
*
* //直接访问成员内部类中的operator方法
* 外部类名.内部类名 对象名 = new 外部类名().new 内部类名() ;
* Body.Heart bh = new Body().new Heart() ;会报错的
*
*
* 成员内部类可以使用过static修饰:
* 特点:静态的成员内部类它里面的所有 成员方法:
* 无论是静态的方法还是非静态的,访问外部类的成员:必须先为静态
*
* 想直接去访问静态的成员内部类的这些成员方法:??
*
* 外部类名.内部类名 对象名 = new 外部类名.内部类名();
*
*/
//外部类
classOuter3{
privateintnum=100;
publicstaticintnum2=20 ;
//静态修饰
staticclassInner3{ //Inner3现在看成是外部类的静态成员!
//非静态的方法
publicvoidshow(){
// System.out.println(num) ;
System.out.println(num2) ;
System.out.println("show Inner3");
}
//静态的方法
publicstaticvoidshow2(){
System.out.println(num2) ;
//System.out.println(num) ;
System.out.println("show2 Inner3");
}
}
}
//测试类
publicclassInnerClassDemo3 {
publicstaticvoidmain(String[] args) {
//访问成员内部类的成员方法
//外部类名.内部类名 对象名 = new 外部类().new 内部类名() ;
//Outer3.Inner3 oi = new Outer3().new Inner3() ; 用不了,只能针对非静态的成员内部类!
//针对静态的成员内部类:直接去访问里面的成员方法
//外部类名.内部类名 对象名 = new 外部类名.内部类名();
Outer3.Inner3oi=newOuter3.Inner3() ;//Inner3类看成是Outer3的静态成员
oi.show() ;
oi.show2() ;
System.out.println("----------------------------------------");
//show2()是静态的成员内部类的静态成员
Outer3.Inner3.show2();
}
}
局部内部类
packagecom.qf.innerclass_02;
/**
* 局部内部类:
* 在外部类的成员方法中定义的类
* 特点:
* 局部内部类也是可以直接访问外部类的成员变量,包括私有!
*
* 面试题:
* 局部内部类里面的成员在访问局部变量的时候,局部变量有什么要求?
*
* JDK8以前的版本,局部内部类在访问外部类的成员方法中的局部变量的时候,此时局部变量必须加入final修饰!
* 原因:
* 局部变量的生命周期随着方法调用而存在,随着方法调用结束而消失;
* 外部类的成员方法调用完毕,此时这个局部变量应该释放了,但是当前这个成员方法中创建局部内部类对象
* 使用局部内部类对象访问它里面的成员方法,成员方法还在使用这个局部变量,所以此时这个变量为常量,显示的加入
* final修饰
* JDK8以及jdk8以后:优化了
* 可以通过反编译工具---->自动加入final,还是定义一个常量
*/
//外部类
classOuter{
privateintnum=20 ;
//外部类的成员方法
publicvoidmethod(){
intx=200 ;
//局部内部类
classInner{
//成员方法
publicvoidshow(){
System.out.println("show Inner") ;
System.out.println(num);
System.out.println(x) ;
}
}
//创建Inner
Innerinner=newInner() ;
inner.show();
}
}
//测试类
publicclassInnerClassDemo {
publicstaticvoidmain(String[] args) {
//创建外部类对象
Outerouter=newOuter() ;
outer.method();
}
}
内部类的面试问题
packagecom.qf.innerclass_02;
/**
* 面试题
* 在控制台分别打印
* 30
* 20
* 10
*
* 内部类外部类没有继承关系,不能使用super!
*/
classOuter2{
intnum=10 ;
//成员内部类
classInner2{
intnum=20 ;
publicvoidshow(){
intnum=30 ;
//补全代码
System.out.println(num) ; //就近原则
System.out.println(this.num) ; //访问本类的成员变量
// System.out.println(new Outer2().num) ; //创建外部类对象.变量名
//this:代表当前类---->Outer2.this--->外部类的this限定(访问的是外部类中的信息)
System.out.println(Outer2.this.num);
}
}
}
//测试类
publicclassInnerClassDemo2 {
publicstaticvoidmain(String[] args) {
Outer2.Inner2oi=newOuter2().newInner2() ;
oi.show();
}
}
匿名内部类
packagecom.qf.innerclass_02;
/**
* 面试题
* 在控制台分别打印
* 30
* 20
* 10
*
* 内部类外部类没有继承关系,不能使用super!
*/
classOuter2{
intnum=10 ;
//成员内部类
classInner2{
intnum=20 ;
publicvoidshow(){
intnum=30 ;
//补全代码
System.out.println(num) ; //就近原则
System.out.println(this.num) ; //访问本类的成员变量
// System.out.println(new Outer2().num) ; //创建外部类对象.变量名
//this:代表当前类---->Outer2.this--->外部类的this限定(访问的是外部类中的信息)
System.out.println(Outer2.this.num);
}
}
}
//测试类
publicclassInnerClassDemo2 {
publicstaticvoidmain(String[] args) {
Outer2.Inner2oi=newOuter2().newInner2() ;
oi.show();
}
}
匿名内部类开发中使用场景2:方法返回值是抽象类或者接口
packagecom.qf.return_05;
/**
* 匿名内部类开发中使用场景2:
* 方法返回值是抽象类或者接口
*/
interfaceLove{
voidlove() ;
}
//LoveDemo
classLoveDemo{
publicLovemethod(){ //返回是一个接口:返回接口的子实现类对象
//?如何返回
//接口不能new
//接口多态
//Love l = new LoveImpl() ;
//return l;
//return new LoveImpl() ;
//2使用接口的匿名内部类
/**
* new 类名或者接口(){
* //重写方法
* }
*/
return newLove() {
@Override
publicvoidlove() {
System.out.println("爱生活,爱Java,爱高圆圆!");
}
};
}
}
//定义一个子实现类
classLoveImplimplements Love{
@Override
publicvoidlove() {
System.out.println("love life,love 高圆圆");
}
}
//测试类
publicclassReturnDemo {
publicstaticvoidmain(String[] args) {
LoveDemold =newLoveDemo() ;
Lovelove=ld.method(); //使用的接口匿名内部类的子实现类对象!
love.love();
}
}

1248

被折叠的 条评论
为什么被折叠?



