欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JAVA基础面向对象

程序员文章站 2022-06-07 20:08:50
...

/**

  • 方法的演示
  • 方法::也称函数,或者叫过程
  • 1.用于封装一段特定的逻辑功能
  • 2.尽可能的独立,只干一件事
  • 3.优点
  • 3)可以被调用多次(避免代码重复、结构清晰)
  • 4)结构清晰、便于维护( 便于维护、便于合作开发)
  • 方法的定义:
  • 修饰词 返回值类型 方法名(参数列表){ 方法体 }
  • 注意:
  •  1)方法可以有参也可以无参,有参更灵活
    
  •  2)方法可以有返回值也可以没有返回值: 无返回值,返回值类型写void
    
  •                 					有返回值,返回值类型写具体的数据类型
    
  •  								(java语法规定,方法在声明时必须指定返回值类型)
    
  •  3)方法体中return:return语句的作用在于结束方法且将数据返回给调用方。
    
  •  				  有返回值:1.结束方法的执行  2.返回结果给调用方
    
  •  						  return后的表达式类型必须与方法定义的返回类型匹配
    
  •  				  无返回值:return;1.结束方法的执行
    

*何时有返回值?何时没有返回值?
*规律:
*若方法执行完后,方法外面需要该方法中的某个数,就有返回值
若方法执行完后,方法外面不需要该方法中的某个数,就没有返回值
*
/
public class MethodDemo {
public static void main(String[] args) {
/

* 方法的调用
* 无返回值方法: 方法名(有参传参);
* 有返回值方法: 数据类型 变量 = 方法名(有参传参);
* 方法名(有参传参);------几乎不用
/
/

* 无参方法调用:方法名();
/
say();
/

* 有参五返回值方法调用:必须传参数,参数类型必须匹配:方法名(有参传参);
/
//sayHi(); //编译错误,必须传参数
//sayHi(8); //编译错误,参数类型不匹配
sayHi(“zhangsan”); //String name=“zhangsan”
sayHi(“lisi”); //String name=“lisi”
sayHi(“wangwu”); //String name=“wangwu”
/

* 无参有返回值方法调用: 数据类型 变量 = 方法名();
/
int num = getNum();
System.out.println(num); //88
/

* 有参有返回值方法调用: 数据类型 变量 = 方法名(有参传参);
/
double d = plus(5,6); //double num1=5,double num2=6
System.out.println(d); //11
double a = 5.5;
double b = 4.4;
double dou = plus(a,b); //double num1=5.5,double num2=4.4
System.out.println(dou);
a(); //方法的嵌套调用
System.out.println(“over”);
}
/

* 方法的嵌套:方法中调方法
*/
public static void a(){
System.out.println(111);
b();//方法的嵌套调用
System.out.println(222);
}
public static void b(){
System.out.println(333);

}
//有参有返回值
public static double plus(double num1,double num2){
	//double num = num1+num2;
	//return num; //返回的不是num,而是num里面那个数
	return num1+num2; //返回的是num1+num2的值
}

//无参有返回值
public static int getNum(){
	//return; //编译错误,必须返回一个值
	//return 5.55; //编译错误,返回值类型不匹配
	return 88; //1.结束方法的执行  2.返回结果(250)给调用方
}

//有参无返回值
public static void sayHi(String name){
	System.out.println("大家好,我叫"+name);
	return; //1.结束方法的执行
}

//无参无返回值
public static void say(){
	System.out.println("大家好,我叫WKJ");
}	

}

/*
*一. 面向过程:数据+方法

  • 面向过程的缺陷:
  •  1.缺乏对数据的封装(在main方法中所定义的变量并无直接关系)。
    
  •  2.数据和方法(操作数据的)的分离(参数错了容易出错)
    
  • 二.解决方案:面向对象
  • 类:数据(成员变量)+方法(1.构造方法给成员变量赋值2.类方法:类的行为和功能)
  • 1.面向对象的第一步就是抽象数据类型,所谓抽象数据类型可以理解为:将不同类型的数
  • 据的集合组成个整体用来描述一种新的事物。(自造的数据类型)
  • 2.类定义了一种抽象数据类型,而类不但定义了抽象数据类型的组成(成员变量),
  • 同时还定义了对该类型可以实施的操作(方法)。
  • 三.
  • 1.什么是类?什么是对象?
  • 1)现实世界是由很多很多对象组成的 基于对象抽出了类( 类:类型、类别,代表一类个体 泛指)
  • 2)对象:真实存在的单个的个体(特指:此创建对象的过程也通常称为实例化具体那一个)
  • 3)类中可以包含:
  •  3.1)所有对象所共有的属性/特征---变量(成员变量)
    
  •  3.2)所有对象所共有的行为--------方法
    
  • 4)类是对象的模板,对象是类的具体的实例
  • 2.定义类的方法:
  •  	类的修饰词(默认public或者不写)  class{成员变量类型+变量名称  类方法   }
    
  • 注意:一个文件中,可以包含多个类但是public修饰的类只能有一个,并且public修饰的类必须与文件同名

*/

