类和面向对象
类是对象的抽象,它用于描述一组对象的共同特征和行为。
对象的创建和使用’
类名 对象名称=new 类名();
通过对象的引用来访问对象所有成员,格式如下
对象引用.对象成员
实现封装--->>private关键字(私有的):
· 是一个权限修饰符
· 可以修饰成员(成员变量和成员方法)
· 作用是保护成员不被别的使用,被private修饰的成员只能在本类中才能访问
针对private修饰的成员变量,如果被其他类所使用,则需要
· 提供“get变量名()”的方法,用于获得成员变量的值,方法用“public”修饰
· 提供“set变量名(参数)”的方法,用于设置成员变量的值,方法用“public”修饰
class Student(){
private String name; //将name属性私有化
private int age; // 将age属性私有化
//下面是共有的getXxxx()和getXxx()方法
public String getName(){
return name;
}
public String setName(String stuName){
name = stuName;
}
public int getAge(){
return age;
}
public int setAge(int stuAge){
//下面是对传入参数进行检查
if(stuAge <= 0){
System.out.println("年龄不合法...");
}else{
age = stuAge; //对属性赋值
}
}
public void introduce(){
System.out.println("大家好,我叫"+name+",我今年"+age+"岁了");
}
public class Example01(){
public static void main(String[] args){
Student stu = new Student();
stu.setAge(-30);
stu.setName("李芳");
stu.introduce();
}
}
运行结果
年龄不合法...
大家好,我叫李芳,我今年0岁了
构造方法
构造方法的定义
· 方法名和类名相同
· 在方法名前面没有返回值类型的声明
· 在方法中不能使用 return 语句返回一个值
在Jave中的每个类都至少有一个构造方法,如果在一个类中没有定义构造方法,系统会自动为这个类创建一个默认的构造方法,这个默认的构造方法没有参数,在其方法体中没有任何代码,即使什么也不做。
classs Person(){
//下面是类的构造方法
public Person() {
System.out.println("无参的构造方法被调用了");
}
}
public class Example02(){
public static viod main(String[] args){
Person p = new Person();
}
}
运行结果:
无参的构造方法被调用了...
在一个类中除了定义无参的构造方法,还可以构造有参的构造方法。当Person类被调用时有参数,则值会传入有参的构造的方法中。
构造方法的重载
在一个类中可以定义多个构造方法,只要每个构造方法的参数类型或参数个数不同即可。
class Person(){
String name;
int age;
//定义两个参数的构造方法
public Person(String con_name,int con_age){
name = con_name; //为name属性赋值
age = con_age; //为age属性赋值
}
//定义一个参数的构造方法
public Person(String con_name){
name = con_name; //为name属性赋值
}
public void speak(){
//打印name和age的值
System.out.println("大家好,我叫"+name+",我今年"+age+"岁了");
}
}
public class Example03(){
public static void main(String[] args){
//分别创建两个对象p1和p2
Person p1 = new Person("张杰");
Person p2 = new Person("李芳",18);
//通过对象p1和p2调用speak()方法
p1.speak();
p2.speak();
}
}
运行结果
大家好,我叫张杰,我今年0岁了
大家好,我叫李芳,我今年18岁了
Person类中定义了两个构造方法,他们构成了重载。在创建p1对象和p2对象时,根据传入的参数的不同,分别调用不同的构造方法。
this关键字:
成员变量和局部变量同名冲突时候,用this访问成员变量,否则会默认访问局部变量。
标准类的制作:
1. 成员变量
· 使用 private 修饰
2 .构造方法
· 提供一个无参的构造方法
· 提供一个带多个参数的构造方法
3. 成员方法
· 提供一个成员变量对应setXxx()和getXxx()
`提供一个展示对象参数的print
//标准类的制作
public class Student {
//成员变量用private修饰
private String name;
private int age;
//构造方法:一个无参方法,一个多参构造方法
public Student(){}
public Student(String name,int age){
this.name=name;
this.age=age;
}
//成员方法
public void setName(String n){
this.name=n;
}
public String getName(){
return name;
}
public void setAge(int a){
this.age=a;
}
public int getAge(){
return age;
}
public void show(){
System.out.println(name+","+age);
}
}
static关键字(声明周期)
定义一个类时,只能描述某类事物的特征和及行为,并没有产生具体的数据。只能通过new创建该类的实例对象后,系统才会为该对象提供空间。有时候,我们需要某些特定的数据在内存中,只有一份,而且能够被一个类的所有实例对象共享,例如一个学校所有学生共享同一个学校名称,此时不必要在每个学生对象所占用的内存空间中都定义一个变量来表示学校的名称。所以就需要一个静态变量被所有实例所共享,出现了static
1.它用于修饰成员变量时,被称为“ 静态变量”,可以使用 “类名.变量名” 来访问
static只能用于修饰成员变量,不能用于修饰局部变量,否则编译器会报错
2.静态方法:不创建对象,可以调用该方法(也就是该方法不必和对象绑在一起)。用 “类名.方法名”来访问
3.静态代码块:当类被加载时,静态代码块会执行,由于类只加载一次,因此静态代码块只执行一次(类在第一次使用时才被加载)。(通常用于对类的成员变量的初始化)
类的继承
一、继承 extends
如果一个类没有指定父类,那就默认继承Object
一个子类只能继承一个直接父类(单继承),多个子类可以继承一个父类,多层继承是可以的。
子类只能继承父类的属性和方法,但构造方法不能继承
1.继承中变量的访问
在子类中访问一个变量
· 子类局部范围找
· 子类成员范围找
· 父类成员范围找
· 如果没有就报错(不考虑父亲的父亲)
2.继承的成员方法的访问特点
通过子类访问一个方法
· 子类成员范围找
· 父类成员范围找
· 如果没有就报错(不考虑父亲的父亲)
3.this和super
关键字 | 访问成员变量 | 访问构造方法 | 访问成员方法 |
this | this.成员变量 访问本类成员变量 | this(....) 访问本类构造方法 | this.成员方法(...) 访问本类成员方法 |
super | super.成员变量 访问父类成员变量 | super(...) 访问父类构造方法 | super.成员方法(...) 访问父类成员方法 |
4.继承中构造方法的访问特点:
子类中所有构造方法都会默认访问父类无参的构造方法
5.方法的重写
子类出现与父类一样的继承方法时,就需要方法的重写
在子类中定义一个相同名字的方法(子类方法的改写)
@Override
· 是一个注解
· 可以帮助我们检查重写方法的正确性
注意事项:
· 私有方法不能被重写(父类的私有成员子类是不能不继承)
· 子类方法访问权限不能更低(public > 默认 > 私有)
7.继承的主义事项
(1)单一继承
(2)多层继承
二、修饰符
1.权限修饰符
修饰符 | 同一类中 | 同一包中子类无关类 | 不同包中的子类 | 不同包中的无关类 |
private | ✓ | |||
默认 | ✓ | ✓ | ||
protected | ✓ | ✓ | ✓ | |
public | ✓ | ✓ | ✓ | ✓ |
2.状态 修饰符
. final(最终态)
. static (静态)
(1)final修饰的特点
. 修饰方法:表明该方法是最终方法,不能被重写
. 修饰变量:表明该变量是常量,不能被再次赋值
. 修饰类:表明最终类,不能被继承
(2)static修饰的特点
. 被类的所有对象共享
这也是我们判断是否使用静态关键字的条件
. 可以通过类名调用
也可以通过对象名调用
推荐使用类名调用
访问特点:
静态只能访问静态,不能访问非静态
三、多态
多态的形式,具体类多态,抽象类多态,接口多态。
·成员变量: 编译看左边,执行看左边
· 成员方法:编译看左边,执行看右边
1.什么是多态
同一对象,在不同时刻表现出不同的形态
举例:猫
我们可以说猫是猫: 猫 cat = new 猫();
我们也可以是说猫是动物 : 动物 Animal = new 猫();
这里是猫在不同时刻表现得不同得形态,这就是多态
多态的前提和体现
· 有继承/实现关系
· 有方法重写
· 有父类引用指向子类对象
2.多态成员的访问特点
Animal a = new Cat();
· 成员变量:编译看左边,执行看右边
· 成员方法:编译看左边,执行看右边
3.多态的好处和弊端
· 好处:提高程序的拓展性
具体实现:定义方法的时候,使用父类作为参数,将来使用的时候,使用具体的子类类型参与操作
· 弊端:不能使用子类的特有功能
4.多态中的转型
· 向上转型
从子到父
父类引用指向子类的对象
· 向下转型
从父到子
父类引用转为子类对象
向上转型、向下转型的实例:
//向上转型
Animal a = new cat();
a.eat();
//向下转型
Cat c = (Cat)a;
c.eat();
抽象类abstract
当定义一个类时,常常需要定义一些方法来描述该类的行为特征,但有时这些方法的实现是无法确定的。例如:定义一个Animal类,shout()类用于表示动物的叫声,但是针对不同的动物,叫声也不同,在shout()方法中无法准确的描述叫声。
针对上面的描述的情况,java允许在定义方法是不写方法体,不包含方法体的方法为抽象方法,(也就是只声明没有具体定义)抽象方法必须用abstract关键字修饰
1.抽象类的定义
在java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类
2.抽象类的特点
· 抽象类和抽象方法必须使用 abstract 关键字修饰
public abstract class 类名{};
public abstract void eat();
· 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
· 抽象类不能实例化(因为抽象类中可能包含抽象方法,抽象方法是没有方法体的,不可以被调用)
那么抽象类如何实例化?参照多态的方法,通过子类对象实例化,叫抽象多态(子类实现父类的抽象方法后可以正常进行实例化)
· 抽象类的子类
要么重写抽象类中的抽象方法
要么是抽象类
3.抽象类中成员的特点
· 成员变量
可以是变量
也可以是常量
· 构造方法
有构造方法(用于子类访问父类数据的初始化),但不能实例化
· 成员方法
可以有抽象方法:限子类必须完成某些动作
也可以有非抽象方法:提高代码复用性
//抽象类的实例化
//定义抽象类
abstract class Animal{
//定义抽象方法shout
abstract void shout();
}
//定义Dog类继承抽象类Animal
class Dog extends Animal{
//实现抽象方法shout()
void shout(){
System.out.println("汪汪...");
}
}
//定义测试类
public class Example05{
public static void main(String[] args){
Dog dog = new Dog(); //创建Dog类的实例对象
dog.shout(); //调用dog对象是的shout()手套
}
}
运行结果
汪汪...
子类实现父类的抽象方法后,可以正常进行实例化
五、接口interface
1.接口的特点
接口就是一种公共资源规范,只要符合规范,大家都可以用
Java中的接口更多的体现在对行为的抽象
· 成员变量
只能是常量
默认修饰符 :public static final(即全局常量)
·构造方法
接口没有构造方法,因为接口是对行为的抽象,是没有具体存在的
一个类如果没有父类,默认继承Object类
· 成员方法
接口只能是抽象方法
默认标识符:public abstract (即抽象方法)
接口可以一个使用了extents关键字去继承另一个类
//接口的继承
//定义一个Animal接口
interface Animal{
int ID = 1; //定义一个全局常量
void breathe(); //定义抽象方法breaehe()
void run(); //定义抽象方法run()
}
//定义一个接口并继承接口
interface LandAnimal extends Animal{
void liveOnland();
}
//定义类实现LandAnimal接口
class Dog implements LandAnimal{
//实现 breathe()方法
public void breathe(){
System.out.println("小狗在呼吸");
}
//实现 run()方法
public void run(){
System.out.printlbn("小狗在跑步");
}
//实现liveOnland()方法
public void liveOnlive(){
System.out.prinfln("修勾生活在陆地上");
}
}
//测试类
public class Example12{
public static void main(String args[]){
Dog dog = new Dog();
dog.braathe();
dog.run();
dog.liveOnlive();
}
}
运行结果
小狗在呼吸
小狗在跑步
修勾生活在陆地上
因为接口中方法都是抽象方法,因此不能通过实例化的对象来调用接口中的方法,需要定义 一个类,并使用implements关键字来实现接口中的所有方法。
接口最后总结:
1. 接口中的方法都是抽象的,不能被实例化
2. 当一个类实现接口时,如果这个类是抽象类,则实现接口中的部分方法即可,否则需要实现接口中的所有方法
3. 一个类通过implements关键字实现接口时,可以实现多接口,被实现的多个接口之间,要用逗号隔开,如下
interface Run{
程序代码。。。
}
interface Fly{
程序代码。。
}
class Dog implement Run,Fly{
//很ok,dog会飞也会跑
}
抽象类和接口的关系
· 成员区别
抽象类 变量,常量; 有构造方法,也有抽象方法
接口 常量; 抽象方法
· 关系区别
类与类 继承 ,单继承
类与接口 实现,可以单实现,也可以多实现
接口与接口 继承,单继承,多继承
· 设计理念区别
抽象类 对类抽象,包括行为、行为
接口 对行为抽象,主要是行为
内部类
根据内部类的位置、修饰符和定义的方式可分为成员内部类、静态内部类、方法内部类。
1.1成员内部类
在一个类中除了可以定义成员变量、成员方法,还可以定义类,这样的类被称为 成员内部类。
在成员内部类中可以访问外部类的所以成员,通过下面的例子学习定义成员内部类
class Outer {
private int num = 4; //定义类的成员变量
//下面的代码定义一个成员方法,方法中访问内部类
public void test{
Inner inner = new Ineer;
inner.show();
}
//下面的代码定义了一个成员内部类
class Inner {
void show(){
//在成员内部类的方法方法中访问外部类的成员变量
System.out.println("num = "+num);
}
}
public class Example16{
public static void main(String[] args){
Outer outer = new Outer(); //创建外部类对象
outer.test(); //调用test()方法
}
}
运行结果:
num = 4
从运行结果来看,内部类在外部类中可以被使用,并能够访问外部类的成员。
1.1.2
内部类想通过外部类去访问内部类,则需要通过外部类对象去创建一个内部类对象,创建内部类对象的具体格式:
外部类名.内部类名 变量名 = new 外部类名().new 内部类名();
//将Example16的main函数部分改成 显示结果不变
Outer.Inner inner = new Outer.Inner();
Inner.show();
需要注意的是:如果内部类被声明为声明为私有,外界无法访问
1.2静态内部类
使用static关键字来修饰成员内部类,该类被称为 静态内部类
作用:可以在不创建外部对象的情况下被实例化
创建静态内部类对象 的格式如下:
外部类名.内部类名 变量名 = new 外部类名.内部类名
注意:
1)在静态内部类中只能访问外部类的静态变量
2)在静态内部类中可以定义静态成员,而在非静态的内部类中不允许定义定义静态成员
1.2.3方法内部类
方法内部类是指成员方法中定义类,它只能在当前方法中被使用。