面向对象
重点知识:
- 1、类和对象
- 2、构造方法
- 3、访问权限
- 4、继承
- 5、多态(最重要)
- 6、抽象和接口
- 7、内存分析
一、面向对象和面向过程
面向过程:侧重的是过程.
优点:简单
缺点:代码量大了之后,维护性非常差
面向对象:侧重的是对象.
优点:可扩展性非常强,维护成本低
缺点:上手难度高
二、类与对象
造车:
1、画图纸
(1)定义车的属性信息:color,speed,seat.
(2)定义车的动作:跑
2、拿图纸找工厂生产车
面向对象的世界里:
- 类 ----> 图纸
属性:这一类事物拥有的共同属性
动作:这一类事物共同能执行的功能
- 对象 ----> 使用类创建的具体某一个东西
对象能干什么完全取决于类是如何定义的
写代码
- 类要使用class来定义
属性:成员变量来描述,直接写在类中的变量。
动作:成员方法,不写 static 就是成员方法
创建对象:类 引用 = new 类();
public class Car {
//成员变量
String color;
int speed;
int seat;
//成员方法
public void run(){
System.out.println("车能跑");
}
public static void main(String[] args) {
//int a=10; //写在方法里的变量,局部变量
//创建对象
//在面向对象的世界里,变量被称为引用。
//java分为两种数据类型:1、基本数据类型;2、引用数据类型(String和创建的所有类)
Car c=new Car(); //创建对象
//让车去跑
//对象或引用.方法()
c.run(); //.表示调用
System.out.println("-------------------");
c.color="绿色";
c.speed=120;
c.seat=5;
System.out.println(c.color);
System.out.println(c.speed);
System.out.println(c.seat);
}
}
三、this关键词
this:当前类的对象
this 可以区分成员变量和局部变量
this 可以在方法内部获取到对象中的属性信息
public class Car {
String color;
int speed;
int seat=5;
public void run(){
//默认会有一个this,当前正在执行这个方法的对象
//获取到车的颜色和速度
System.out.println(this.color);
System.out.println(this.speed);
System.out.println("车能跑");
}
public void fly(String color){
System.out.println(this.color+"的车会飞,飞在"+color+"的云彩里");
//变量的查找顺序:先找自己方法内,如果自己没有,就去this里面找
}
public static void main(String[] args) {
Car c=new Car(); //车里的属性就是类中定义好的成员变量
c.color="红色";
c.speed=120;
c.run(); //在调用方法的时候,java会自动的把对象传递给方法,在方法中由this来接收
System.out.println(c);
c.fly("黑色");
}
}
四、构造方法
在创建对象的时候,自动调用的方法.
语法:
public 类名(传参){
}
注意:
1.没有返回值这一项
2.在我们new的时候,自动调用构造方法
作用:在创建对象的时候,给对象设置属性信息。
java会默认自动的送给每一个类一个无参数的构造方法。但是,如果你写了构造方法,系统就不再赠送了。
public class Car {
String color;
int speed;
int seat=5;
//java会自动给每一个类一个无参数的构造方法
//如果自己定义了构造方法,java就不再自动赠送了
//在创建对象的时候,自动调用方法
public Car(String color,int speed){
//设置属性信息
this.color=color;
this.speed=speed;
}
public void run(){
System.out.println(this.color+"的车会跑");
}
public static void main(String[] args) {
Car c1=new Car("绿色",120); //默认调用的是构造方法
Car c2=new Car("红色",180);
c1.run();
c2.run();
}
}
五、构造方法重载
构造方法也是方法,也可以 进行重载。
作用:可以有更多的方式去创建对象
使用this可以访问其他的构造方法。 this () ;
public class DaXia {
String name;
String waihao;
int age;
String bangPai;
//需要两个构造方法
public DaXia(String name,int age,String bangPai){
this.name=name;
this.age=age;
this.bangPai=bangPai;
}
//构造方法也是方法,也可以进行重载
//可以让我们用更多的方式去创建对象
public DaXia(String name,int age,String bangPai,String waihao){
/*this.name=name;
this.age=age;
this.bangPai=bangPai;*/
this(name, age, bangPai); //this还可以调用当前类中的其他构造方法
this.waihao=waihao;
}
public static void main(String[] args) {
//岳不群
DaXia dx1=new DaXia("岳不群",18,"华山派");
//武松
DaXia dx2=new DaXia("武松",19,"梁山","行者");
}
}
六、static 静态
静态的内容在内存中是保留一份的,并且各个对象之间进行共享
public class Person {
String name;
static String country="大清"; //被static修饰的是共享的
String address;
public Person(String name,String address){
this.name=name;
this.address=address;
}
public static void main(String[] args) {
Person p1=new Person("赵铁柱","八大胡同");
Person p2=new Person("李小花","朝阳门");
Person.country="民国";
System.out.println(p1.country);
System.out.println(p2.country);
}
}
使用 p1.country=“民国”,不推荐这样使用静态变量。
推荐使用类名去访问静态的内容
特点:
1.数据共享
2.属于类的,并不属于对象
3.优先对于对象产生的
通用构造器,静态构造器
public class test {
{
System.out.println("通用构造器");
}
static {
System.out.println("静态构造器");
}
public test(){
System.out.println("构造方法");
}
public static void main(String[] args) {
new test();
}
}
创建对象的过程(简单):
1.静态构造器
2.通用构造器
3.构造方法 ----> .创建对象
由于创建对象的过程是在静态内容加载完成之后,在静态方法和静态块里不能使用this.
public class test {
public static void pen(){
System.out.println("还我钱");
}
public static void main(String[] args) {
pen(); //在静态方法里调用静态的东西是可以的
test.pen(); //使用类名去访问静态方法
}
}
静态的内容使用类名去访问。
七、包和导包
包:其实本质就是文件夹
在代码中需要写 package 包名 ;
导包:
import 包+类 ;
不需要导包:
-
在自己包里
-
java.lang 包下的所有内容都不需要导包
八、访问权限
- public 公共的:在自己包内可以访问,在其他包内也可以访问
- default 包访问权限:在自己包内可以随意访问
- private 私有的:只能在自己类里面访问
九、getter和setter
成员变量一般使用private来声明,保护成员变量不被胡乱的赋值
setter:主要是给成员变量s赋值,做一定的保护
getter:从成员变量中获取数据
自动生成getter和setter:
空白位置 --> 右键 --> generate --> getter and setter --> 全选 --> OK
public class Person {
//成员变量是私有的
private String name;
private int age;
//setter
public void setName(String name){
this.name=name;
}
//有效的保护我们的成员变量不被胡乱的赋值
public void setAge(int age){
if(age<0){
this.age=0;
}else{
this.age=age;
}
}
//getter
public String getName(){
return this.name;
}
public int getAge(){
return this.age;
}
public void chi(){
System.out.println(this.name+"在吃东西");
}
}
public class TestPerson {
public static void main(String[] args) {
Person p=new Person();
/* p.name="周润发";
p.age=-1; //语法没有问题,但是逻辑上有问题 */
p.setName("周润发");
p.setAge(-1);
//查找这个人的名字和年龄
System.out.println(p.getName());
System.out.println(p.getAge());
p.chi();
}
}
十、继承
继承:子类可以自动拥有父类中除了私有内容外的其他所有内容。
当出现 x 是一种 y 的时候,x 就可以继承 y
public class 类 extends 父类 {
}
**作用:**简化代码开发。
子类对父类进行的拓展
public class YaoGuai {
String name;
private void pasi(){
System.out.println("妖怪怕死");
}
public void chiRen(){
System.out.println("妖怪会吃人");
}
}
public class HeiXiongGuai extends YaoGuai{ //子类实际上是对父类进行了扩展
public void tou(){
System.out.println("黑熊怪喜欢偷袈裟");
}
}
public class Test {
public static void main(String[] args) {
HeiXiongGuai hx=new HeiXiongGuai();
hx.name="大黑熊";
System.out.println(hx.name);
hx.chiRen();
hx.tou();
// hx.pasi(); //私有的内容是不能被继承的
}
}
十一、super关键字
super:表示父类中的内容
this:表示自己类中的内容
可以用super和this来区分父类和子类中的内容
创建对象的过程:先创建父类的对象,然后创建子类的对象
public class Hero {
String name="英雄";
public Hero(){
System.out.println("这是父类的构造方法");
}
}
ublic class SunWuKong extends Hero{
String name="孙大圣";
public SunWuKong(){
super(); //还原程序 在子类构造方法的第一行,默认调用父类的构造方法
System.out.println("这是子类的构造方法");
}
public void chi(){
//想看到父类中的name
System.out.println(super.name);
//先找自己类,然后找父类
System.out.println(this.name+"在吃桃子");
}
public static void main(String[] args) {
SunWuKong s=new SunWuKong();
s.chi();
}
}
小总结:
-
super可以获取到父类中的内容
-
可以调用父类中的构造方法,必须写在子类构造方法的第一行
如果父类的构造方法是无参的,可以不写;如果父类没有无参数的构造,必须要写super
十二、方法的重写
重写:子类对父类中提供的方法进行重新定义
语法:子类和父类中的方法声明完全一致
重写又被称为方法的覆盖
public class LiYuan {
public void makeCountry(){
System.out.println("李渊想建立一个自己的国家");
}
}
public class LiShiMin extends LiYuan{
//子类中的方法必须和父类中的方法完全一致
public void makeCountry(){
//半盖.
super.makeCountry(); //super可以调用父类中被重写了的方法
System.out.println("李世民也想建立一个自己的国家");
}
public static void main(String[] args) {
LiShiMin lsm=new LiShiMin();
lsm.makeCountry();
}
}
十三、多态
多态:同一个对象拥有多种形态
**作用:**把不同的数据类型进行统一. 让程序具有超强的可拓展性
小知识点:
-
把子类的对象赋值给父类的变量 —> 向上转型
缺点:向上转型会屏蔽掉子类中特有的方法
-
把父类的对象赋值给子类的变量 —> 向下转型
向下转型有可能有风险,Java要求必须要写强制类型转换
(转会之后的数据类型)变量
//猫是一种动物 ---> 继承关系
//可以把猫当成动物来看
public class Cat extends Animal{
public void eat(){
System.out.println("猫吃鱼");
}
public void CatMouse(){
System.out.println("猫喜欢抓老鼠");
}
}
public class Dog extends Animal{
public void eat(){
System.out.println("狗吃骨头");
}
}
public class DaXiang extends Animal{
public void eat(){
System.out.println("大象吃香蕉");
}
}
public class Animal {
public void eat(){
System.out.println("动物在吃");
}
}
public class Person {
public void feed(Animal ani){ //接收到的所有动物都是Animal
ani.eat();
}
}
public class Client {
public static void main(String[] args) {
//向上转型
Animal ani1= new Cat(); //可以把猫当成动物来看,把子类的对象赋值给父类的引用(变量)
Animal ani2=new Dog();
Animal ani3=new DaXiang();
Person p=new Person();
p.feed(ani1);
p.feed(ani2);
p.feed(ani3);
//向下转型
Cat cc=(Cat)ani1;
cc.CatMouse();
}
}
十四、final关键字
- 被final修饰的变量不可以被改变,又被称为常量。
- 被final修饰的方法不可以被重写。
- 被final修饰的类不可以被继承。
final总结就是不可变
十五、抽象、
抽象:现实中不存在的东西
在Java中:只声明,不实现
抽象方法:使用abstract来修饰,不可以有方法体,直接用分号结束即可。
抽象类:如果一个类中有抽象方法,这个类必须是一个抽象类
特点:
- 抽象类不可以创建对象
- 抽象类的子类,必须重写父类中的抽象方法;否则,子类必须也是抽象类
通过抽象类可以强制的要求子类中必须有哪些方法
小知识点:抽象类中可以有正常的方法
public abstract class Animal { //类中如果有抽象方法,那么这个类必须是一个抽象类
//abstract修饰方法,这个方法就是一个抽象方法,抽象方法没有方法体,直接;结束
public abstract void eat();
public abstract void dong();
//抽象类可以有正常的方法
public void smell(){
System.out.println("我在smell");
}
}
public class Cat extends Animal{
public void eat() {
System.out.println("猫吃鱼");
}
public void dong(){
System.out.println("猫懒洋洋地动");
}
}
public class Client {
public static void main(String[] args) {
Animal c=new Cat(); //这里是多态性
c.eat();
c.dong();
/* Animal ani=new Animal();*/ //抽象类不可以创建对象
}
}
十六、接口
接口实际上是一种特殊的抽象类
接口中所有的方法都是抽象方法
接口使用interface来声明
类只能单继承,接口支持多实现
接口同样具有多态性
接口可以把很多不相关的内容进行整合
特点:
- 接口中所有的方法都是抽象方法,都是公开的
- 接口中所有的变量都是全局静态常量
/**
* 能继承接口的只能是接口
* 接口和类只能是实现关系 implements
* */
public interface Valuable { //接口使用interface来声明,已经不再是类了
public static final int money=100;
//接口中所有方法都是抽象方法,可以省略掉abstract
//接口中所有的内容都是公开的,公共的。
void getMoney(); //接口中的所有方法都是抽象方法,不可以有正常的方法
}
public interface Protectable {
public void cang();
}
public class Animal {
public void eat(){
System.out.println("动物会吃");
}
}
//类可以继承一个类,实现多个接口
public class Panda extends Animal implements Valuable,Protectable{
@Override //重写
public void eat() {
System.out.println("熊猫吃竹子");
}
@Override
public void cang() {
System.out.println("把熊猫藏山里");
}
@Override
public void getMoney() {
System.out.println("熊猫可以换钱");
}
}
public class Gold implements Valuable{
//必须要实现抽象方法
public void getMoney(){
System.out.println("黄金可以换钱");
}
}
public class Test {
public static void main(String[] args) {
Valuable g=new Gold(); //接口一样具有多样性
g.getMoney();
Panda p=new Panda();
Animal ani=new Panda(); //向上转型
Valuable v=new Panda(); //向上转型
Protectable pro=new Panda(); //向上转型
p.eat();
p.cang();
p.getMoney();
/*ani.cang(); //站在动物角度只能吃*/
p.getMoney();
/*ani.getMoney(); //不行*/
v.getMoney();
pro.cang();
System.out.println(Valuable.money);
}
}
十七、成员变量初始值
Java中所有的变量必须先声明,后赋值才能使用
Java中的成员变量,在创建对象的时候,都会执行依次初始化操作,都会给一个默认值
基本数据类型默认值都是0 包括 boolean —> false
引用数据类型:null(null表示空,什么都没有,占位)
十八、object
万事万物皆为对象
所有的东西都是对象
在Java中所有的类都有继承object
object是一个类,所有类的根
我们写的类即使不写继承关系,那么默认也会继承object.
public class Student extends Object{
public static void main(String[] args) {
Student s=new Student();
}
}
十九、equals 和 ==
==:判断左右两边数据是否一致
equals:Object 类提供的一个方法,用来判断两个对象是否相等
equals可以自己重写
public class Cat {
String name;
String color;
public Cat(String name,String color){
this.color=color;
this.name=name;
}
public boolean equals(Cat c){
if(this.color==c.color){ //单纯的自己去写判断的逻辑
return true;
}else{
return false;
}
}
public static void main(String[] args) {
Cat c1=new Cat("小花","红色");
Cat c2=new Cat("小花","红色");
/* System.out.println(c1==c2); //false ==:默认判断的是两个对象的内存地址是否一致,一般用在基本数据类型上*/
/* System.out.println(c1.equals(c2)); //false 默认调用的是object提供的equals方法*/
System.out.println(c1.equals(c2)); //得到的是true,此时调用的子类中的equals方法
}
}
字符串的判断一定要用equals来判断
public class Test {
public static void main(String[] args) {
String str1="小红";
String str2="小红"; //第二次的小红并没有单独占用内存空间
System.out.println(str1==str2);
System.out.println(str1.equals(str2));
String str3=new String("钢筋");
String str4=new String("钢筋");
System.out.println(str3==str4); //false
System.out.println(str3.equals(str4)); //true 判断两个字符串的内容是否一致
}
}
二十、toString 方法
toString() 对一个对象的字符串的表示形式
Java推荐你重写这个方法,默认的那个太丑了
public class Cat { //类默认继承object
String name;
String color;
public Cat(String name,String color){
this.name=name;
this.color=color;
}
//子类对父类提供的方法不满意,重写
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", color='" + color + '\'' +
'}';
}
public static void main(String[] args) {
Cat c=new Cat("小花","绿色");
//直接打印这个c
System.out.println(c);
//默认打印对象,自动的执行这个对象中的toString()方法
System.out.println(c.toString());
//默认的toString() --> 包+类@内存地址
}
}
二十一、instanceof 关键字
instanceof :判断 xxx 对象是否是 xxx 类型的
public class Cat extends Animal{
public static void main(String[] args) {
Animal ani=new Cat();
if(ani instanceof Cat){ //判断ani是否是一只猫
System.out.println("是一只猫,撸一撸");
}else{
System.out.println("不是一只猫");
}
}
}
二十二、参数传递的问题
值传递:把变量的值作为参数进行传递
引用传递:直接把变量作为参数进行传递
Java使用的是值传递