类的成员
java语言是一个面向对象的高级编程语言
什么是面向对象?
面向对象是用代码高度模拟现实世界的事物,从而为人类服务以及解决业务需求。
Pig pig=new Pig();
pig.eat("西瓜");
面向对象的关键概念是:类和对象
什么是类?
类是相同时事物共同特征的描述。
类是学术上抽象的一个概念,类不是具体存在的事物,只能是描述一类事物
什么是对象?
对象是具体存在的事物,对象是现实世界上真实存在的实例。(对象==实例)
有了类和对象面向对象就可以描述万千世界所有的事物!!
必须先有类,才能创建对象!!
定义类的格式:
修饰符 class 类名{
}
类名:首字母应该大写,满足“驼峰模式”。
一个Java代码文件中可以定义多个类,但是只能有一个类是用public修饰,
而且public修饰的类名必须成为Java代码的文件名称。
修饰符 class 类名{
// 1.成员变量(Field):描述类或者对象的属性信息的。
// 2.成员方法(Method):描述类或者对象的行为的。
// 3.构造器(Constructor): 初始化对象中的数据,并返回这个对象的地址。
// 4.代码块
// 5.内部类
}
类中只要不是这5大成分代码就会报错!!
构造器
构造器的作用:初始化对象的数据,并返回对象的地址
构造器的格式:
修饰符 类名(形参列表){
}
构造器的注意事项:
1.一个类默认自带一个无参数构造器
2.一旦写了有参构造器,那么无参构造器就被覆盖了。如果还需要无参构造器,需要自己手动写一个无参数构造器。
创建对象初始化格式
类名 对象名称=new 构造器;
无参数构造器可以初始化对象数据成为默认值返回对象地址给我们。
有参数构造器可以初始化对象数据成为指定值返回对象地址给我们。可以在做对象的时候数据就注入好了!
class Student{
private String name ;
private int age ;
private char sex ;
public Student() {
}
public Student(String name, int age, char sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
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 char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
}
public class ClassDemo {
public static void main(String[] args) {
// 1.调用无参数构造器创建一个学生对象!
Student s1 = new Student();
s1.setName("蜘蛛精");
s1.setAge(1000);
s1.setSex('妖');
System.out.println(s1.getName()+"==>"+s1.getAge()+"==>"+s1.getSex());
// 2.调用有参数构造器:在初始化对象的时候直接为对象赋值好!
Student s2 = new Student("铁扇公主",21,'女');
System.out.println(s2.getName()+"==>"+s2.getAge()+"==>"+s2.getSex());
}
}
1.封装
面向对象的三大特征:封装、继承、多态
什么是封装?
封装是对代码进行”合理隐藏,合理暴露“
封装的作用是为了安全性和代码的组件化思想
封装的规范:
一般是成员变量私有,方法公开。
要为私有的成员变量提供成套的setter和getter暴露赋值和取值。
小结:封装作为特征实际上已经成为Java代码的实施标准,即使代码毫无意义,我们可能还是会这样写!
this关键字:
this代表了当前对象。
this出现在实例方法中谁调用这个方法,this就代表谁!
this出现在构造器中,代表了构造器正在初始化的那个对象。
public class ClassDemo03 {
public static void main(String[] args) {
Wolf w = new Wolf();
w.setName("七匹狼");
w.setSex('男');
w.setSex('雄');
System.out.println(w.getName());
Wolf xueLang = new Wolf("雪狼",12,'公');
System.out.println(xueLang.getName());
}
}
class Wolf{
private String name;
private int age ;
private int sex ;
public Wolf() {
}
public Wolf(String name, int age, int sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public String getName() {
// this有时候可以省略不写!
return name;
}
public void setName(String name) {
// this在方法中,谁调用这个方法,this就代表谁!
this.name = name; // w.name = "七匹狼"
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
}
static关键字
之前定义很多成员变量(name,age,sex)
发现每个对象都可以用,就说明java中这些成员变量或者方法是存在所属性的。
有些属于对象,有些是属于对象的
java是通过成员变量是否有static修饰来区分是类的还是对象的。
static==静态==修饰的成员(方法和成员变量)属于类本身的。
按照有无static修饰,成员变量和方法
成员变量:
(1)静态成员变量(类变量):有static修饰的成员变量称为静态成员变量也叫类变量,属于类本身的,直接用类名访问即可。
(2)实例成员变量:无static修饰的成员变量称为实例成员变量,属于类的每个对象的,必须用类的对象来访问。
成员方法:
(1)静态方法有static修饰的成员方法称为静态方法也叫类方法,属于类本身的,
直接用类名访问即可。
(2)实例方法无static修饰的成员方法称为实例方法,属于类的每个对象的,必须用类的对象来访问。
静态方法使用:类名.方法名
实例方法使用:new 类名().方法名
public class Student {
// 2个实例成员变量
public String name ;
private int age ;
// 1.静态方法:属于类,有static修饰,直接用类名访问即可。
public static void inAddr(){
System.out.println("我们都在吉山区!");
}
// 2.实例方法:属于对象的,无static修饰,必须对象访问。
public void run(){
System.out.println(name+"已经"+age+"岁,跑的贼溜~~~~~");
}
public static void main(String[] args) {
// a.类名.静态方法
Student.inAddr();
// 注意:同一个类中访问静态方法可以省略类名不写
inAddr();
// b.对象.实例方法
// Student.run(); // 报错了!
Student jnl = new Student();
jnl.name = "贾乃绿";
jnl.age = 30;
jnl.run();
// c.对象.静态方法(不推荐)
jnl.inAddr();
}
}
2.继承
继承是java中一般特殊的关系,是一种子类到父类的关系
例如:学生类继承了人类。猫类继承动物类
被继承的类称为:父类、超类
继承父类称为:子类
继承的作用?
”可以提高代码的复用“
子类更强大:子类不仅得到了父类的功能,它还有自己的功能。
继承的特点:
子类继承了一个父类,子类就可以直接得到父类的属性(成员变量)和行为(方法)了。
子类 extends 父类{
}
public class ExtendsDemo {
public static void main(String[] args) {
Cat dlam = new Cat();
dlam.run();
dlam.eat();
}
}
class Animal{
public void run(){
System.out.println("动物可以跑~~");
}
}
class Cat extends Animal {
public void eat(){
System.out.println("猫爱吃鱼~~");
}
}
拓展
子类继承父类,子类就得到了父类的属性和行为。
但是并非所有父类的属性和行为等子类都可以继承。
子类不能继承父类的东西:
子类不能继承父类的构造器:子类有自己的构造器。(没有争议的)
有争议的观点(拓展):
子类是否可以继承父类的私有成员(私有成员变量,私有成员方法)?
-- 我认为子类是可以继承父类的私有成员的,只是不能直接访问已!!
子类是否可以继承父类的静态成员?
-- 我认为子类没有继承父类的静态成员。
-- 父类的静态成员属于父类本身,只有一份,可以被子类共享访问,共享并非继承!
public class ExtendsDemo {
public static void main(String[] args) {
Cat cat = new Cat();
// cat.run();
System.out.println(Cat.schoolName);
}
}
class Cat extends Animal{
}
class Animal{
public static String schoolName = "张三丰";
private void run(){
}
}
继承后成员变量的访问特点
就近原则:
子类有找子类,子类没有找父类,父类没有就报错。
this代表了当前对象,可以访问当前子类对象的成员变量。
super指代访问父类中的成员变量。
public class TestDemo {
public static void main(String[] args) {
Cat dlam = new Cat();
dlam.showName();
}
}
class Cat extends Animal{
public String name = "子类名称";
public void showName(){
String name = "局部名称";
System.out.println(name); // 局部名称
System.out.println(this.name); // 子类名称
System.out.println(super.name); // 父类名称
}
}
class Animal{
public String name = "父类名称";
}
方法重写
目标:方法重写(重点)
方法重写的概念:
子类继承了父类,子类就得到了父类的某个方法
但是子类觉得父类的这个方法不好用或者无法满足自己的需求
子类重写一个与父类申明一样的方法 来覆盖父类的该方法,子类的这个方法
就进行了方法重写。
方法重写的校验注解: @Override
Java建议在重写的方法上面加上一个@Override注解。
方法一旦加了这个注解,那就必须是成功重写父类的方法,否则报错!
@Override优势:可读性好,安全,优雅!!
方法重写的具体要求:
1.子类重写方法的名称和形参列表必须与父类被重写方法一样。
2.子类重写方法的返回值类型申明要么与父类一样,要么比父类方法返回值类型范围更小。
3.子类重写方法的修饰符权限应该与父类被重写方法的修饰符权限相同或者更大。
4.子类重写方法申明抛出的异常应该与父类被重写方法申明抛出的异常一样或者范围更小!
方法重写的规范:
1.加上@Override注解。
2.建议“申明不变,重新实现”。
拓展
super:代表了父类引用。
super可以用在子类的实例方法中调用父类被重写的方法。
public class ExtendsDemo02 {
public static void main(String[] args) {
SportMan zjk = new SportMan();
zjk.go();
}
}
class SportMan extends People{
@Override
public void eat(){
System.out.println("运动员要吃好喝好,吃的贼多~~~~");
}
public void go(){
System.out.println("开始~~~");
eat(); // 子类的
super.eat(); // 父类的
}
}
class People{
public void eat(){
System.out.println("人要吃饭~~~~");
}
}
静态方法和私有方法是否可以被重写(拓展语法) 可以吗?
都不可以.
public class ExtendsDemo03 {
}
class BasketBall extends Human{
// @Override // 私有的方法不能重写!!
// public void run(){
// System.out.println("🏀运动员跑的贼溜~~~~~");
// }
// @Override
// public static void test(){
// }
}
class Human{
private void run(){
System.out.println("人可以跑");
}
public static void test(){
}
}
继承后构造器的特点
特点:子类的全部构造器默认一定会先访问父类的无参数构造器,再执行子类自己的构造器。
为什么子类全部构造器一定要先访问父类构造器在执行自己?
1.子类的构造器的第一行默认存在super();调用父类的无参构造器,根据参数匹配父类的构造器。
重点:
为什么要调用父类的构造器,和java双亲委派机制有关。
比如,创建一个名为string的类,程序无法加载。因为双亲委派机制,JVM出于安全性的考虑,全限定类名相同的string是不能被加载。
java.lang.String会被顶级类加载器Bootstrap Classloader加载。当 class 文件被加载到内存中时,类文件常量池中的其他常量会加载到运行时常量池,但是字符串常量不会。它会首先在堆区中创建一个字符串对象,然后再把这个对象的引用保存到全局字符串常量池中。
public class String {
public static void main(String[] args) {
String string = new String();
string.setAge("1");
System.out.println(string);
}
public String() {
}
public String(String name, String age) {
this.name = name;
this.age = age;
}
private String name;
private String age;
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public String getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(String age) {
this.age = age;
}
public java.lang.String toString() {
return "String{name = " + name + ", age = " + age + "}";
}
}
super调用父类构造器
子类的全部构造器默认一定会调用父类的无参数构造器再执行自己
super(...):可以根据参数选择父类的某个构造器初始化继承自父类的成员
public class TestDemo {
public static void main(String[] args) {
Wolf qpl = new Wolf("七匹狼" , 12 , '雄');
qpl.run();
}
}
class Wolf extends Animal{
public Wolf(String name, int age, char sex) {
super(name, age , sex);// 指定调用父类的有参数构造器初始化继承自父类的成员。
}
}
class Animal{
private String name ;
private int age ;
private char sex;
public Animal() {
}
public Animal(String name, int age, char sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public void run(){
System.out.println(name+"=>"+age+"=>"+sex+",可以跑的很快~~~");
}
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 char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
}
总结
总结与拓展:this和super关键字使用总结
this代表了当前对象的引用(继承中指代子类对象):
this.子类成员变量。
this.子类成员方法。
this(...):可以根据参数匹配访问本类其他构造器。(还没有学习)
super代表了父类对象的引用(继承中指代了父类对象空间)
super.父类成员变量。
super.父类的成员方法。
super(...):可以根据参数匹配访问父类的构造器。
拓展:this(...)根据参数匹配访问本类其他构造器。
注意:
this(...)可以在本类构造器中借用本类其他构造器。
super(...)调用父类的构造器。
this(...)和super(...)必须放在构造器的第一行,否则报错!
所以this(...)和super(...)不能同时出现在构造器中!!!
public class ThisDemo {
public static void main(String[] args) {
Student zbj = new Student("天蓬元帅", 1000 );
System.out.println(zbj.getName());
System.out.println(zbj.getAge());
System.out.println(zbj.getSchoolName());
Student swk = new Student("齐天大圣", 2000 ,"清华大学");
System.out.println(swk.getName());
System.out.println(swk.getAge());
System.out.println(swk.getSchoolName());
}
}
class Student {
private String name ;
private int age ;
private String schoolName ;
public Student() {
}
public Student(String name , int age){
// 根据参数调用兄弟构造器
this(name ,age ,"湖畔大学");
}
public Student(String name, int age, String schoolName) {
this.name = name;
this.age = age;
this.schoolName = schoolName;
}
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 getSchoolName() {
return schoolName;
}
public void setSchoolName(String schoolName) {
this.schoolName = schoolName;
}
}
继承的特点
Java是单继承的。
1.单继承:一个类只能继承一个直接父类。
面试题:Java是什么继承方式,为什么是这种方式?
答:Java是单继承的,一个类只能直接继承一个父类。
反证法:假如Java可以多继承,请看如下代码:
class A{
public void test(){
System.out.println("A");
}
}
class B{
public void test(){
System.out.println("B");
}
}
class C extends A , B {
public static void main(String[] args){
C c = new C();
c.test(); // 出现了类的二义性!所以不能多继承!
}
}
2.Java可以间接继承,支持多层继承。
3.一个类可以有多个子类
4.Object类是一切类的祖宗类,一个类要么直接继承了Object,要么默认继承了Object,要么间接继承了Object