day07 7.1 Java中的面向对象之类与对象
【一】类与对象
【1】类定义规范
- 类与对象的关系
- 类 是实体对象的概念模型,笼统的,不具体的,
- 比如人类、动物类、鸟类
- 对象 又称为实体,类具体化的表现
- 小红/小明
- 小猫一号/小狗一号
- 对象中有属性,有方法
- 不同对象属性是独有的
- 方法是共有的
- 类 是实体对象的概念模型,笼统的,不具体的,
- 类定义规范
// [] :内的内容可以不写 | :左右的内容表示或
[public][abstract|final] class 类名class_name [extends 继承的类名] [implements 实现的接口名]{
// 定义成员属性
属性类型1 属性名1; // String name;
属性类型2 属性名2; // int age;
// 定义静态属性(类属性)
private String name;
// 定义类成员方法
public int add(int a, int b){
return a+b;
}
// 定义静态方法(类方法)
public static void speak(){
System.out.println("说话")
}
}
public:表示类是公有的
java文件的文件名必须是public class 类名
abstract:抽象类
final:类如果被 final 修饰 ,这个类不能被别的类所继承
extends:继承某个父类
implements:实现的接口
(1)类的定义
public class Person {
// 定义成员属性
private String name;
// 定义成员属性
public int age;
// 定义静态属性
public static int sex;
// 定义类成员方法
// void:方法没有返回值
public void speak() {
System.out.println("说话了!");
}
// 静态方法
public static run() {
System.out.println("跑起来了!");
}
}
(2)对象的实例化
import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
public class Demo01 {
public static void main(String[] args) {
// 因为在同一个包下,所以可以直接引用
// (1)实例化类对象 p
Person p = new Person();
// (2)修改对象属性
// 由于 name 是由 private 修饰
// 所以无法通过对象 修改该属性
p.age = 18;
System.out.println(p);
// Person@1b6d3586
// (3)调用对象方法
p.speak();
// 说话了!
}
}
【2】Java的类属性
- 在类中有属性
- 成员属性
- 只要不被static修饰的,就是成员属性,他是属于对象的,需要对象来调用
- 静态变量
- 只要 static修饰的,需要类或类实例的对象来调用
- 成员属性
import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
//public class Demo01 {
//
// public static void main(String[] args) {
// // 因为在同一个包下,所以可以直接引用
// // (1)实例化类对象 p
// Person p = new Person();
//
// // (2)修改对象属性
// // 由于 name 是由 private 修饰
// // 所以无法通过对象 修改该属性
// p.age = 18;
// System.out.println(p);
// // Person@1b6d3586
//
// // (3)调用对象方法
// p.speak();
// // 说话了!
// }
//}
public class Demo01 {
public static void main(String[] args) {
// 类属性
// (1)实例化类得到类对象
Person p = new Person();
// 对象的属性 ----> 不被static修饰的
p.hobby = "music";
p.age = 18;
Person p1 = new Person();
// 对象的属性 ----> 不被static修饰的
p1.hobby = "sport";
p1.age = 29;
// 每个对象都有自己的属性,因此打印的内容不一样
System.out.println(p.hobby);
System.out.println(p1.hobby);
// (2)静态成员:被static修饰的,属于类
// 通过对象,修改静态成员,但是他是属于类的,都会受影响
p.sex = 2;
p1.sex = 1;
System.out.println(p.sex);
// 2
// 1
System.out.println(p1.sex);
// 2
// 1
// 类来修改静态属性,一般是用类来修改静态属性
Person.sex = 3;
System.out.println(p.sex);
// 3
System.out.println(p1.sex);
// 3
}
}
public class Person {
// 定义成员属性
private String name;
// 定义成员属性
public String hobby;
public int age;
// 定义静态属性
public static int sex;
// 定义类成员方法
// void:方法没有返回值
public void speak() {
System.out.println("说话了!");
}
// 静态方法
public static void run() {
System.out.println("跑起来了!");
}
}
- 在Python中年对象的属性只能对象来调用
- 在Python中年类的属性只能类来调用
【3】成员方法
- 类中没有被static修饰的方法,绑定给类的,需要类来调用。
Python中有绑定给对象的方法,绑定给类的方法
Python的类中,不加任何装饰器的的方法是绑定给对象的
java:public void Speak(){}
Python的类中,使用@classmethod修饰的,是绑定给类的方法
java:public static void Speak(){}
public class Demo01 {
public static void main(String[] args) {
// 静态方法和成员方法
Person p = new Person();
p.speak(); // 对象的方法
// p.run();//类的方法,正常不是对象来调用,而是类来调用
Person.run();
}
}
public class Person {
// 定义成员属性
private String name;
// 定义成员属性
public String hobby;
public int age;
// 定义静态属性
public static int sex;
// 定义类成员方法
// void:方法没有返回值
// 没有被 static 修饰
public void speak() {
System.out.println("说话了!");
}
// 静态方法
// 被 static 修饰
public static void run() {
System.out.println("跑起来了!");
}
}
【4】构造方法
在Python中
__init__
方法完成对象的初始化在Java中
完成对对象的初始化,向对象中添加内容
可以存在多个,使用哪种初始化方式,就会触发那种构造方法
public class Demo01 {
public static void main(String[] args) {
// 构造方法
// (1)触发无参构造方法
Person person = new Person();
// 实例化对象,但是不向对象中添加参数
// 会触发Person类的无参构造方法,完成初始化
// 一旦执行,person中的 name 就完成了初始化 变成了 dream
System.out.println(person.name);
// 我正在开始执行!
// dream
// (2)触发有参构造方
Person p = new Person("mengmeng");
System.out.println(p.name);
// 我是有参构造方法,形参为1个
// mengmeng
// (3)触发有参构造方法
Person p1 = new Person("CHIMENG", 19);
System.out.println(p1.name);
System.out.println(p1.age);
// 我是有参构造方法,形参为2个
// CHIMENG
// 19
}
}
public class Person {
// 定义成员属性
// private String name;
// 定义成员属性
public String hobby;
public String name;
public int age;
// 定义静态属性
public static int sex;
// 定义类成员方法
// void:方法没有返回值
// 没有被 static 修饰
public void speak() {
System.out.println("说话了!");
}
// 静态方法
// 被 static 修饰
public static void run() {
System.out.println("跑起来了!");
}
// 构造方法
// 无参构造方法
public Person() {
System.out.println("我正在开始执行!");
this.name = "dream";
}
// 有参构造方法
public Person(String name) {
System.out.println("我是有参构造方法,形参为1个");
this.name = name;
}
// 有参构造方法
public Person(String name, int age) {
System.out.println("我是有参构造方法,形参为2个");
this.name = name;
this.age = age;
}
}
【5】this关键字
- this是写在类中的成员(对象)方法中
- [static修饰的方法中,即静态方法中,没有this]
public class Demo01 {
public static void main(String[] args) {
// 构造方法
// (1)触发无参构造方法
Person person = new Person();
// 实例化对象,但是不向对象中添加参数
// 会触发Person类的无参构造方法,完成初始化
// 一旦执行,person中的 name 就完成了初始化 变成了 dream
System.out.println(person.name);
// 我正在开始执行!
// dream
// (2)触发有参构造方
Person p = new Person("mengmeng");
System.out.println(p.name);
// 我是有参构造方法,形参为1个
// mengmeng
// (3)触发有参构造方法
Person p1 = new Person("CHIMENG", 19);
System.out.println(p1.name);
System.out.println(p1.age);
// 我是有参构造方法,形参为2个
// CHIMENG
// 19
// this 触发
// 谁调用方法就是谁
person.Sleep();
//dream
//睡觉中.....
p.Sleep();
//mengmeng
//睡觉中.....
p1.Sleep();
//CHIMENG
//睡觉中.....
}
}
public class Person {
// 定义成员属性
// private String name;
// 定义成员属性
public String hobby;
public String name;
public int age;
// 定义静态属性
public static int sex;
// 定义类成员方法
// void:方法没有返回值
// 没有被 static 修饰
public void speak() {
System.out.println("说话了!");
}
// 静态方法
// 被 static 修饰
public static void run() {
System.out.println("跑起来了!");
}
// 构造方法
// 无参构造方法
public Person() {
System.out.println("我正在开始执行!");
this.name = "dream";
}
// 有参构造方法
public Person(String name) {
System.out.println("我是有参构造方法,形参为1个");
this.name = name;
}
// 有参构造方法
public Person(String name, int age) {
System.out.println("我是有参构造方法,形参为2个");
this.name = name;
this.age = age;
}
// this 关键字
public void Sleep() {
System.out.println(this.name);
System.out.println("睡觉中.....");
}
}
【6】访问控制符
访问范围 | private | friendly(默认) | protected | public |
---|---|---|---|---|
同一个类 | 可访问 | 可访问 | 可访问 | 可访问 |
同一包中的其他类 | 不可访问 | 可访问 | 可访问 | 可访问 |
不同包中的子类 | 不可访问 | 不可访问 | 可访问 | 可访问 |
不同包中的非子类 | 不可访问 | 不可访问 | 不可访问 | 可访问 |
//1 private
用 private 修饰的类成员,只能被该类自身的方法访问和修改,而不能被任何其他类(包括该类的子类)访问和引用。因此,private 修饰符具有最高的保护级别
//2 friendly(默认)
如果一个类没有访问控制符,说明它具有默认的访问控制特性。这种默认的访问控制权规定,该类只能被同一个包中的类访问和引用,而不能被其他包中的类使用,即使其他包中有该类的子类。这种访问特性又称为包访问性(package private)
//3 protected
用保护访问控制符 protected 修饰的类成员可以被三种类所访问:该类自身、与它在同一个包中的其他类以及在其他包中的该类的子类。使用 protected 修饰符的主要作用,是允许其他包中它的子类来访问父类的特定属性和方法,否则可以使用默认访问控制符。
//4 public
当一个类被声明为 public 时,它就具有了被其他包中的类访问的可能性,只要包中的其他类在程序中使用 import 语句引入 public 类,就可以访问和引用这个类
【7】静态变量和静态方法(static)
在类中,使用static修饰的变量是属于类的,正常类来调用,但是对象也可以调用
在类中,使用static修饰的方法是属于类的,正常类来调用,不需要实例化,就能调用,但是对象也可以调用,但是他的内部没有this关键字
什么情况下定义对象的方法[成员方法]
什么情况下定义类的方法[静态方法]
以后,不想初始化得到对象就能使用这个方法,就定义成静态方法。
(1)什么是静态变量(类变量)
- 在类中,使用 static 修饰符修饰的属性(成员变量)称为静态变量,也可以称为类变量
- 常量称为静态常量
- 方法称为静态方法或类方法
- 它们统称为静态成员,归整个类所有。
- 静态成员不依赖于类的特定实例,被类的所有实例共享
- 就是说 static 修饰的方法或者变量不需要依赖于对象来进行访问
- 只要这个类被加载,Java 虚拟机就可以根据类名找到它们
(2)什么是静态变量
- 类的成员变量可以分为以下两种:
- 静态变量(或称为类变量),指被 static 修饰的成员变量
- 实例变量,指没有被 static 修饰的成员变量
静态变量与实例变量的区别如下:
1)静态变量
运行时,Java 虚拟机只为静态变量分配一次内存,在加载类的过程中完成静态变量的内存分配
在类的内部,可以在任何方法内直接访问静态变量
在其他类中,可以通过类名访问该类中的静态变量
2)实例变量
每创建一个实例,Java 虚拟机就会为实例变量分配一次内存
在类的内部,可以在非静态方法中直接访问实例变量
在本类的静态方法或其他类中则需要通过类的实例对象进行访问
(3)什么是静态方法
- 类的成员方法也可以分为以下两种:
- 静态方法(或称为类方法),指被 static 修饰的成员方法
- 实例方法,指没有被 static 修饰的成员方法
- 静态方法与实例方法的区别如下:
- 静态方法不需要通过它所属的类的任何实例就可以被调用
- 因此在静态方法中不能使用 this 关键字,也不能直接访问所属类的实例变量和实例方法
- 但是可以直接访问所属类的静态变量和静态方法。
- 另外和 this 关键字一样, super 关键字也与类的特定实例相关
- 所以在静态方法中也不能使用 super 关键字
- 在实例方法中可以直接访问所属类的静态变量、静态方法、实例变量和实例方法
【二】面向对象之继承
【1】继承格式
-
在 Java 中通过 extends 关键字可以申明一个类是从另外一个类继承而来的,一般形式如下:
class 父类 { } class 子类 extends 父类 { } class 子子类 extends 子类 { }
-
Java中的继承
- 只支持单继承,不支持多继承,但支持实现多个接口
- 支持一条线上的多重继承
-
Java不支持多继承,但是可以通过接口来实现多继承的功能
【2】构造方法
(1)分文件继承
- 构造Animal类
public class Animal {
String name;
}
- 构造Dog类
public class Dog extends Animal {
int age;
// 有参构造
public Dog(String name,int age){
this.name = name;
this.age = age;
}
}
- 实例化调用
public class Demo01 {
public static void main(String[] args) {
// 继承的关系测试
// 实例化得到一个DOG对象
// Dog = new Dog(); // 没有参数传入会报错,因为Dog内部是一个有参构造方法
Dog d = new Dog("dream", 18);
System.out.println(d.name); // dream
}
}
(2)单文件继承
在一个文件中只能有一个 public 方法
class Animal {
String name;
}
class Dog extends Animal {
int age;
// 有参构造
public Dog(String name,int age){
this.name = name;
this.age = age;
}
}
public class Demo01 {
public static void main(String[] args) {
// 继承的关系测试
// 实例化得到一个DOG对象
// Dog = new Dog(); // 没有参数传入会报错,因为Dog内部是一个有参构造方法
Dog d = new Dog("dream", 18);
System.out.println(d.name); // dream
}
}
(3)小结
- 子类如果没写构造方法
- 默认使用父类无参构造
- 本案例名字为:固定名字
// 1 子类如果没写构造方法,默认使用父类无参构造,本案例名字为:固定名字
// 2 子类如果没写构造方法,不会自动使用父类的有参构造,所以Person p=new Person("justin");用法是报错的
import java.util.*;
public class Demo04 {
public static void main(String[] args) throws Exception {
Person p=new Person("justin");
p.Speak();
System.out.println(p.name);
}
}
class Animal{
String name;
public Animal(){
this.name="固定名字";
}
public Animal(String name){
this.name=name;
}
public void Speak(){
System.out.println("动物说话");
}
}
class Person extends Animal {
int age;
// 子类如果没写构造方法,默认使用父类无参构造,本案例名字为:固定名字
// 子类如果没写构造方法,不会自动使用父类的有参构造,所以Person p=new Person("justin");用法是报错的
// public Person(String name,int age){
// this.name=name;
// this.age=age;
// }
public void Run(){
System.out.println("人走路");
}
@Override
public void Speak(){
super.Speak(); // 代指父类对象,等同于python的super()
System.out.println("人说话");
}
}
【3】super 与 this 关键字
有了继承关系就会多了另一个关键字(原来有this):super(等同于python中的super())
- super关键字:
- 我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类
- this关键字:指向自己的引用
class Animal{
String name;
public void Speak(){
System.out.println("动物说话");
}
}
class Person extends Animal {
int age;
public void Run(){
System.out.println("人走路");
}
@Override
public void Speak(){
this.Speak(); // 代指自己的,先从自己找,自己没有去父类找
super.Speak(); // 代指父类对象,等同于python的super(),直接去父类找
System.out.println("人说话");
}
}
【三】重写(Override)与重载(Overload)
【1】什么是重写
- 重写(Override)是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。
- 即外壳不变,核心重写
【2】什么是重载
-
重载(overloading) 是在一个类里面,方法名字相同,而参数不同。
-
返回类型可以相同也可以不同
-
被重载的方法必须改变参数列表(参数个数或类型不一样)
【3】演示
class Animal{
String name;
public Animal(){
this.name="固定名字";
}
public Animal(String name){
this.name=name;
}
public void Speak(){
System.out.println("动物说话");
}
}
class Person extends Animal {
int age;
public void Run(){
System.out.println("人走路");
}
// 重载方法 - 方法名一样,参数不一样
public void Run(String ss){
System.out.println(ss);
System.out.println("走路");
}
// 重写方法Speak - 必须有继承关系
@Override
public void Speak(){
super.Speak(); // 代指父类对象,等同于python的super()
System.out.println("人说话");
}
// 重载方法Speak
public void Speak(String aa){
super.Speak(); // 代指父类对象,等同于python的super()
System.out.println("人说话");
}
}
【四】面向对象之接口
【1】接口的介绍
(1)接口是一个抽象类型
- 接口(Interface),是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。
- 一个类通过继承接口的方式,从而来继承接口的抽象方法。
只在接口中定义某个方法,可以不写这个方法,意思是继承接口的类必须要有我定义的接口中的方法
(2)接口并不是类
- 接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。
- 类描述对象的属性和方法。接口则包含类要实现的方法。
(3)接口无法被实例化,但是可以被实现
- 一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。
- 接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。
接口不支持被 new
(4)接口与类相似点
- 一个接口可以有多个方法
- 接口文件保存在 .java 结尾的文件中,文件名使用接口名
(5)接口与类的区别
- 接口不能用于实例化对象
- 接口没有构造方法
- 接口中所有的方法必须是抽象方法
- 接口不能包含成员变量,除了 static 和 final 变量
- 接口不是被类继承了,而是要被类实现
- 接口支持多继承
- 类可以实现多个接口
【2】接口声明
- 定义接口语法
public interface 接口名 extends 其它接口 {
// 声明变量 static 和 final 变量
// 声明方法,抽象方法
public Speak(); // 不用加{},这里只是定义了一个接口方法,而没有具体实现这个方法,所以不用加{}
}
- 官方一点的写法
[可见度] interface 接口名称 [extends 其他的接口名] {
// 声明变量
// 抽象方法
}
- 示例
- 接口
interface Duck {
//任何类型 final, static 字段
final String name="dream";
public static int age = 19;
//抽象方法
public void Speak();
//public void Run(){}; // 不能有具体实现
public void Run(); // 不能有具体实现
}
- 子类中实现接口
// 子类实现接口,必须实现接口中所有的方法
class TDuck implements Duck {
@Override
public void Speak() {
System.out.println("鸭子叫");
}
@Override
public void Run() {
System.out.println("鸭子走路");
}
}
- python中的鸭子类型
- 只要我的方法中有这两个方法,就是同一类
class TDuck(): def speak(): pass def run(): pass class RDuck(): def speak(): pass def run(): pass
- Java中的鸭子类型
- 在Java中必须实现继承的同一个接口的两个类才叫鸭子类型,是同一类
interface Duck { //任何类型 final, static 字段 final String name = "dream"; public static int age = 19; //抽象方法 public void Speak(); //public void Run(){}; // 不能有具体实现 public void Run(); // 不能有具体实现 } // 子类实现接口,必须实现接口中所有的方法 class TDuck implements Duck { @Override public void Speak() { System.out.println("唐老鸭鸭子叫"); } @Override public void Run() { System.out.println("唐老鸭鸭子走路"); } } class RDuck implements Duck { @Override public void Speak() { System.out.println("肉鸭鸭子叫"); } @Override public void Run() { System.out.println("肉鸭鸭子走路"); } }
【3】接口继承
- 可以继承多个接口
interface Duck {
public void Speak();
public void Run();
}
interface TDuck extends Duck{
public void Flay();
}
// 接口的多继承:在Java中,类的多继承是不合法,但接口允许多继承。在接口的多继承中extends关键字只需要使用一次,在其后跟着继承接口
interface Foo extends Duck, TDuck{
}
【4】接口实现
- 可以实现多个接口
// 实现接口,必须实现接口中所有的方法
interface Duck {
//抽象方法
public void Speak();
public void Run(); // 不能有具体实现
}
interface TDuck extends Duck{
public void Flay();
}
class RealDuck implements TDuck{
@Override
public void Speak() {
}
@Override
public void Run() {
}
@Override
public void Flay() {
}
}
【五】面向对象之抽象类
- 定义格式
public abstract class Foo{
// 定义方法
public void Speak(){
System.out.println("Speak Speak Speak");
}
// 定义抽象方法
public abstract void Sleep();
}
// 继承
class Bird extends Foo {
// Speak 已经有具体实现了,可以不重写
// 但是Sleep必须重写,因为没有实现
@Override
public void Sleep() {
System.out.println("必须重写抽象方法");
}
}
- 案例演示
public class Demo04 {
public static void main(String[] args) {
Bird b = new Bird();
b.Speak(); // Speak Speak Speak
b.Sleep(); // 必须重写抽象方法
}
}
abstract class Foo {
// 定义方法
public void Speak() {
System.out.println("Speak Speak Speak");
}
// 定义抽象方法
public abstract void Sleep();
}
// 继承
class Bird extends Foo {
// Speak 已经有具体实现了,可以不重写
// 但是Sleep必须重写,因为没有实现
@Override
public void Sleep() {
System.out.println("必须重写抽象方法");
}
}
【六】抽象类和接口的区别
【小结】
-
关键字不一样
-
类继承是
implements
extends
-
类是类,接口是接口
-
抽象类中方法可以具体实现,但是接口不能有具体实现
-
一个类可以实现多个接口,但是不能继承多个类
【详解】
-
关键字不同:
-
在Java中,使用
abstract
关键字定义抽象类 -
使用
interface
关键字定义接口。
-
-
形式上的区别:
-
类可以继承一个类,但类不能继承多个类
-
一个类可以实现多个接口。
-
-
方法的实现:
-
抽象类可以包含具体的方法实现
- 这些方法可以被子类继承和重写,也可以直接被调用。
-
接口只能定义方法的签名
- 不能包含方法的实现,实现接口的类必须提供接口中定义的所有方法的具体实现。
-
-
字段的定义:
-
抽象类可以定义实例变量
- 这些变量可以是任意的访问修饰符,并且可以有默认值。
-
接口只能定义常量字段(
static final
)- 而且字段默认为公共、静态和最终。
-
-
设计思想:
-
抽象类用于表示一种通用的父类
- 其中包含了子类所共有的属性和方法。
-
接口则用于定义一组行为和功能的规范
- 不关心具体实现细节,只关注方法的输入和输出。
-
- 总结来说
- 抽象类更类似于普通类的扩展和继承
- 接口更像是一种规范或者契约,用于描述类应该具有的行为和功能。
- 在设计中,应根据具体的需求选择使用抽象类还是接口。
- 如果需要表达一种"is-a"的关系并且需要共享代码实现
- 可以使用抽象类;
- 如果需要表达一种"has-a"的关系或者需要多继承
- 可以使用接口。
【七】面向对象之封装
【1】面向对象三大特性
-
继承
-
多态
-
封装
-
封装
- 把属性或方法放在类的内部,可以隐藏起来,然后拿到一个对象
- 可以 .属性 .方法 进行使用
【2】在Java中,习惯把属性定义成私有的,然后提供方法,来进行读写
public class Demo05 {
public static void main(String[] args) {
// 实例化类对象
Fish f = new Fish();
f.name = "xxx"; // 这样做是不行的,因为类属性被定义为私有的属性,无法通过实例化对象调用去修改私有属性
}
}
// 定义一个类
class Fish {
// 类里面放了一个私有属性
private String name;
}
- 解决
public class Demo05 {
public static void main(String[] args) {
// 实例化类对象
Fish f = new Fish();
// 通过方法去修改设置属性 - 安全
f.setName("小黄鱼");
System.out.println(f.getName()); // 小黄鱼
}
}
// 定义一个类
class Fish {
// 类里面放了一个私有属性
private String name;
// Java 中习惯这样用
// 开放接口方法,供外部修改调用
public void setName(String name) {
this.name = name;
}
// 开放接口方法,当外部访问时,可以将想要反出去内容返回
public String getName() {
return this.name;
}
}
- 支持自定义返回数据
public class Demo05 {
public static void main(String[] args) {
// 实例化类对象
Fish f = new Fish();
// 通过方法去修改设置属性 - 安全
f.setName("小黄鱼");
System.out.println(f.getName()); // 小黄鱼安全属性
}
}
// 定义一个类
class Fish {
// 类里面放了一个私有属性
private String name;
// Java 中习惯这样用
// 开放接口方法,供外部修改调用
public void setName(String name) {
this.name = name;
}
// 开放接口方法,当外部访问时,可以将想要反出去内容返回
public String getName() {
// 支持返回的数据拼接其他的东西
return this.name + "安全属性";
}
}
【3】详解
// java中一般不直接通过对象调用属性,而是通过方法来设置和获取属性【更安全】
class Person {
public String name ;
private int age;
public void setAge(int age){
this.age=age;
}
public int getAge(){
return this.age+1;
}
}
【八】面向对象之多态
【1】什么是多态
- 多态是同一类事物[实例,对象]多种形态
猫对象1号
狗对象1号
都属于动物类 --> 动物类(通过继承,实现多个接口),有多种具体形态
调用 同一类事物共有的方法 --> 虽然调用同样的方法,但是各自表现出来的不一样,狗是狗叫,猫是猫叫
- 从而调用同一类[实例,对象]方法时,表现出不同
【2】多态存在的三个必要条件
- (1)编写具有继承关系的父类和子类/接口实现
- (2)子类重写父类方法
- (3)使用父类的引用指向子类的对象
前面是父类 ---- 指向了具体的某一个类
Duck d = new Tduck()
而不是
Tduck d = new Tduck()
【3】继承实现的多态
public class Demo06 {
public static void main(String[] args) {
// 多态
// 实例化得到对象
// 将具体的类赋值给父类
Foo1 c1 = new Child1();
Foo1 c2 = new Child2();
// 调用方法
c2.Run();
c2.Speak();
// c2.Sleep(); // c2是Foo1类型,Foo1没有 Sleep 方法,所以不能调用 Sleep 方法
// 如果想调用必须要做类型转换
Child2 cc2 = (Child2) c2; // 强制转换数据类型
cc2.Sleep(); // 转成具体类型,可以调用具体的独有的方法
// c1 可以转换成 Child2 类型吗?
// 不可以,每个对象有每个对象自己独有的类,不能将两个本质上不同的类强转成另一个类
// 即 c1 本质上是 Child1 类型 , 不能强转成 Child2 类型
// 强转类型建议加 If 判断
if (c1 instanceof Child1) {
Child1 cc1 = (Child1) c1;
}
}
}
// 定义父类
class Foo1 {
public void Speak() {
System.out.println("父类的Speak方法");
}
public void Run() {
System.out.println("父类的Run方法");
}
}
// 子类继承父类
class Child1 extends Foo1 {
// 重写父类方法可以不写
@Override
public void Speak() {
System.out.println("这是子类1中重写的 Speak 方法");
}
@Override
public void Run() {
System.out.println("这是子类1中重写的 Run 方法");
}
}
class Child2 extends Foo1 {
// 重写父类方法可以不写
@Override
public void Speak() {
System.out.println("这是子类2中重写的 Speak 方法");
}
@Override
public void Run() {
System.out.println("这是子类2中重写的 Run 方法");
}
// 定义子类独有的方法
public void Sleep() { // 派生方法: 比父类方法多的方法叫派生方法
System.out.println("这是子类2独有的 Sleep 方法");
}
}
- 子类转父类不叫强转,直接赋值给父类即可
- 父类转子类需要强转,强转可能会出错
【4】其他知识详解
(1)多态成员变量编译运行看左边
public class Demo04 {
public static void main(String[] args) throws Exception {
// 1 多态成员变量:编译运行看左边
Animal dog = new Dog();
System.out.println(dog.age);
}
}
//父类
class Animal {
public int age = 11;
}
//子类
class Dog extends Animal {
public int age = 33;
}
(2)多态成员方法:编译看左边,运行看右边
public class Demo04 {
public static void main(String[] args) throws Exception {
// 1 多态成员变量:编译运行看左边
Animal dog = new Dog();
System.out.println(dog.age);
// 2 多态成员方法:编译看左边,运行看右边
dog.eat();
}
}
//父类
class Animal {
public int age = 11;
public void eat() {
System.out.println("动物吃饭");
}
}
//子类
class Dog extends Animal {
public int age = 33;
@Override
public void eat() {
System.out.println("狗吃饭");
}
}
(3)子类增加独有方法walk()
import java.util.*;
import com.justin.*;
import com.justin.Db;
import com.justin.Helper;
public class Demo04 {
public static void main(String[] args) throws Exception {
// 1 多态成员变量:编译运行看左边
Animal dog = new Dog();
System.out.println(dog.age);
// 2 多态成员方法:编译看左边,运行看右边
dog.eat();
// 3 无法调用子类独有方法
//dog.walk();
}
}
//父类
class Animal {
public int age = 11;
public void eat() {
System.out.println("动物吃饭");
}
}
//子类
class Dog extends Animal {
public int age = 33;
@Override
public void eat() {
System.out.println("狗吃饭");
}
public void walk() {
System.out.println("狗走路");
}
}
(4)引用类型转换
- 1 向上转型:【儿子变父亲】
- 多态本身是子类向父类向上转换(自动转换)的过程
- 这个过程是默许的
- 当父类引用指向一个子类对象时,就是向上转型
- 2 向下转型:【父亲变儿子,需要强制转换】
- 向下转型,强制类型转换
Dog dog1 = (Dog) dog;
dog1.walk();
- 3 类型转换会出现【类型转换异常】
- 4 instanceof 判断具体类型
import java.util.*;
import com.justin.*;
import com.justin.Db;
import com.justin.Helper;
public class Demo04 {
public static void main(String[] args) throws Exception {
// 强制类型转换会出错
Animal cat = new Cat();
// Dog d=(Dog)cat;
// d.walk();
// 通过instance判断再转
if(cat instanceof Cat){
Cat c=(Cat) cat;
c.sleep();
}
}
}
//父类
class Animal {
public int age = 11;
public void eat() {
System.out.println("动物吃饭");
}
}
//子类
class Dog extends Animal {
public int age = 33;
@Override
public void eat() {
System.out.println("狗吃饭");
}
public void walk() {
System.out.println("狗走路");
}
}
class Cat extends Animal {
public int age = 63;
@Override
public void eat() {
System.out.println("猫吃饭");
}
public void sleep() {
System.out.println("猫睡觉");
}
}
(5)抽象类实现的多态
public class Demo04 {
public static void main(String[] args) throws Exception {
// 抽象类实现的多态
Animal a=new Dog();
a.eat();
a.speak();
}
}
//父类
abstract class Animal {
abstract void speak();
public void eat() {
System.out.println("动物吃饭");
}
}
//子类
class Dog extends Animal{
// 必须重写虚类上的方法
@Override
void speak() {
System.out.println("狗叫");
}
}
(6)接口实现的多态
import java.util.*;
import com.justin.*;
import com.justin.Db;
import com.justin.Helper;
public class Demo04 {
public static void main(String[] args) throws Exception {
// 2 接口实现的多态
Animal a=new Dog();
a.speak();
}
}
interface Animal {
public void speak();
}
//子类
class Dog implements Animal{
@Override
public void speak() {
System.out.println("狗叫");
}
public void eat() {
System.out.println("狗吃");
}
}
【九】枚举
- Java 枚举是一个特殊的类,一般表示一组常量,
- 一年的 4 个季节
- 一年的 12 个月份
- 性别有男,女,未知
import java.util.*;
public class Demo04 {
public static void main(String[] args) throws Exception {
// 1 简单使用
System.out.println(Sex.Unknown);
System.out.println(Sex.Male);
// 2 更多使用
System.out.println("枚举顺序值,"+Week.SUNDAY.ordinal()); // 0
System.out.println(Week.MONDAY.id);
System.out.println(Week.MONDAY.meaning);
}
}
enum Sex {
Male,
Female,
Unknown;
}
enum Week {
SUNDAY(0, "星期日"),
MONDAY(1, "星期一"),
TUESDAY(2, "星期二"),
WEDNESDAY(3, "星期三"),
THURSDAY(4, "星期四"),
FRIDAY(5, "星期五"),
SATURDAY(6, "星期六");
public int id;
public String meaning;
Week(int id, String meaning) {
this.id = id;
this.meaning = meaning;
}
}
【十】包(package)
【1】什么是包
- 为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间。
我们可以定义很多包
不同包下,类名可以重复
同一个包下,类名不能重复
【2】包的作用
-
1、把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用
-
2、同文件夹一样,包采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。
-
3、包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。
【3】创建包
// 右键,新建包----》其实就是文件夹
com.dream
// 在包中定义类
com.dream
Db.java
Helper.java
- Helper.java
// 先声明是哪个包下的类(功能)
package com.dream;
public class Helper {
public int add(int a ,int b){
return a+b;
}
}
【4】引入包,并使用包中的类
// 导入包下的所有类
import com.dream.*;
// 单独导入指定的包
import com.dream.Db;
import com.dream.Helper;
public class Demo04 {
public static void main(String[] args) throws Exception {
// 实例化的到dream类
Helper h=new Helper();
System.out.println(h.add(4,5));
}
}
标签:Java,name,void,day07,System,7.1,println,public,out
From: https://www.cnblogs.com/dream-ze/p/17557889.html