java面向对象
面向对象概述
重要知识点:
-
类与对象
-
构造方法
-
访问权限
-
继承
-
多态(最重要)
-
抽象和接口
-
内存分析
面向对象和面向过程
面向过程:侧重的是过程。
优点:新手上手简单
缺点:代码量大了后,维护性非常差。
面向对对象:侧重的是对象。(你是上帝视角,你创建一个大象,告诉大象,进冰箱)
优点:可扩展性非常强,维护成本低。
缺点:新手上手难。
类与对象
造车:
-
画图纸。
-
定义车的属性信息: color,speed,seat.
-
定义车的动作:跑
-
2.拿着图纸找工厂生产车
面向对象的世界里:
类:就是图纸
属性:这一类事物拥有的共同属性。
动作:这一类事物共同能执行的功能。
对象:使用类创建具体某一东西
对象能干什么?完全取决于类如何定义。
写代码:
类要使用class来定义
属性:成员变量来描述,直接写在类中的变量。
动作:成员方法,不写static就是成员方法。
创建对象:
类 引用 = new 类 ();、
this关键词
this:当前类的对象
this可以在方法内部获取到对象中的属性信息
this还可以区分局部变量和成员变量
构造方法
在创建对象的时候,自动调用的方法。
语法:
public 类名(传参){}
package object01;
public class Car {
String color;//颜色
int speed;//速度
int seat=5;//座位
//java会默认赠送给每一个类一个无参数的构造方法,简称无参构造
//如果你自己定义了构造方法,java就不再赠送你了
//在创建对象的时候,自动调用方法
//public 类名(){}
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("红色",150);
c1.run();
c2.run();
}
}
运行结果:
绿色的车在跑
红色的车在跑
ackage CG;public class GZ {
public String name;
//无参构造
//实例化初始值
//1.使用new关键字,本质是在调用构造器
public GZ(){
this.name="cc";
}
//有参构造
//一旦定义了有参构造,无参就必须显示定义
public GZ(String name){
this.name=name;
}
}
构造器:
-
和类名相同
-
没有返回值
作用:
-
new 本质在调用构造方法
-
初始化对象的值
注意点:
-
定义有参构造之后,如果想使用无参构造,就需要显示定义一个无参构造
快捷键:
alt+insert==>>Constructor==>>OK==>>自动生成有参构造方法
alt+insert==>>Constructor==>>Select None==>>自动生成无参构造方法
注意:
-
必须与类名相同,没有返回值这一项(不能写void)
-
在我们new的时候 ,自动调用构造方法
-
java会默认赠送给每一个类一个无参数的构造方法,简称无参构造
-
如果你自己定义了构造方法(有参构造),java就不再赠送你了(系统默认的无参构造就会被覆盖)
作用:创建对象的时候,给对象设置属性信息
构造方法的重载
package object01;
public class Daxia {
String nema;
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,age,bangpai);//this还可以调用当前类中其他的构造方法
this.waihao=waihao;
}
public static void main(String[] args) {
//岳不群
Daxia dx1=new Daxia("岳不群",48,"华山派");
//武松
Daxia dx2=new Daxia("武松",28,"梁山","行者");
}
}
构造方法也是方法,也可以进行重载
作用:可以又更多的方式去创建对象
使用this可以访问其他的构造方法。
this()
static
static静态(共享同一内容)
有多少人就要改多少次。
静态的内容在内存中是保存一份的,并且各个对象之间进行共享
使用p1.country="民国",不推荐这样使用静态变量
推荐使用类名去访问静态的内容
例:Person.country
特点:
-
数据共享
-
属于类的 ,不属于对象
-
优先于对象产生
了解一下
通用构造器
静态构造器
创建对象的过程(简单):
-
静态构造器
-
通用构造器
-
构造方法->创建对象
由于创建对象的过程是在静态内容加载完成之后,在静态方法和静态块里不能使用this.
静态的内容使用类名去访问
包和导包
包:其实本质上就是文件夹
在代码中需要写package 包名:
导包:
import包+类(快捷键:alt+enter)
不需要导包的情况:
-
在同一个包
-
java.lang包下的所以的内容都不需要导包
String
System.out.println()
访问权限
-
public 公共的.所以的人都可以访问·
-
default 包访问权限.在自己包内可以随意访问.
-
private 私有的
我们用的最多的是private和public
setter和getter(封装)
我们程序设计要追求“高内聚”,”低耦合“。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;
低耦合:仅暴露少量的方法给外部使用
成员变量一般使用private来声明,保护成员变量不被胡乱的赋值
setter主要是给成员变量赋值
getter从成员变量中获取数据
setter的作用:
允许我外界修改私有数据
getter的作用:
允许外界读取私有数据
快捷生成方式
空白位置->右键->generate->getter and setter->全选->OK.
package com.xyq.entitiy;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+"在吃东西");
}
}
package com.xyq.entitiy;
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();
}
}
运行结果:
周润发
0
周润发在吃东西
作用:
-
提高程序的安全性,保护数据
-
隐藏代码的实现细节
-
统一接口
-
提高系统的可维护性
继承(extends)
extends的意思是"扩展",子类是父类的扩展。
JAVA中只有单继承,不存在多继承。
继承关系的俩个类,一个为子类(派生类),一个为父类(基类),子类继承父类,使用关键字extends来表示
继承:子类可以自动拥有父类中除了私有内容外的其他所有内容当出现x是一种y的时候,x就可以继承y
例:
-
猫是一种动物
-
如来是一个神仙
-
黑熊怪是一种妖怪
public class类 extends 父类(
)
package com.xyq.jicheng;
//父类
//在java中,所有的类,都默认直接或者间接继承Object
public class YaoGai {
String name;
//public,公共的
//protected,受保护的
//default,默认的
//private,私有的
private void pashi(){
System.out.println("妖怪怕死!");
}
public void chiRen(){
System.out.println("妖怪会吃人!");
}
}
package com.xyq.jicheng;
//子类
//子类继承了父类,就会拥有父类的全部方法(不包括私有的)!
public class HeiXiongGuai extends YaoGai{
public void tou(){
System.out.println("黑熊怪喜欢偷袈裟");
}
}
package com.xyq.jicheng; public class Test { public static void main(String[] args) { HeiXiongGuai HXG=new HeiXiongGuai(); HXG.name="大黑熊"; System.out.println(HXG.name); HXG.chiRen(); HXG.tou(); // HXG.pashi();//私有的不能被继承 } } 运行结果: 大黑熊 妖怪会吃人! 黑熊怪喜欢偷袈裟
作用:简化代码的开发
子类对父类进行扩展
super关键字
super:表示访问父类中的内容
this:表示访问自己类中的内容
用super和this来区分父类和子类中重名的内容
创建对象的过程:先创建父类的对象,然后创建子类对象
总结:
-
super可以获取到父类的内容
-
可以调用父类中的构造方法,必须写在子类构造方法的第一行,如果父类的构造是无参数的,可以不写(默认会有),如果父类没有无参数的构造,必须要写super
方法的重写(方法覆盖)
重写:子类对父类中提供的方法进行重新定义
语法:子类和父类中的方法的声明完全一致
重写又被称为方法的覆盖
package com.xyq.chongxie; public class LiYuan { public void makeCountry(){ System.out.println("李渊想建立一个自己的国家"); } }
package com.xyq.chongxie; public class LiShiMing extends LiYuan { public void makeCountry(){ //半盖 super.makeCountry();//super可以调用父类中被重写了的方法 System.out.println("李世民也想建立一个自己的国家"); } public static void main(String[] args) { LiShiMing lsm=new LiShiMing(); lsm.makeCountry(); } }
多态(套娃)
多态:同一个对象拥有多个形态.
作用:把不同的数据类型进行统一
kage com.xyq.duotai; //猫是一种动物 //可以把猫当成动物来看 //子类重写了父类的方法,执行子类的方法 public class Cat extends Animal { public void eat(){ System.out.println("猫正在吃鱼!"); } }
package com.xyq.duotai; //子类重写了父类的方法,执行子类的方法 public class Dog extends Animal { public void eat(){ System.out.println("狗正在吃骨头!"); } }
package com.xyq.duotai; //子类重写了父类的方法,执行子类的方法 public class DaXiang extends Animal { public void eat(){ System.out.println("大象正在吃香蕉!"); } }
package com.xyq.duotai;
public class Person {
//接收到的所以的动物都是Animal
public void food(Animal ani){
ani.eat(); }
// public void feedcat(Cat c){
// c.eat();
// }
//
// public void feedgod(Dog d){
// d.eat();
// }
//
// public void feedDaXiang(DaXiang dx){
// dx.eat();
// }}
package com.xyq.duotai;
public class Animal {
public void eat(){
System.out.println("动物正在吃!");
}
}
package com.xyq.duotai;
public class Client {
public static void main(String[] args) {
//向上转型
//缺点:会屏蔽掉子类中特有的方法
// Cat c=new Cat();//创建一支猫
Animal ani1=new Cat();
//可以把猫当成动物来看,把子类的对象赋值给父类的引用(变量)向上转型
Animal ani2= new Dog();
Animal ani3= new DaXiang();
Person p=new Person();
p.food(ani1);
p.food(ani2);
p.food(ani3);
//多态:把不同的数据类型进行统一
//站在动物的角度,不是所有动物都会抓老鼠,慎用
//向下转型
//Cat cc= (Cat)ani1;
//cc.catchMouse(); }
}
运行结果:
猫正在吃鱼!
狗正在吃骨头!
大象正在吃香蕉!
小知识点:
-
把子类的对象赋值给父类的变量->向上转型
缺点:屏蔽掉子类中特有的方法
-
把父类的变量转化回子类的变量->向下转型
向下转型有可能有风险,java 要求必须强制类型转换(强转:转换之后的数据类型+变量)
特点:让程序具有超强的可扩展性
多态注意事项:
-
多态是方法的多态,属性不具有多态
-
父类和子类,有联系,类型转换异常!:ClassCastException!
-
存条件:继承关系,方法需要重写, 父类引用指向子类对象! father f1= new Son(); //子类是父类的一种形态
不能重写的:
1. static 方法,属于类,它不属于实例;
2. final 常量;
3. private 方法;
练习
现在有两种数据库,一个是Mysql数据库,另一个是Oracle数据库,请通过程序设计,设计一个可以根据用户输入来自动选择数据库,并执行增删改查操作
需求:
在main里,根据用户输入的编号,系统自动创建一个Mysql或者Oracle,然后执行增删改查操作.
package com.xyq.lianxi; public class DNF extends Game { public void play(){ System.out.println("刷副本中..."); } }
package com.xyq.lianxi; public class LOL extends Game{ public void play(){ System.out.println("快乐风男eee..."); } }
package com.xyq.lianxi; public class CS extends Game{ public void play(){ System.out.println("RushB GO GO GO!"); } }
package com.xyq.lianxi; public class Game { public void start(){ System.out.println("开机中..."); } public void play(){ System.out.println("我要打游戏!"); } public void end(){ System.out.println("关机,睡觉!"); } }
package com.xyq.lianxi; public class Player { public void happy(Game game){ game.start();//一定是父类中的方法 game.play();//一定是子类中的方法 game.end();//一定是父类中的方法 } }
package com.xyq.lianxi; public class Client { public static void main(String[] args) { Game c1=new DNF();//向上转型 Game c2=new LOL(); Game c3=new CS(); Player p=new Player(); p.happy(c1); p.happy(c2); p.happy(c3); } } 运行结果: 开机中... 刷副本中... 关机,睡觉! 开机中... 快乐风男eee... 关机,睡觉! 开机中... RushB GO GO GO! 关机,睡觉!
final(最终的)
-
被final修
-
饰的变量不可以被改变,又被称为常量
-
被final修饰的方法不可以被重写
-
被final修饰的类不可以被继承
final总结是不可变
抽象(abstract)
抽象:现实中不存在的东西
在java中,只声明,不实现.
抽象方法:使用abstract来修饰.直接用分号结束即可
抽象类:如果一个类中有抽象的方法,这个类必须是一个抽象类.
特点:
1. 抽象类不可创建对象 2. 抽象类的子类,必须重写父类中的抽象方法或者子类也是个抽象类
作用:通过抽象类可以强制的要求子类中必须有哪些方法.
小知识点:抽象类中可以有正常的方法
package com.xyq.chouxiang; public class Cat extends Animal { public void eat(){ System.out.println("猫在吃鱼!"); } public void dong(){ System.out.println("猫在捉老鼠!"); } }
package com.xyq.chouxiang; //类中如果有抽象方法,那么这个类必须是一个抽象的类 public abstract class Animal { //abstract修饰方法,是个抽象的修饰方法 //抽象的方法没有方法体.直接;结束 public abstract void eat(); public abstract void dong(); //抽象类可以有正常的方法 public void sum(){ System.out.println("我在smell..."); } }
package com.xyq.chouxiang; public class Client { public static void main(String[] args) { Animal c=new Cat(); c.eat(); c.dong(); c.sum(); } } 运行结果: 猫在吃鱼! 猫在捉老鼠! 我在smell...
接口(interface)
接口实际上是一种特殊的抽象类
接口中所有的方法都是抽象方法
接口使用interface来声明
接口实现implements
类只能单继承.接口是多实现
package com.xyq.jiekou; public class Animal { public void eat(){ System.out.println("动物会吃!"); } }
package com.xyq.jiekou; public class Gold implements Valuable{ //必须实现抽象方法 public void getMoney(){ System.out.println("黄金可以换钱!"); } }
package com.xyq.jiekou; public interface Protectable { public void cang(); }
package com.xyq.jiekou; /** 能继承接口的只能是接口 * 接口和类只能是实现关系 implements* */ public interface Valuable { //接口中所以的方法都是抽象方法 //接口中所以的内容都是公开的,公共的 public abstract void getMoney(); }
package com.xyq.jiekou; //类可以继承类,实现多个接口 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("熊猫可以换钱!"); } }
package com.xyq.jiekou; public class Test { public static void main(String[] args) { Panda p=new Panda(); Animal ani1=new Panda(); Valuable v=new Panda(); Protectable pro=new Panda(); //第一种方法 p.eat(); p.cang(); p.getMoney(); //第二种方法 ani1.eat(); v.getMoney(); pro.cang(); } }
接口同样具有多态性
作用:接口可以把很多不想关的内容进行整合.
特点:
-
接口中所有的方法都是抽象方法,并且都是公开的.
-
接口中所有的变量都是全局静态变量
小练习
现在有两种数据库,一个是Mysql数据库,另一个是Oracle数据库,请通过程序设计,设计 一个可以根据用户输入来自动选择数据库,并实行增删改查操作
需求:
在main里,根据用户输入的编号,系统自动创建一个MysqlDao或者OracleDao,然后执行增删改查操作
package LX.jiekou; public interface IDAO { void add(); void del(); void upd(); void sel(); void connect(); }
package LX.jiekou; public class MysqIDAO extends AbstractDao { public void connect() { System.out.println("myql的链接..."); } }
package LX.jiekou; public class OracleDao extends AbstractDao { public void connect() { System.out.println("Orac的链接..."); } }
package LX.jiekou; //抽象类 public abstract class AbstractDao implements IDAO { public void add() { System.out.println("增加"); } public void del() { System.out.println("删除"); } public void upd() { System.out.println("修改"); } public void sel() { System.out.println("查询"); } }
package LX.jiekou; import java.util.Scanner; public class Client { public static void main(String[] args) { System.out.println("请选择输入数据库(1.MysqlDao/2.OracleDao)"); Scanner s=new Scanner(System.in); int n=s.nextInt(); IDAO dao; if (n==1){ dao=new MysqIDAO(); } else { dao=new OracleDao(); } dao.connect(); dao.add(); dao.del(); dao.upd(); dao.sel(); } } 运行结果: 1 myql的链接... 增加 删除 修改 查询
成员变量初始值
java中所有的变量必须先声明,后赋值才能使用
public class Test { public static void main(String[] args) { int t; System.out.println(t); } } 运行结构: java: 可能尚未初始化变量t
java中的成员变量,在创建对象的时候,都会执行以下初始化操作,都会给一个初始值.
public class Person { int t; }
public class Test { public static void main(String[] args) { Person p=new Person(); System.out.println(p.t); } } 运行结果:0
基本数据类型默认值都是0 ,包括boolean->false
引用数据类型:null
null:表示空,什么都没有,占位
object
java中一直流传:万事万物皆为对象.
在java中所以的类都要继承object -
object是一个类,所有类的根
我们写的类即便不写继承关系,那么默认也会继承object
equals和==
==:判断左右两端的数据是否一致
equals:object类提供的一个方法,用来判断两个对象是否相等(???)
equals可以重写
package LX.equals; public class Cat { String name; String color; public Cat(String name,String color){ this.name=name; this.color=color; } 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))默认调用的是Object提供的equals方法,false System.out.println(c1.equals(c2));//得到的是true,此时调用的子类中的equals方法 } } 运行结果:true
字符串的判断一定要用equals来判断(可以帮助我们判断内容)
package LX.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 判断两个字符串的内容是否一致 //字符串的判断必须用 equals 可以帮助我们判断内容 } } 运行结果: true true false true
小练习:模拟用户登录
package LX.equals; import java.util.Scanner; public class Test2 { public static void main(String[] args) { String yhm="admin"; String mima="123"; Scanner scanner=new Scanner(System.in); System.out.println("请输入用户名:"); String y=scanner.nextLine(); System.out.println("请输入密码"); String m=scanner.nextLine(); //用equals判断 if (yhm.equals(y)&&mima.equals(m)){ System.out.println("登入成功!"); }else { System.out.println("登入失败!"); } } } 运行结果: 请输入用户名: admin 请输入密码 123 登入成功!
toString方法
toString()对一个对象的字符串的表示形式
JAVA官方推荐你重写这个方法。默认太丑了
package LX.entity;
public class Cat { //默认继承Object
String name;
String color;
public Cat(String name,String color){
this.name=name;
this.color=color;
}
//子类对父类的方法不满意,重写
instanceof关键字
instanceof:判断xxx对象是否是xxx类型
package CG01;
public class Cat extends Animal{
public static void main(String[] args) {
Animal ani=new Cat();
//判断ani是否是一只猫
if(ani instanceof Cat){
System.out.println("是一只猫,撸一撸");
}else{
System.out.println("不是一只猫");
}
}
}
参数传递的问题
值传递:把变量的值作为参数进行传递
引用传递:直接把变量作为参数进行传递
java使用的是值传递:
package CG02; public class Cat { public String name; public Cat(String name) { this.name = name; } }
package CG02; public class Test { public static void change(Cat c){ c = new Cat("黑猫"); } public static void main(String[] args) { Cat c =new Cat("蓝猫"); change(c); System.out.println(c.name); } } 运行结果: 蓝猫
package CG02; public class Cat { public String name; public Cat(String name) { this.name = name; } }
package CG02; public class Test { public static void change(Cat c){ c.name ="土猫"; } public static void main(String[] args) { Cat c =new Cat("蓝猫"); change(c); System.out.println(c.name); } } 运行结果: 土猫
内部类(不推荐经常使用)
内部类:内部类就是在一个类的内部在定义一个类,比如,A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了。
-
成员内部类
-
静态内部类
-
局部内部类
-
匿名内部类
ackage CG01;public class Outer {
private int id=10;
public void out(){
System.out.println("这是外部的方法");
}
//局部内部类
public class Inner{
public void in(){
System.out.println("这是内部类的方法");
}
//获得外部类的私有属性
//内部类当然可访问static,但是static的内部类不能访问外部非static属性
public void getID(){
System.out.println(id);
}
}
package CG01;
public class Application {
public static void main(String[] args) {
Outer outer=new Outer();
//通过这个外部类来实例化内部类~
Outer.Inner inner=outer.new Inner();
inner.in();
inner.getID();
}
}
运行结果:
这是内部类的方法
10
package CG;
public class CK {
public static void main(String[] args) {
//没有名字初始化类,不用讲实例保存到变量中~~
new Apple().eat();
new UserService(){
总结
本章重点:
-
类与对象->封装
-
构造 this.super
-
访问权限
-
继承
-
多态(可以把不同的数据类型进行统一)
-
抽象(意义:对子类进行约束,子类必须实现重写父类的抽象方法)
-
接口(LOL中如何继承英雄的物理属性和魔法属性,就可以用接口将其区分)
-
内存简单分析
你好!
你好!
你好!
你好!