public class Student {//学生类
String name; //成员变量
int age;
String address;

void study(){ //方法
	System.out.println(name+"在学习...");
}
void sayHi(){
	System.out.println("大家好,我叫"+name+",今年"+age+"岁了,家住"+address);
}

}

package oo.day01;
//学生类的测试类
public class StudentTest {
public static void main(String[] args) {
/*
* 使用new关键字创建学生对象
* new运算的语法为: new 类名();此创建对象的过程也通常称为实例化。
* 类名+引用=new 类名(参数)如果有空的构造也可以:类名+引用=new 类名()
* new之后,所有成员变量都有一个默认的初始值:
* 成员变量如果是:数值类型(byte,short,char,int,long,float,double)默认:0
* boolean类型:false 引用类型NULL
* 为了能够对实例化的对象进行访问控制,需一个特殊的变量,即引用。(zs)
* 引用类型变量可以存储该类对象的地址信息,通常称为“指向该类的对象”,
* 当一个引用类型变量指向该类的对象,就可以通过这个变量对对象实施访问。
* (除8种基本类型之外,用类、接口、数组等声明的变量都称为引用类型变量,简称“引用”)
/
Student zs = new Student();
/

* 访问成员变量:引用.成员变量
/
zs.name = “zhangsan”;
zs.age = 25;
zs.address = “河北廊坊”;
/

* 调用类中的方法:1.无返回值:引用.方法名(有参传参)2.:有返回值: 返回值类型 a=引用.方法名(有参传参)
* 能.出什么看类型
*/
zs.study();
zs.sayHi();
//new之后,所有成员变量都有一个默认的初始值
Student ww = new Student();
ww.study();
ww.sayHi();
/*引用类型变量存储的是对象的地址信息:引用类型之间画等号:指向同一个对象.
* 1)对其中一个引用的修改会影响另外一个 原因:对象只有一份 eg:房子钥匙(一个对象)
* 2)基本类型之间画等号:赋值 1)对其中一个变量的修改不会影响另外一个 原因:数据有两份
* eg:身份证复印件(两份身份证)
/
Student ls=zs;
/

* null和NullPointerException
* null: 1)空,不指向任何对象
* 2)对null值做任何操作都是不合理的, 报空指针异常(NullPointerException)
* 对没有指向对象的引用使用(赋值,调方法啊),
*/
Student st=null;
System.out.println(st.age);//报空指针异常(NullPointerException)

}

}

/*

  • Java语法规定,一个类中不可以有两个方法签名(方法名+参数列表)完全相同的方法。
  • 一个类中不可以有两个方法的方法名和参数列表都完全相同。
  • 如果一个类的两个方法只是方法名相同而参数列表不同,是可以的。(即方法的重载)
  • 方法的重载(overload):
  • 1)在同一个类中,方法名称相同,参数列表不同(参数的类型,个数,顺序有关、但是和返回值类型,参数名称无关)
  • 2)编译器根据签名来绑定调用不同的方法
  • 3)遵循“编译期绑定”看引用类型调用方法(使用哪个类的方法看引用类型,具体调用哪个的看签名)
    */
    //重载的演示
    public class OverloadDemo {
    public static void main(String[] args) {
    Aoo o = new Aoo();
    o.say();
    o.say(“zhangsan”);
    o.say(25);
    o.say(“zhangsan”, 25);
    o.say(25, “zhangsan”);
    }
    }

class Aoo{
void say(){}
//int say(){return 1;} //编译错误,与返回值类型无关
void say(String name){}
//void say(String address){} //编译错误,与参数名称无关
void say(int age){}
void say(String name,int age){}
void say(int age,String name){}

}

