-
给引用类型数组的元素赋值,需要new一下
-
若想访问对象的属性或调用方法,需要通过数组元素去打点
//注意:对于引用数组而言,必须给所有元素都赋值,否则访问时会发生空指针异常 Student[] stus = new Student[3]; //创建Student数组对象 stus[0] = new Student("zhangsan",25,"LF"); //创建Student对象 stus[1] = new Student("lisi",24,"JMS"); stus[2] = new Student("wangwu",26,"SD"); System.out.println(stus[0].name); //输出第1个学生的名字 stus[1].age = 28; //修改第2个学生的年龄为28 stus[2].sayHi(); //第3个学生跟大家问好 for(int i=0;i继承: -
作用:代码复用
-
通过extends来实现继承
-
超类/父类:共有的属性和行为
派生类/子类:特有的属性和行为
-
派生类既可以访问派生类的,也能访问超类的,但超类不能访问派生类的
-
一个超类可以有多个派生类,一个派生类只能继承一个超类-------单一继承
-
具有传递性
-
java规定:构造派生类之前必须先构造超类
-
在派生类的构造方法中,若没有调用超类构造方法,则默认super()调用超类无参构造方法
-
public class SuperDemo {
public static void main(String[] args) {
Boo o = new Boo();
}
}
class Aoo{
Aoo(){
System.out.println("超类构造方法");
}
}
class Boo extends Aoo{
Boo(){
super(); //默认的,调用超类的无参构造方法
System.out.println("派生类构造方法");
}
}
在派生类的构造方法中,若自己调用了超类构造方法,则不再默认提供
注意:super()调用超类构造方法,必须位于派生类构造方法的第一行
class Coo{
Coo(int a){
}
}
class Doo extends Coo{
Doo(){
super(5); //自己调用超类构造了,则不会再默认super()
}
}
super:指代当前对象的超类对象
super的用法:
-
super.成员变量名-----------------------------访问超类的成员变量
-
super.方法名()----------------------------------调用超类的方法-----------------------明天下午讲
-
super()--------------------------------------------调用超类的构造方法
-
超类型的引用指向派生类的对象
-
能点出来什么,看引用的类型-------------这是规定,记住就可以了
多种角色能干的事都一样的时候,可以将多种角色统一造型到超类数组中,实现代码复用
eg: 学生/老师/医生都是输出名字+问好------干的事都一样,
就可以将学生/老师/医生统一造型到Person数组中,这样一个for即可----代码复用
public class UploadDemo {
public static void main(String[] args) {
Aoo o1 = new Aoo();
o1.a = 1;
o1.show();
//o1.b = 2; //编译错误,超类不能访问派生类的
//o1.test(); //编译错误
Boo o2 = new Boo();
o2.b = 1;
o2.test();
o2.a = 2; //正确,派生类可以访问超类的
o2.show(); //正确
Aoo o3 = new Boo(); //向上造型
o3.a = 1;
o3.show();
//o3.b = 2; //编译错误,能点出来什么,看引用的类型
//o3.test(); //编译错误
}
}
class Aoo{
int a;
void show(){
}
}
class Boo extends Aoo{
int b;
void test(){
}
}
方法的重写(override/overriding):重新写
-
发生在父子类中,方法名相同,参数列表相同
-
重写方法被调用时,看对象的类型
class 餐馆{
void 做餐(){ 做中餐 }
}
//1)我还是想做中餐--------------不需要重写
class Aoo extends 餐馆{
}
//2)我想改做西餐----------------需要重写
class Aoo extends 餐馆{
void 做餐(){ 做西餐 }
}
//3)我想在中餐基础之上加入西餐----需要重写(先super中餐,再加入西餐)
classs Aoo extends 餐馆{
void 做餐(){
super.做餐();
做西餐
}
}
-
重写需遵循"两同两小一大"原则:------------------------ 了解,一般都是一模一样的
-
两同:
-
方法名相同
-
参数列表相同
-
-
两小:
-
派生类方法的返回值类型小于或等于超类方法的
-
void和基本类型时,必须相等
-
引用类型时,小于或等于
-
-
派生类方法抛出的异常小于或等于超类方法的
-
-
一大:
-
派生类方法的访问权限大于或等于超类方法的
-
-
//超类大,派生类小
class Coo{
void show(){}
double test(){ return 0.0; }
Student say(){ return null; }
Person sayHi(){ return null; }
}
class Doo extends Coo{
//int show(){ return 1; } //编译错误,void时必须相等
//int test(){ return 0; } //编译错误,基本类型时必须相等
//Person say(){ return null; } //编译错误,引用类型时必须小于或等于
Student sayHi(){ return null; } //正确
}
重写与重载的区别:
-
重写(override):发生在父子类中,方法名相同,参数列表相同
-
重载(overload):发生在同一类中,方法名相同,参数列表不同
-
作用:避免类的命名冲突
-
同包中的类不能同名,但不同包中的类可以同名
-
类的全称:包名.类名,常常有层次结构
-
建议:包名所有字母都小写
import:导入类、引入类
-
同包中的类可以直接访问,但不同包中的类不参直接访问,若想访问:
-
先import导入类再访问类-------建议
-
类的全称-----------------------------太繁琐,不建议
-
访问控制修饰符:-----------------------------保护数据的安全注意:
顺序问题:package----import----class
import 包名.*; 表示导入了包中的所有类,但不建议,建议用哪个类导哪个类
------因为.*会影响性能
-
public:公开的,任何类
-
private:私有的,本类
-
protected:受保护的,本类、派生类、同包类
-
默认的:什么也不写,本类、同包类
注意:
-
java不建议默认权限
-
类的访问权限只能是public或默认的
类中成员的访问权限如上4种都可以
-
访问权限由大到小依次为:public--protected--默认的--private
-
class Card{ //银行卡
private String cardId; //卡号
private String cardPwd; //密码
private double balance; //余额
public boolean payMoney(double money){ //支付金额
if(balance>=money){
balance-=money;
return true;
}else{
return false;
}
}
public boolean checkPwd(String pwd){ //检测密码--营业员可以调用
if(pwd和cardPwd相同){
return true;
}else{
return false;
}
}
}
package ooday05;
//访问控制修饰符的演示
public class Aoo {
public int a; //任何类
protected int b; //本类、派生类、同包类
int c; //本类、同包类
private int d; //本类
void show(){
a = 1;
b = 2;
c = 3;
d = 4;
}
}
class Boo{ //----------------演示private
void show(){
Aoo o = new Aoo();
o.a = 1;
o.b = 2;
o.c = 3;
//o.d = 4; //编译错误
}
}
package ooday05_vis;
import ooday05.Aoo;
public class Coo { //----------------演示同包的
void show(){
Aoo o = new Aoo();
o.a = 1;
//o.b = 2; //编译错误
//o.c = 3; //编译错误
//o.d = 4; //编译错误
}
}
class Doo extends Aoo{ //跨包继承---------演示protected
void show(){
a = 1;
b = 2;
//c = 3; //编译错误
//d = 4; //编译错误
}
}
final:最终的、不可改变的--------------------单独应用几率低
-
修饰变量:变量不能被改变
//演示final修饰变量
class Eoo{
final int a = 5;
void show(){
//a = 55; //编译错误,final的变量不能被改变
}
}
修饰方法:方法不能被重写
修饰类:类不能被继承
static:静态的-
静态变量:
-
由static修饰
-
属于类,存储在方法区中,只有一份
-
常常通过类名点来访问
-
何时用:所有对象所共享的数据(图片、音频、视频等)
-
class Loo{
int a;
static int b;
Loo(){
a++;
b++;
}
void show(){
System.out.println("a="+a+",b="+b);
}
}
public class StaticDemo {
public static void main(String[] args) {
Loo o1 = new Loo();
o1.show();
Loo o2 = new Loo();
o2.show();
Loo o3 = new Loo();
o3.show();
System.out.println(Loo.b); //常常通过类名点来访问
}
}
静态方法:
-
由static修饰
-
属于类,存储在方法区中,只有一份
-
常常通过类名点来访问
-
静态方法中没有隐式this传递,所以不能直接访问实例成员
-
何时用:方法的操作与对象无关
//演示静态方法
class Moo{
int a; //实例变量(对象来访问)
static int b; //静态变量(类名点来访问)
void show(){ //有this
System.out.println(this.a);
System.out.println(Moo.b);
}
static void test(){ //没有this
//静态方法中没有隐式this传递,
//没有this就意味着没有对象,
//而实例变量a是必须通过对象点来访问的
//所以如下语句发生编译错误
//System.out.println(a); //编译错误
System.out.println(Moo.b);
}
}
静态块:
-
由static修饰
-
属于类,在类被加载期间自动执行,因为一个类只被加载一次,所以静态块也只执行一次
-
何时用:加载/初始化静态资源(图片、音频、视频等)
//演示静态块
class Poo{
static{
System.out.println("静态块");
}
Poo(){
System.out.println("构造方法");
}
}
public class StaticDemo {
public static void main(String[] args) {
Poo o4 = new Poo();
Poo o5 = new Poo();
Poo o6 = new Poo();
}
}
day06
static final常量:应用率高
-
必须声明同时初始化
-
常常由类名点来访问,不能被改变
-
建议:常量所有字母都大写,多个单词用_分隔
-
编译器在编译时会将常量直接替换为具体的值,效率高
-
何时用:数据永远不变,并且经常使用
public class StaticFinalDemo {
public static void main(String[] args) {
System.out.println(Aoo.PI); //常常通过类名点来访问
//Aoo.PI = 3.1415926; //编译错误,常量不能被改变
//1)加载Boo.class到方法区中
//2)静态变量num一并存储在方法区中
//3)到方法区中获取num的值并输出
System.out.println(Boo.num);
//编译器在编译时会将常量直接替换为具体的值,效率高
//相当于System.out.println(5);
System.out.println(Boo.COUNT);
}
}
class Boo{
public static int num = 5; //静态变量
public static final int COUNT = 5; //常量
}
class Aoo{
public static final double PI = 3.14159;
//public static final int NUM; //编译错误,常量必须声明同时初始化
}
抽象方法:
-
由abstract修饰
-
只有方法的定义,没有具体的实现(连{}都没有)
-
由abstract修饰
-
包含抽象方法的类必须是抽象类
-
抽象类不能被实例化
-
抽象类是需要被继承的,派生类:
-
重写抽象方法(变不完整为完整)-----------一般做法
-
也声明为抽象类-------------------------------一般不这么做
-
-
抽象类的意义:
-
封装共有的属性和行为--------------------代码复用
-
为所有派生类提供统一的类型-----------向上造型(代码复用)
-
可以包含抽象方法,为所有派生类提供统一的入口(造型之后能点出来),同时可以达到强制必须重写的目的(相当于制定一个规则)
-
-
类中套类,外面的称为外部类,里面的称为内部类
-
内部类只服务于外部类,对外不具备可见性
-
内部类对象通常在外部类中创建
-
内部类中可以直接访问外部类的成员(包括私有的),
内部类中有一个隐式的引用指向创建它的外部类对象-----外部类名.this---后面API中会用
//成员内部类的演示
public class InnerClassDemo {
public static void main(String[] args) {
Mama m = new Mama();
//Baby b = new Baby(); //编译错误,内部类对外不具备可见性
}
}
class Mama{ //外部类
private String name;
void create(){
Baby b = new Baby(); //正确,内部类对象通常在外部类中创建
}
class Baby{ //成员内部类
void showName(){
System.out.println(name); //简写
System.out.println(Mama.this.name); //完整写法
//System.out.println(this.name); //编译错误,当前Baby类没有name属性
}
}
}
匿名内部类:
-
何时用:若想创建一个类(派生类)的对象,并且对象只被创建一次,可以设计为匿名内部类,可以大大简化代码操作
-
在匿名内部类中不能修改外面局部变量的值,因为在此处该变量会被默认为final的---API时用
-
小面试题:
-
问:内部类有独立的.class字节码文件吗?
-
答:有
-
//匿名内部类的演示
public class NstInnerClassDemo {
public static void main(String[] args) {
//1)创建了Aoo的一个派生类,但是没有名字
//2)为该派生类创建了一个对象,名为o1----向上造型为Aoo类型
// ---new Aoo(){}是在创建Aoo的派生类的对象
//3)大括号中的为派生类的类体
Aoo o1 = new Aoo(){
};
//1)创建了Aoo的一个派生类,但是没有名字
//2)为该派生类创建了一个对象,名为o2----向上造型为Aoo类型
// ---new Aoo(){}是在创建Aoo的派生类的对象
//3)大括号中的为派生类的类体
Aoo o2 = new Aoo(){
};
int num = 5;
num = 55;
//1)创建了Boo的一个派生类,但是没有名字
//2)为该派生类创建了一个对象,名为o3----向上造型为Boo类型
//3)大括号中的为派生类的类体
Boo o3 = new Boo(){
void show(){
System.out.println("showshow");
//num = 55; //在此处会默认外面的局部变量num为final的
}
};
o3.show();
}
}
abstract class Boo{
abstract void show();
}
abstract class Aoo{
}



