类和对象
什么是类?
● 概念:具有相同特征(同一类)事物的抽象描述,如人类,车类,学生类等。
类的结构:
● 变量: 事物属性的描述(名词)
● 方法: 事物的行为(可以做的事情 动词)
● 构造方法: 初始化对象
● 块: 一段没有名称的代码块
● 内部类: 即在类体中声明的类
如何写一个类?
第一步----发现类
第二步----定义类的成员变量
第三步----定义类的成员方法
第四步----使用类创建对象
/*定义一个学生类(发现类)*/
public class Student {//定义类的成员变量String name ;int age;String gender;//定义类的成员方法public void study(){System.out.println("学生要好好学习");}public void excise(){System.out.println("学生要多运动");}public static void main(String[] args) {//使用类创建对象Student student = new Student();//调用类中的成员方法,成员变量student.study();student.name = "小王";}
}
什么是对象?
● 概念:对象是类的实例,以类为模版,在内存中创建出一个实际存在的实例。
我们使用new关键字来创建一个新的对象。
构造方法
分类:构造方法分为 无参构造方法 和 有参构造方法。
特点:
● 在一个类中可以有多个构造方法 ( 构造方法可以重载 ).
● 方法名与类名相同,没有返回值,且不需要void修饰。
● 如果一个类没有定义构造方法,Java会提供一个默认的无参构造方法。如果一个类定义了构造 方法,Java将不会提供默认构造方法。
● 构造方法在使用new关键字实例化对象时自动调用。
作用:
● 构造方法的作用是初始化对象的状态,可以在构造方法中为对象的实例变量赋初值。
public class Student {String name ;int age;String gender;//无参构成方法public Student(){name = "小张";age = 18;gender = "男";System.out.println(name+age+gender);}//有参构成方法public Student(String name,int age,String gender){this.name=name;this.age=age;this.gender=gender;System.out.println(name+age+gender);}public static void main(String[] args) {// 使用构造方法创建对象,并初始化Student student = new Student();//调用无参构造方法Student student1 = new Student("小魏",20,"女");//调用有参构造方法}
}
方法的重载
● 在一个类中有多个名称相同的方法,如何在调用时区分同名的方?
通过方法的参数的个数,类型,顺序;
● 方法的重载与返回值类型无关
public class Student {String name ;int age;String gender;//有参构成方法的重载public Student(String name,int age,String gender){}public Student(int age,String name,String gender){//通过参数顺序区分}public Student(String name,int age){//通过参数个数区分}
}
this关键字
● 在一个类的内部可以使用this关键字来引用成员变量名,区分成员变量和局部变量.
● this在类中表示当前正在访问的对象
//this在类中用来表示当前正在访问的对象, this.成员变量名--显示的访问当前对象的成员变量public Person(String name,int age,String gender){this.name = name;this.age = age;this.gender = gender;}
static关键字
介绍:
● static---静态,可以修饰类中的成员变量,成员方法,代码块,内部类(不能修饰构造方法)
● 修饰成员变量
静态成员变量也称类变量,在内存中只有一份,所有对象可以共享,一般情况下,将类中所有 对象都相同的属性设置为静态的。
● 修饰成员方法
修饰的成员方法也称为类方法,可以直接使用类名访问,在静态的方法中只能访问静态的成员 变量,非静态的方法中可以使用静态的成员变量。
static关键字修饰的属性特点:
● 随着类的加载而加载
● 优先于对象存在
● 静态成员被所有对象共享
● 可以直接使用类名访问
注意:
● 静态的方法中,只能使用静态的成员变量,因为他们都是随着类的加载而加载的;
● 一旦方法中使用了非静态的成员变量,那么此方法就不能定义为静态的;但非静态的方法中可以 使用静态的成员变量。
代码块
概念:在类中声明的一个没有名字的代码块。
分类:实例代码块:在每次创建对象时执行 { 实例代码块内容 }
静态代码块:在类被加载时自动执行 static { 静态代码块内容 }
类什么时候会被加载?
● 运行类中的main方法
● 访问类中的静态成员变量,静态成员方法
● 创建类的对象
public class Demo {//实例代码块{System.out.println("1-创建对象时,不需要显示的调用,会自动执行");}//静态代码块static{System.out.println("2-在类被加载时,会自动执行");}//运行类中的main方法,此时类被加载,静态代码块执行public static void main(String[] args) {//创建对象,实例代码块执行new Demo();new Demo();}
}
访问权限修饰符
● public 公共权限 --------修饰的成员,在任何地方都可以访问到.
● protected 受保护权限------在本类,同包的其他类中可以访问到,及不同包的子类.
● default 默认权限 --------在本类,同包的其他类中可以访问到.
● private 私有权限 -------只能在本类访问到.
( protected和默认(default)的区别就是,protected可以在不同包的子类中访问 )
面向对象的三大特征
封装
● 概念:将类中的某些信息,使用不同的访问权限修饰符隐藏起来,不让外界直接访问操作,而是通过 类中向外提供的特定方法访问,方便加入控制语句,主动权在类手中。
● 封装案例1:将类中成员变量私有化
public class Student {private String name;private int age ;
}
● 此时在其他类中不能任意访问成员变量,只能通过类中提供的特殊的方法进行访问.
public String getName() {return name;}public void setName(String name) {//加入控制语句if(name.length()>1&&name.length()<5);{this.name = name;}}public int getAge() {return age;}public void setAge(int age) {//加入控制语句if(age<100&&age>0){this.age = age;}}
public static void main(String[] args) {Student s1 = new Student();s1.setName("小王"); //符合setName方法中的条件s1.setAge(-1); //不符合setAge方法中的条件System.out.println(s1.getName());System.out.println(s1.getAge());}
● 封装案例2:将类中的方法私有化
单例模式:让一个类在一个程序中只能创建一个对象,将类的构造方法私有化,外界不能随便用.
public class Window {//在类加载时,只创建了一个唯一对象static Window window = new Window();//将构造方法私有化,在外界不能随意调用private Window(){}//向外界提供可获得此对象的方法public static Window getWindow(){return window;}public static void main(String[] args) {System.out.println(Window.getWindow());System.out.println(Window.getWindow());System.out.println(Window.getWindow());}}
可以看到,此例中创建的每个window的哈希值都相同于Window类中第一次创建的window
● 作用:可以有效的避免创建多个对象,达到在一个程序中只创建一个对象的作用。
继承
● 概念:将同一类事物中共性的属性和行为进行抽取,定义为一个类中(基类),其他类可以继 承基类,就可以拥有基类中的功能,但不能使用基类中私有的内容.
● 作用:实现代码的复用性,以及可以在子类扩展自己特有的功能,而不影响其他类.(优点)
● 使用条件:只要符合is-a关系(什么是什么关系,比如苹果是水果),就可以使用继承,一个类 只能直接继承一个类;而间接的可以继承多个类,称为继承的传递性,例如b继承a,然后c继承 b,则c也继承了a.
● 继承的基本语法:
在创建类的时候在类名后使用extends关键字继承别的类,子类继承父类后,拥有了父类的成员 变量和成员方法,但不能访问私有成员。
public class Cat extends Animal{//Cat继承Animal的成员变量和成员方法,但不能访问私有成员
}
● 注意:当一个类没有显示继承其他类的时候默认继承object类,Object类是java类体系中最大的 类,Object类之上再也没有别的类。
多态
● 前提:二者存在直接或间接的继承关系。
● 概念:用父类的引用变量指向子类对象,多态也称向上转型,将子类类型转为父类类型。
● 作用:用父类类型表示任意的子类类型对象,利于程序扩展。
Animal dog = new Dog();
两个时间段:
● 编译期 --- 类型是父类类型
● 运行期 --- 类型是具体的子类类型
口诀:编译看左边,运行看右边 ( 若是静态方法则都看左边(父类))
● 多态的存在意味着可以使用父类类型的引用来调用子类对象中重写的方法。
案例:
public class Animal {public void makeSound() {System.out.println("Animal is making a sound");}
}
public class Dog extends Animal{@Override//方法的重写public void makeSound() {System.out.println("Dog is barking");}public static void main(String[] args) {Animal dog = new Dog();//现在我们可以使用Animal类的引用来引用Dog对象dog.makeSound(); //输出Dog is barking}
}
● 在上面的例子中,animal引用的是一个Dog对象,但是调用的是Dog类中重写的makeSound()方 法。这就是多态的效果!
方法的重写
概念:当父类中方法的实现不能满足子类需求时,可以在子类中对父类的方法进行重写 ( 覆盖) ,这 样调用时,就会调用子类中重写的方法。
重写时需要注意:
● 子类重写的方法结构与父类方法的结果必须一致(方法名,参数列表,返回值类型必须一致)
● 子类重写的方法使用的访问权限不能小于父类被重写方法的访问权。
● 构造方法,静态方法不能重写,成员变量不存在重写。
● 使用 @Override 注解标签
了解:
@Override是Java中的一个注解标签,定义在重写的方法上面,表示此方法是从父类重写而来,也可以不用添加,不过建议保留,因为编译器可以进行语法验证 ,并且阅读代码时可以明确的知道此方法是重写的。
抽象类
抽象方法
● 概念:抽象方法是一种特殊的方法,只有声明,没有具体的实现,必须用abstract关键字修饰, 没有方法体。
● 作用:在一些体系结构的顶端,只需要某些定义功能而没有必要实现,因为不同子类中的实现 都不同,这个时候就可以将这个方法声明为抽象方法。
例如定义一个eat的抽象方法:
//抽象类也需要用abstract来修饰
public abstract class Animal {//抽象方法,没有方法体public abstract void eat();}
● 注意:一个类如果包含抽象方法,这个类为抽象类;一个类为抽象类,不一定有抽象方法。
抽象类也需要用abstract关键字修饰。
● 抽象类的特点:
1. 抽象类不能用来创建对象,其他功能与正常类相同,可以有成员变量,成员方法,构造方法。
2. 主要在上层定义功能,让子类继承实现。
● 代码实现:
abstract class Animal {abstract void sound(); // 抽象方法void sleep() {System.out.println("睡觉"); // 具体方法}
}
● 子类继承抽象类时,必须实现所有的抽象方法,否则子类也必须声明为抽象类
class Dog extends Animal {void sound() {System.out.println("汪汪"); // 实现抽象方法}
}
● 抽象类可以有构造方法,但是不能被实例化。子类可以通过使用"super"关键字来调用抽象类的 构造方法和方法。
接口
介绍:
● 接口可以看做是一种特殊的抽象类,里面可以包含抽象方法,但不能被创建对象; 接口可以被 类实现,实现类必须实现接口中定义的所有方法;接口和抽象类十分的类似,接口内部的方法也 是默认抽象的,不可在内部实例化的,只能由接口的调用者去实现。
● 接口通过关键字 interface定义;类通过implements关键字来实现接口。
如何定义接口?
//interface关键字修饰接口
public interface MyInterface {
int num = 10; // public static final int num = 10;void eat(); //public abstract void eat();
//静态方法,可以直接通过接口名调用public static void test(){
}//默认方法,被子类继承后调用default void test1(){
}
}
注意:类实现接口后,要么重写接口中所有抽象方法,要么声明为抽象类。
● 一个类可以实现多个接口:
public class MyClass implements A,B{//Myclass类实现A,B接口
}
● 一个接口可以继承多个接口:
public interface A extends B,C{ //A继承B,C接口
}