/*1.构造方法:构造函数、构造器、构建器

  • 1)给成员变量初始化

  • 2)与类同名,没有返回值类型

  • 3)在创建对象(new)时被自动调用

  • 4)若自己不写构造,则编译器默认提供一个无参构造, 若自己写了构造,则编译器不再默认提供

  • 5)构造方法可以重载

  • 2.构造方法语法结构

  • 1)构造方法的名称必须与类名相同。

  • 2)构造方法没有返回值,但也不能写void。

  • 3)【访问修饰符】类名( ) {构造方法体}访问修饰符只能是public或者不写

  • 3.类方法和构造方法的区别:

  • 1)类方法:是描述对象的行为,封装对象的功能。构造方法给成员变量初始化的。

  • 2)语法上:【访问修饰符】返回值类型 方法名称(参数列表) {方法体 }
    */
    public class Student {
    String name;
    int age;
    /*this:指代当前对象,哪个对象调指的就是哪个对象 在方法中访问成员变量之前默认有个this.
    *this的用法:

    • 1)this.成员变量名-----访问成员变量
    • 2)this.方法名()-------调用方法
    • 3)this()--------------调用构造方法
      */
      public Student() {}//默认的构造方法
      public Student(String name, int age) {
      super();
      this.name = name;
      this.age = age;
      }
      void study(){
      System.out.println(name+“在学习…”);
      }
      void sayHi(){
      System.out.println(“大家好,我叫”+name+",今年"+age+“岁了”);
      }

    /*

    • 构造方法的重载
    • 1.声明:Cell ( int row , int col ) {}调用:Cell c1 = new Cell ( 5 , 6 );
    • 2.声明:Cell ( ) { } 调用:Cell c1 = new Cell ( ) ;
    • this()--------------调用构造方法
    • 3.声明:Cell (int row) {this(row , row );}调用:Cell c1 = new Cell ( 5 ) ;
      */

}

//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;
      }
      }

/*

  • 向上造型:
  • 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(){}
}

/**
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©; //编译错误,使用之前必须初始化
    //a = 55; //编译错误,final的变量不能被改变
    }
    }

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;
}
}

/*
在java语言中,子类可以重写(覆盖)继承自父类的方法,
即方法名和参数列表与父类的方法相同,但是方法的实现不同。
子类重写了父类的方法后,该重写方法被调用时
(无论是通过子类的引用调用还是通过父类的引用调用),运行的都是子类重写后的版本。
1.方法的重写(override):重新写、覆盖
1)发生在父子类中,方法名称相同,参数列表相同,方法体不同。
2)重写方法被调用时,看对象的类型。
/
//重写的演示
public class OverrideDemo {
public static void main(String[] args) {
/

* 重写遵循"两同两小一大"原则:一般都是完全相同的
* 1.两同:
* 1)方法名相同
* 2)参数列表相同
* 2.两小:
* 1)子类的返回值类型小于或等于父类的
* 1.1)基本类型和void时,必须相同
* 1.2)引用类型时,小于或等于
* 2)子类抛出的异常小于或等于父类的–异常之后
* 3.一大:
* 1)子类的访问权限大于或等于父类的–访问控制修饰符后
*/
}
}

//父类大,子类小
class Aoo{
void show(){}
double say(){return 0.0;}
Aoo get(){return null;}
Boo test(){return null;}
}
class Boo extends Aoo{
void show(){} //void时必须相同
double say(){return 2.2;} //基本类型时必须相同
Boo get(){return null;} //正确的,小于
//Aoo test(){return null;} //错误的,只能小于或等于
}

package oo.day04;
/**
重写与重载的区别----常见面试题
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();
}
}

/**
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();
}
}
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(),即父类的构造方法,->执行非静态代码块-〉执行本类的构造函数-〉执行其他代码
下面通过一个案例进行解析:

public class DaiMaKuai {
static {
System.out.println(“大家好我是静态代码块!”);
}

{
	
	System.out.println("大家好我是构造代码块!");

}

public DaiMaKuai(){
	System.out.println("大家好我是构造方法!");

}

}

入口类:

package day08;

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();

}

}

输出:

河南科技大学!
洛阳牡丹甲天下!

大家好我是静态代码块!
大家好我是构造代码块!
大家好我是构造方法!

大家好我是构造代码块!
大家好我是构造方法!

/**
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(){} //编译错误,默认抽象方法,不能有方法体
}

//求一组图形中的最大面积
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)由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
cc;
}
}
class Circle extends Shape{ //0.0796
public Circle(double c){
this.c = c;
}
public double area(){
return 0.0796
c*c;
}
}
/**
可以总结出如下几点抽象类和接口的区别:
1.一个类只能继承一个抽象类,但可以实现多个接口。
2.抽象类中可以包含抽象方法和非抽象方法,而接口中的所有方法均为抽象的。所以的变量都是常量必须声明时初始化。
3.子类继承抽象类必须实现抽象类中所有抽象方法,否则子类也必须是抽象类。
而子类实现接口则必须实现接口中的所有抽象方法。
设计规则:
1)将公共的属性和行为,抽到父类中
2)所有子类行为都一样,做成普通方法 所有子类行为不一样,做成抽象方法
3)符合既是也是的规则,使用接口(部分子类共有的行为)
4)将程序的任务,流程,步骤写到测试类中
*/

/**
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; //编译错误,必须声明同时初始化
}

/**
成员内部类:
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属性
}
}
}

/**
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{}

/**
匿名内部类:
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)表现形式:
重写、重载
*/

相关标签: java面向对象