目录
1.万物皆对象
package oop;
public class OopTest {
public static void main(String[] args) {
Phone p = new Phone();
p.call();
p.message();
p.learn();
System.out.println(p.brand);//null
System.out.println(p.price);//0.0
System.out.println(p.size);//0.0
System.out.println(p.color);//null
//以下为匿名对象,其实我更喜欢这么写 0.0
new Phone().call();
new Phone().learn();
new Phone().message();
System.out.println(new Phone().brand);
System.out.println(new Phone().price);
System.out.println(new Phone().size);
System.out.println(new Phone().color);
}
}
class Phone{
//特征(属性)--类的成员变量来描述--位置:类里方法外
String brand;//品牌
double price;//价格
double size;//尺寸
String color;//颜色
//行为(功能)--类的方法来描述--修饰符 返回值类型 方法名(参数列表){方法体}
public void call() {
System.out.println("正在打电话");
}
public void message() {
System.out.println("正在发短信");
}
public void learn() {
System.out.println("正在看直播");
}
}
2.面向对象的三大特征:封装,继承,多态
2.1封装:
属性封装后无法直接查看和修改,需要generate Getter() and Setter().也可以用构造方法修改
//封装
private String brand;
//第一种更改和查看方法
p.setBrand("Huawei");
System.out.println(p.getBrand());
//第二种更改方法,生成一个带参数的构造方法
public Phone(String brand) {
this.brand = brand;
}
Phone p = new Phone("Huawei");
//或者这样写
System.out.println(new Phone("Huawei").getBrand());
访问控制符:
2.2构造方法
Phone p = new Phone(); new Phone();//都会调用无参构造 Phone p = new Phone("Huawei"); new Phone("Huawei");//调用含参构造 /*******************************************/ new Phone().call();//先去调用无参构造,再执行call()方法
2.3构造代码块
- 位置: 在类的内部,在方法的外部
- 作用: 用于抽取构造方法中的共性代码
- 执行时机: 每次调用构造方法前都会调用构造代码块
- 注意事项: 构造代码块优先于构造方法加载
2.4局部代码块
- 位置: 在方法里面的代码块
- 作用: 通常用于控制变量的作用范围,出了花括号就失效
- 注意事项: 变量的作用范围越小越好,成员变量会存在线程安全的问题
注意执行顺序:构造代码块->构造方法->普通方法->局部代码块
new Phone().call();1.执行构造代码块2.执行无参构造3.执行方法4.执行局部代码块
2.5 this
功能1.调用本类中的成员变量
功能2.this(),用于构造方法中,调用无参或者含参构造,注意不能用于普通方法。
3.继承
3.1概念
继承是面向对象最显著的一个特征
继承是从已有的类中派生出新的类,新类能吸收已有类的数据属性和行为,并扩展新的能力.
Java继承是会用已存在的类的定义作为基础建立新类的技术
新类的定义可以增加新的数据或者新的功能,也可以使用父类的功能,但不能选择性的继承父类(超类/基类)
这种继承使得复用以前的代码非常容易,能够大大的缩短开发的周期,降低开发费用.
3.2特点
1.相当于子类把父类的功能复制了一份
2.Java只支持单继承
3.继承可以传递(爷爷/儿子/孙子这样的关系)
4.父类的私有成员也会被继承,但由于私有限制访问,所以子类不能使用父类的私有资源
5.继承多用于功能的修改,子类可以在拥有父类功能的同时,进行功能拓展
3.3super
1.super.xx -->父类的成员变量
2.子类的构造函数默认有super();
package oop;
public class OopTest {
public static void main(String[] args) {
new Phone().call();
System.out.println("****");
new Iphone().call();
}
}
class Phone{
static {
System.out.println("静态代码块");
}
static double price;//价格
double size;//尺寸
String color;//颜色
{
System.out.println("我是一个构造代码块");
}
public Phone(){
System.out.println("父类无参构造");
}
public void call() {
System.out.println("正在打电话");
{
System.out.println("我是一个局部代码块");
}
}
}
class Iphone extends Phone{
public Iphone(){
//super();
System.out.println("子类无参构造");
}
// public void call(){
// System.out.println("子类打电话");
// }
}
执行结果:
****补充一道多态题目,求输出值
方法重写,就调用子类方法。属性值,就近
变量basename在子类,所以输出子类值,但是此时子类无参构造没执行完,子类变量还没加载
package oop;
public class Test {
public static void main(String[] args) {
Base b = new Sub();
}
}
class Base {
private String baseName = "base";
public Base() {
callName();
}
public void callName() {
System.out.println(baseName);
}
}
class Sub extends Base
{
private String baseName = "sub";
public void callName()
{
System. out. println (baseName) ;
}
}
null
3.4 Static
3.4.1特点
1.static可以修饰成员变量和方法
2.被static修饰的资源称为静态资源
3.静态资源随着类的加载而加载,最先加载,优先于对象进行加载
4.静态资源可以通过类名直接调用,也被称作类资源
5.静态被全局所有对象共享,值只有一份
6.静态资源只能调用静态资源,普通资源可以调用静态资源
7.静态区域内不允许使用this与super关键字
static double price;//价格 //不用new对象 可以直接加载 System.out.println(Phone.price);
3.4.2静态代码块
静态资源随着类的加载而加载,并且只被加载一次,一般用于项目的初始化
特点: 被static修饰,位置在类里方法外
3.4.3三种代码块的比较
- 静态代码块:在类加载时就加载,并且只被加载一次,一般用于项目的初始化
- 构造代码块:在创建对象时会自动调用,每次创建对象都会被调用,提取构造共性
- 局部代码块:方法里的代码块,限制局部变量的范围
3.4.4final
特点
被final修饰的类,不能被继承
被final修饰的方法,不能被重写
被final修饰的字段是个常量,值不能被修改
常量的定义形式:final 数据类型 常量名 = 值
4.多态
4.1前提:
多态对象把自己看做是父类类型
- 成员变量: 使用的是父类的
- 成员方法: 由于存在重写现象,所以使用的是子类的
- 静态成员: 随着类的加载而加载,谁调用就返回谁的,所以跟成员变量性质差不多,执行父类的静态资源
4.2 静态方法
package practise;
public class duotai {
public static void main(String[] args) {
a ab=new b();
ab.play();//执行父类玩
/*多态中,调用的静态方法是父类的,因为多态对象把自己看作是父类类型
* 直接使用父类中的静态资源*/
}}
class a{
public static void play(){
System.out.println("父类玩");
}
}
class b extends a{
/*这不是一个重写的方法,只是恰巧在两个类中出现了一模一样的两个静态方法
* 静态方法属于类资源,只有一份,不存在重写的现象
* 在哪个类里定义,就作为哪个类的资源使用*/
public static void play(){
System.out.println("子类玩");
}
public void eat(){
}
}
4.3抽象类
4.3.1 特点:
1.abstract 可以修饰方法或者类
2.被abstarct修饰的类叫做抽象类,被abstract修饰的方法叫做抽象方法
3.抽象类中可以没有抽象方法
4.如果类中有抽象方法,那么该类必须定义为一个抽象类
5.子类继承了抽象类以后,要么还是一个抽象类,要么就把父类的所有抽象方法都重写
6.多用于多态中
7.抽象类不可以被实例化
4.3.2 注意:
抽象方法没有方法体,不能实例化。抽象方法需放在抽象类中。
子类继承了抽象类以后,要么还是一个抽象类,要么就把父类的所有抽象方法都重写
这里涉及抽象方法存在的意义:就是提取共性放在父类中,是所有子类都必须具备的,例如动物都具备吃睡,子类也必须具备。老师都具备备课讲课的方法,所以子类也都要有次方法。
抽象类不能实例化,所以可以用多态形式,注意子类构造方法默认有super();
package practise;
public class AbstractTest {
public static void main(String[] args) {
new Dog(1).eat();
Animal d=new Dog();
}
}
class Animal{
public Animal(){
System.out.println("父类无参");
}
}
class Dog extends Animal{
public Dog(){
//super();
System.out.println("zileiwucna");
}
public Dog(int n){
//super();
System.out.println("子类有餐");
}
public void eat(){
System.out.println("eat");
}
}
4.3.3 拓展注意
总结:abstract注意事项
抽象方法要求子类继承后必须重写。
那么,abstract关键字不可以和哪些关键字一起使用呢?以下关键字,在抽象类中。用是可以用的,只是没有意义了。
1.private:被私有化后,子类无法重写,与abstract相违背。
2.static:静态优先于对象存在,存在加载顺序问题。
3.final:被final修饰后,无法重写,与abstract相违背。
4.4 接口
个人感觉接口就像是一个抽象类,很多性质也和抽象类差不多。
但不一样的是类不能多继承,接口可以多继承。
4.4.1接口的特点
1.通过interface关键字来定义接口
2.通过implements让子类来实现接口
3.接口中的方法全部都是抽象方法(JAVA8)
4.可以把接口理解成一个特殊的抽象类(但接口不是类!!!)
5.类描述的是一类事物的属性和方法,接口则是包含实现类要实现的方法
6.接口突破了java单继承的局限性
7.接口和类之间可以多实现,接口与接口之间可以多继承
8.接口是对外暴露的规则,是一套开发规范
9.接口提高了程序的功能拓展,降低了耦合性
10.接口中的变量都是静态常量。public static final
4.4.2 抽象类和接口的区别
抽象类是一个特殊的类,特殊在,抽象类中可以包含没有方法体的方法(抽象方法)
接口可以理解成一个特殊的抽象类,特殊在,接口里的都是抽象方法,没有普通方法
接口会为方法自动拼接public abstract,还会为变量自动拼接public final static
抽象类可以有成员变量成员常量 接口只能有静态常量
抽象类可以有构造方法–用来给子类创建对象,接口中没有构造方法
抽象类和接口都不能实例化(创建对象)
接口可继承接口,并可多继承接口,但类只能单继承
抽象方法只能声明,不能实现,接口是设计的结果 ,抽象类是重构的结果
5.内部类
5.1类的五大成员:
属性,方法,构造器,代码块,内部类。
5.2 内部类的特点
1) 内部类可以直接访问外部类中的成员,包括私有成员,方法和属性
2) 外部类要访问内部类的成员,必须要建立内部类的对象
5.3局部内部类
1.局部内部类通常定义在方法中或代码块中
2.作用域在方法体,或者代码块中
3.本质仍然是个类
4.局部内部类和外部类属性重名时,就近原则,访问外部类,类名。this。属性名
package oop;
public class Test {
public static void main(String[] args) {
new T().m1();
}
}
class T{
private int age=10;
public T() {
System.out.println("wucan");
}
public void m1(){
class t{
private int age=20;
public void m2(){ //1) 内部类可以直接访问外部类中的成员,包括私有成员,方法和属性
System.out.println(age);//就近 原则 输出20
System.out.println(T.this.age);//输出10
//T。this本质就是外部类的对象,谁调用了m2,T。this就是哪个对象
// m1();
}
}
new t().m2();
}
}
5.4 匿名内部类(重要)
5.4.1匿名内部类的调用
package innerClass;
/*匿名内部类*/
public class AnonymousInnerClass {
public static void main(String[] args) {
new Outer().method();//传统方法实现A接口
}
}
class Outer{
private int n1=10;
public void method(){
//基于接口的匿名内部类
//1.需求:使用A接口,传统方法,implements 然后实现,如下
//2.但是Tiger类为了实现A 只用了一次,一次就定义一个类太麻烦
// new Tiger().cry();
//3.用匿名内部类简化,注意:一次只能调用一个方法。
new A() {
@Override
public void cry() {
System.out.println("tiger cry");
}
@Override
public void eat() { }
}.cry();
//来查看一下匿名内部类的底层
/*底层实际是创建了一个类去实现接口
class Outer$2 implements A{}
* */
System.out.println(new A() {@Override public void cry() { }
@Override
public void eat() { }
}.getClass());
}
}
interface A{
void cry();
void eat();
}
//class Tiger implements A{
// @Override
// public void cry() {
// System.out.println("cry");
// }
//}
class Father{
public Father(String name){
}
public void test(){
}
}
5.4.2匿名内部类可以用来传递参数
package innerClass;
public class AnonymousInnerClassTest {
public static void main(String[] args) {
//用匿名内部类实现参数的传递
f(new IA() {
@Override
public void show() {
System.out.println("show");
}
});
}
public static void f (IA ia){
ia.show();
}
}
interface IA {
void show();
}
package innerClass;
public class AnonymousInnerClassPra {
public static void main(String[] args) {
new Cellphone().alarmClock(new Bell() {
@Override
public void ring() {
System.out.println("起床了");
}
});
}
}
interface Bell{
void ring();
}
class Cellphone{
public void alarmClock(Bell bell){
bell.ring();
}
}
5.5 成员内部类
调用方式: new Outer1().new inner1();其他的跟上面差不多