概述:面向对象(Object-Oriented,简称OO)是一种对现实世界理解和抽象的方法的计算机编程技术。面向对象的三大特征:
封装(Encapsulation)
继承(Inheritance)
多态(Polymorphism)
一、访问修饰符,类,关键字和构造方法:
1)private:类访问权限:本类内部可以访问,不能继承到子类;
2)default:什么都不写,包访问权限:本类内部可以访问,同包其他类也可以访问,同包可继承;
3)protected:子类访问权限:本类内部可以访问,不同包的子类也可以访问,同包其他类也可以访问,能继承到子类;
4)public:公共访问权限:任何地方都可以访问,能继承到子类;
5)类(class):是Java 语言的最小编程单位,也是设计和实现Java 程序的基础。类是一组事物共有特征和功能的描述。类的概念是抽象的,类似于建筑设计中的图纸,是对于现实需要代表的具体内容的抽象。类只包含框架结构,而不包含具体的数据。所以类代表的是总体,而不代表某个特定的个体。
类的对象包含:属性和方法。
6)static 关键字:一般都用static静态方法,可以不用初始化,就能够直接调用。
Static常用语静态代码块编写,特点,随着类的加载而执行,只执行一次,优先于主函数。
注意:
1、静态方法只能访问静态成员;
2、而非静态成员可以访问静态成员;
3、静态方法中不可以使用this,super关键字;
7)this 关键字:this 表示当前对象。帮助理解:当在一个类中要明确指出使用对象自己的变量或函数时就应该加上 this 引用。
8)void 关键字:用来声明无返回值的函数。
9)final 关键字:最后的,最终的。
1、final类,final类不能被继承,因此final类的成员方法没有机会被覆盖,默认都是final的。在设计类时候,如果这个类不需要有子类,类的实现细节不允许改变,并且确信这个类不会再被扩展,那么就设计为final类。 final方法不能被子类的方法覆盖,但可以被继承。
2、final方法,如果一个类不允许其子类覆盖某个方法,则可以把这个方法声明为final方法。
使用final方法的原因有二:
第一、把方法锁定,防止任何继承类修改它的意义和实现。
第二、高效。编译器在遇到调用final方法时候会转入内嵌机制,大大提高执行效率。
3、final变量(常量),用final修饰的成员变量表示常量,只能被赋值一次,赋值后值无法改变!
final修饰的变量有三种:静态变量、实例变量和局部变量,分别表示三种类型的常量。
10)super 关键字:常用于子父类方法中的子类,当子类继承父类的时候,要调用父类的方法,成员变量时,就要用到 super,用法:super.方法名。注意,当父类中的成员被私有化时,子类无法访问到父类的私有化变量,方法。只能通过父类提供的公共的构造方法访问。
11)构造方法:是用来构造类的实例,因为每一个类都有一个默认的无参数的构造方法,这个构造方法是用于给对象初始化,new一次,用一次。如果构造方法被私有化,则这个构造方法不能被初始化。
私有化:是封装的一种表现形式。是为了控制传入的数据,和操作,提高代码健壮性。
构造方法:一开始就运行,给对象初始化。
一般方法:可以被改对象多次使用。
Person p = new Person("zhangsan",20);
这句话做了什么事情?
1、因为new用到了Person.class,所以会找到Person.class文件,并加载到内存中。
2、执行该类中的static静态代码块,如果有的话,给Person.class,类进行初始化。
3、在堆内存中开辟内存空间,并确定分配内存地址。
4、在堆内存中建立对象的特有属性,并进行默认初始化。
5、对属性进行显示初始化。
6、对对象进行构造代码块初始化。
7、对对象进行对应的构造方法初始化。
将对象地址付给栈内存中的p变量。
二、面向对象的封装:
是指隐藏对象的属性和实现细节,仅对外提供公共访方式。
1)封装的好处:
1、将变化隔离;
2、便于使用;
3、提高重用性;
4、提高安全性。
2)封装的原则:
1、将不需要对外提供的内容都隐藏起来。
2、把属性都隐藏起来,提供公共访问方法对其访问。
3)私有化也是封装的一种表现形式。
4)demo:对私有属性提供对外的公共的get 和set 方法。
public class Person {
private String name;//私有化,是为了控制传入的数据,和操作,提高健壮性。
private int age;
<span style="white-space:pre"> </span>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;
}
}
三、面向对象的继承:
新的实例要在原有类上的扩展,就是继承原有类的功能外还可以扩展需要的功能。
继承的好处:
1、提高代码的复用性。
2、让类与类之间产生了关系。有了这个关系才有了多态性。
3、java 支持多实现。
1)继承的原则:
java 语言中,java 只支持单继承,不支持多继承。因为多继承容易带来安全隐患,当多个父类中定义了相同方法时,当功能不同,不确定要运行A还是B,但是java保留了这种机制,java用另一种体现机制来完成表示。叫多实现。
2)继承的扩展:子父类关系
子父类中的函数。当子类中出现和父类一模一样的函数时候,当子类对象调用该函数,会运行子类函数的内容。如同父类的函数被覆盖一样。这种情况也是函数的另一个特性:重写(覆盖)。
父类,一般称为基类。子父类出现后,出现新特性:
重载:只看同名参数列表。
重写:子父类方法要一模一样。
子类重写父类中的方法,但是不继承父类方法中的内容,只执行自己重写方法中的内容子类中用super关键字来调用父类中的变量,方法。
4)继承的子父类 Demo:
package study.base.day006;
public class Fu{
int num = 4;
void father(){
System.out.println("I'm a father");
}
void speak(){
System.out.println("speak");
}
Fu(){
System.out.println("fu lei de gzhs");
}
}
子类继承父类:
package study.base.day006;
public class Zi extends Fu{
int num = 5;
Zi(){
//super(); 默认执行了super
System.out.println("zi lei de gzhs");
}
void show(){
//父类中的num不能私有化
System.out.println(super.num);
//子类中用super关键字来调用父类中的变量,方法
int i = super.num;
super.father();
}
//子类重写父类中的方法,但是不继承父类方法中的内容,只执行自己重写方法中的内容
void speak(){
//递归方法,调用父类中的show()方法,执行父类show()方法
//this.speak();
super.speak();
System.out.println("aaaa");
}
}
四、抽象类与抽象方法
1) 概念:在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
2) 抽象类:当一个类被声明为abstract时,这个类被称为抽象类。所谓的抽象类就是没有实例对象的类。
3) 抽象方法:作为修饰符,abstract声明了一种没有具体对象的,出于组织概念的层次关系需要而存在的抽象类;作为类方法修饰符,abstract则声明了一种仅有方法头,而没有具体的方法体和操作实现的抽象方法。
4) 个人理解:当父类中的一个方法,无法确定其具体的实现形式,那么就要用到抽象方法。而这些不去实现抽象方法的类就是抽象类。
代码演示:
public abstract class Animal {
abstract void eat();
<span style="white-space:pre"> </span>//提高了代码的复用性
public static void func(Animal a){
a.eat();
}
}
五、接口
1) 概念:Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
2) 初期理解:可以理解为一个特殊的抽象类,当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表现。
3)定义接义时的格式特点:
1、接口中常见定义:常量,抽象方法。
2、接口中的成员都有固定的修饰符。
常量:public static final
方法:public abstract
4) 深入理解:接口是不可以创建对象的,因为有抽象方法。需要被子类实现,而子类对接口中的抽象方法全部覆盖后,子类才可以实例化,否则子类是一个抽象类。接口可以被类多实现,也是对多继承不支持的转换形式。Java 支持多实现。
demo:
public interface InterFace {
public static final double PI = 3.14;
public abstract void show();
}
public class InferFaceTest implements InterFace,InterFaceA{
@Override
public void show() {
System.out.println("show");
}
@Override
public void show2() {
}
}
六、面向对象的多态:
指同一个实体同时具有多种形式。就好比养宠物,你家养了猫,别人家养了狗,但是猫和狗都称作为宠物,或者动物。
继承是多态产生的前提条件。
多态的特点:
1、提高了代码的复用性。
2、多态至始至终都是子类对象在做变化。
<pre name="code" class="html">public class PolymorphismDemo {
public static void main(String[] args) {
//类型提升。 向上转型
Animal a = new Cat();
a.eat();
//func(new Cat());
func(new Dog());
//强制将父类的引用,转成子类类型。 向下转型。
//多态至始至终都是子类对象在做变化。
Cat c = (Cat)a;
c.catchMouse();
}
public static void func(Animal a){ //提高了代码的复用性
a.eat();
// a 指向 Cat 类
if(a instanceof Cat){ //判断 a 是谁的实例。如果是,就执行。
Cat c = (Cat)a;
c.catchMouse();
}else if(a instanceof Dog){
Dog d = (Dog)a;
d.watchHome();
}
}
}
多态的练习:
/**
* 需求:
* 电脑运行实例
* 电脑运行基于主板
*/
package study.base.day007;
public class PolymorphismDemo2 {
public static void main(String[] args) {
MainBoard mb = new MainBoard();
mb.run();
mb.usePCI(new NetCard());
}
}
interface PCI{
public void open();
public void close();
}
class MainBoard{
public void run(){
System.out.println("main board run");
}
public void usePCI(PCI pci){
if(pci!=null){
pci.open();
pci.close();
}
}
}
class NetCard implements PCI{
public void open(){
System.out.println("netcard open");
}
public void close(){
System.out.println("netcard close");
}
}
七、单例设计模式(Singleton):
解决一个类在内存中只存在一个对象。想要保证对象的唯一。
1、为了避免其它程序过多的建立对象,先禁止其他程序建立该类对象。
2、还为了让其他程序可以访问到该类对象,只好在本类中,自定义一个对象。
3、为了方便其它程序对自定义对象的访问,可以对外提供一些访问方式。
这三步的具体实现:
1、将构造方法私有化。
private void String getName(String name){
this.name = name;
}
2、在类中创建一个本类对象。
Person p = new Person();
3、提供一个方法,可以获取该对象:p
单例模式-->
饿汉式与懒汉式
饿汉式:类一进内存,就创建好对象。
private static Single2 s2 = new Single2(); //直接 初始化
private Single2();
public static Single2 getInstance(){return s;}
懒汉式:对象方法被调用时,才初始化,也叫做对象的延时加载。
Single 类进内存,对象还没有存在,只是调用了getInstance方法时,才建立对象。
synchronized给代码块或者方法加锁,保证只有同一时刻只有一个线程执行,但是会降低系统的效率。
private static Single2 s2 = null;
private static Single2 getInstance(){
if(s2==null){
//如果多人同时访问,但是cpu没有办法同时处理多个程序,所以就报错了。
synchronized(Single2.class){
if(s2==null){
s2 = new Single2(); //重新 初始化 了一个Single2对象
}
}
}
return s2;
}
八、内部类和匿名内部类
内部类的访问规则:
1)内部类可以直接访问外部类中的成员,包括私有。
之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,
格式为:外部类类名.this.xx
2)外部类要访问内部类,必须建立内部类对象。
访问格式:
1、当内部类定义在外部类的成员位置上,而且非私有,可以在外部其它类中,
可以直接建立内部类对象,
格式:
外部类名.内部类名 变量名 = 外部类对象.内部类对象。
OuterClass.InnerClass ic = new OuterClass().new InnerClass();
3)当内部类在成员位置上,就可以被成员修饰符修饰。
比如,private:将内部类在外部类中进行封装。
static:内部类可以被静态修饰,就具备了静态的特性。
但是当被static修饰符修饰了后,只能直接访问外部类中的static成员。
出现了访问局限。
注意:当内部类中定义了静态成员,该内部类必须是 static 的。
当外部类中的静态方法访问内部类时,内部类也必须是 static 的。
当描述事物时,事物的内部还有事物,该事物用内部类来描述。
因为内部事务在使用外部事物的内容。
4)匿名内部类:
1、匿名内部类其实就是内部类的简写格式。
2、定义匿名内部类的前提。内部类必须继承一个类或者实现一个接口。
package study.base.day007;
public class OuterClass {
private static final int x = 4;
public static void main(String[] args) {
}
class InnerClass{
void show(){
//System.out.println("inner:"+OuterClass.this.x);//同下
System.out.println("inner:"+x);
}
}
void viewInner(){
InnerClass ic = new InnerClass();
ic.show();
}
}
class InnerClassDemo2{
public static void main(String[] args) {
OuterClass.InnerClass ic = new OuterClass().new InnerClass();
ic.show();
}
}
九、枚举
枚举的描述:
1) 枚举就相当于一个类,其中也可以定义构造方法、成员变量、普通方法和抽象方法。
子类完成父类的抽象方法。子类的构造方法就是调用父类的无参数构造方法,也可
以指定传入参数的构造方法。枚举通常用于内部类的使用。
2) 枚举元素必须位于枚举体中的最开始部分,枚举元素列表的后要有分号与其他成员分隔。
把枚举中的成员方法或变量等放在枚举元素的前面,编译器报告错误。所以枚举的构造
方法一定要放在变量后面。
3) 带构造方法的枚举
构造方法必须定义成私有的。
如果有多个构造方法,该如何选择哪个构造方法?
枚举元素如MON和MON()的效果一样,因为都是调用默认的构造方法。
4) 带方法的枚举
定义枚举TrafficLamp;
实现普通的next方法;
实现抽象的next方法:每个元素分别是由枚举类的子类来生成的实例对象,
这些子类采用类似内部类的方式进行定义;
增加上表示时间的构造方法.
5) 枚举只有一个成员时,就可以作为一种单例的实现方式。
6) Demo
package study.part3.day018.enumstudy;
public abstract class WeekDay {
//私有化构造函数
private WeekDay(){}
public final static WeekDay SUN = new WeekDay(){
@Override
public WeekDay nextDay() {
return MON;
}
};
public final static WeekDay MON = new WeekDay(){
@Override
public WeekDay nextDay() {
return SUN;
}
};
//定义一个抽象方法,nextDay
public abstract WeekDay nextDay();
}
package study.part3.day018.enumstudy;
public class EnumTest{
public static void main(String[] args) {
System.out.println(WeekDay.SUN);
}
public enum WeekDay{
SUN,MUN,THU,WEN,THR,FIA,SAT;
WeekDay(){
}
}
public enum TrafficLamp{
//添加了构造方法后,这里就得加上一个小括号,把 int 类型的time参数传进去
//这样就表示了它是调用了具体的哪一个构造方法,它是谁的子类
RED(30) {
@Override
public TrafficLamp nextLamp() {
return GREEN;
}
},GREEN(13) {
@Override
public TrafficLamp nextLamp() {
return YELLOW;
}
},YELLOW(20) {
@Override
public TrafficLamp nextLamp() {
return RED;
}
};
//定义一个抽象的下一次显示的灯
public abstract TrafficLamp nextLamp();
private int time;
//构造方法
TrafficLamp(int tim){
this.time = tim;
}
}
}
十、基本数据类型对象包装类:
* 基本数据类型对象包装类
* 基本数据类型 引用数据类型
* byte Byte
* short Short
* int Integer
* long Long
* boolean Boolean
* float Float
* double Double
* char Character
* 基本数据类型对象包装类的最常见作用。
* 就是用于基本数据类型和字符串类型之间做转换
* 基本数据类型转成字符串。
* 1--基本数据类型+""
* 2--基本数据类型.toString(基本数据类型值);
* 如:Integer.toString(34);//将整数34转成字符串"34"
* 字符串转成基本数据类型。
* 基本数据类型
* xxx a = Xxx.parseXxx(String);
* int a = Integer.parseInt(str);
* double b = Double.parseDouble("12.33");
* boolean b = Boolean.parseBoolean("true");
* Integer i = new Integer("2123");
* int num = i.intValue();
* 十进制转成其它进制:
* toBinaryString()
* toHexString()
* toOctalStirng();
* 其它进制转十进制:
* parseInt()
package study.base.day010.ThreadTX;
public class BaseDateObject {
public static void main(String[] args) {
//整数类型的最大值
sc("int max:"+Integer.MAX_VALUE);
sc("int min:"+Integer.MIN_VALUE);
int num = Integer.parseInt("123215");
System.out.println(num);
long l = Long.parseLong("34");
System.out.println(Integer.toBinaryString(6));
System.out.println(Integer.toHexString(67));
/**
* 其它进制转十进制
*/
int i = Integer.parseInt("3c",16);
System.out.println("3c转成十进制是:"+i);
}
public static void sc(String str){
System.out.println(str);
}
}
十一、递归与迭代:
/**
* 递归与迭代
*/
package study.base.day006;
public class DiGui {
public static void main(String[] args) {
int i = fib(5);
System.out.println(1);
}
static int fib(int n)
{
if(0 == n)
return 0;
if(1 == n)
return 1;
if(n > 1)
return fib(n-1)+fib(n-2);
else
return n;
}
//递归Demo
int funcA(int n)
{
if(n > 1)
return n+funcA(n-1);
else
return 1;
}
//迭代Demo
int funcB(int n)
{
int i,s=0;
for(i=1;i<n;i++)
s+=i;
return s;
}
}