Java面向对象 第1节 类和对象

一、Java 对象和类

  1. 面向对象语言三大特性:封装、继承、多态;
  2. 对象:描述客观事物的一个实体;
  3. 类:类是封装对象的属性和方法的载体,反过来说具有相同属性和行为的一类实体被称为类;类行为:方法;属性:成员变量
  4. 定义类:
    [访问修饰符] class 类名{   //class是声明类的关键字,类名首字母大写
      //代码
    }
  5. java中权限修饰符
    访问位置 private 默认 protected public
    同一个类
    同包或其子类 ×
    其他包的类或子类 × ×
    其他包的非子类 × × ×
  6. 定义属性:
      [访问修饰符]   数据类型 属性名;
  7. 定义成员方法:
    [权限修饰符] 返回值类型 方法名(参数类型 参数1名,....){
      //方法体
      return 返回值;    //若无返回值,此句可以不写(但仍可以用return ;退出该方法),并用void关键字声明返回值类型
    }
    注:访问修饰符可选;
      参数列表可选;

二、创建和使用对象

  • 声明:声明一个对象,包括对象名称和对象类型。
  • 实例化:使用关键字new来创建一个对象。
  • 初始化:使用new创建对象时,会调用构造方法初始化对象。
  • 类名  对象名 = new 类名();
             new是关键字     类名()为对象的构造方法      
    public class Puppy{ 
      int puppyAge;    //成员变量
      public Puppy(String name){ 
          // 这个构造器仅有一个参数:name 
            System.out.println("小狗的名字是 : " + name ); 
           } 
            public void setAge( int age ){ 
                puppyAge = age; 
            } 
            public int getAge( ){ 
              System.out.println("小狗的年龄为 : " + puppyAge ); 
              return puppyAge; 
            } 
            public static void main(String []args){   //程序执行的入口
                /* 创建对象 */ 
               Puppy myPuppy = new Puppy( "tommy" );
               /* 通过方法来设定age */ 
               myPuppy.setAge( 2 );
               /* 调用另一个方法获取age */ 
               myPuppy.getAge( ); 
               /*你也可以像下面这样访问成员变量 */ 
               System.out.println("变量值 : " + myPuppy.puppyAge ); 
            } 
    }       
    结果:
    小狗的名字是 : tommy
    小狗的年龄为 : 2
    变量值 : 2
  • 使用对象:对象.属性   对象.方法名
  • 对象数组:对象数组的数据类型就是具体的类名,对象数组存储的就是这个类的对象,每个元素就是一个对象。
  • 源文件声明规则:

    • 一个源文件中只能有一个public类
    • 一个源文件可以有多个非public类
    • 源文件的名称应该和public类的类名保持一致。例如:源文件中public类的类名是Employee,那么源文件应该命名为Employee.java。
    • 如果一个类定义在某个包中,那么package语句应该在源文件的首行。
    • 如果源文件包含import语句,那么应该放在package语句和类定义之间。如果没有package语句,那么import语句应该在源文件中最前面。
    • import语句和package语句对源文件中定义的所有类都有效。在同一源文件中,不能给不同的类不同的包声明。Java包

三、方法的重载(不同于重写即覆盖,后面会说到)

  方法重载即在同一个类中允许同时存在一个或多个同名方法,构成重载的条件:1.参数类型不同;2.参数顺序不同;3.参数个数不同

  注意:方法的返回值类型不能作为判断是否重载的依据;
     可以定义不定长参数方法:返回值  方法名(数据类型 ... 参数名称)      例如:void main(int[ ] a){....} 

package cn.galc.test;
public class TestOverLoad {
  void max(int a, int b) {
    System.out.println(a > b ? a : b);
  }
  /*int max(int a, int b) {    //不构成重载
    return a > b ? a : b; 
  }*/
  void max(float a, float b) {
    System.out.println(a > b ? a : b);
  }
}

四、this关键字

  根据面向对象的基本语法,每当调用变量或者函数的时候,都要按照类名.变量(函数)的格式来调用,意即每个变量或函数都必须属于某一个实际的对象而不是一个类(static的除外).

  1.Java中规定使用this关键字来表示“本类对象的引用”,this关键字被隐式地用于引用对象的成员变量和方法。

private  void setName(String name){
              this.name = name;
    成员变量name _|       |_ 形参name
}

  2.this引用的就是本类的一个对象,在局部变量或方法覆盖了成员变量时,就需要添加一个this关键字明确引用的是成员变量还是局部变量或方法。  

  3.this还可以作为方法的返回值:

public Book getBook(){
    return this;     //返回Book类引用      
}

  4. this在不会产生混淆的前提下是可以省略的,但一般都会加上:  

package  con.ytb.test;
public class  Pepole{
    String  name;    //成员变量
    void say(String  name){
        System.out.println("我的名字是:"+this.name);   //我的名字是:李明
        System.out.println("我的名字是:"+name);   //我的名字是:李四
    }
public static void main(String[] args){
Pepole p = new Pepole(); p.name = "李明"; p.say("李四"); }
}

五、构造方法

   是一个与类同名的方法,对象的创建就是通过构造方法完成的。

  • 构造方法无返回值(不用void修饰)
  • 默认构造犯法没有参数,因此参数列表可选
  • 构造方法名和类名相同
  • 没实例化一个对象时,类都会自动调用构造方法

  1.只能在类中没有定义任何构造方法时,编译器会自动创建一个不带参数的构造方法,但不执行任何代码;如果类中定义的构造方法都不是无参的构造方法(可以理解为无参的构造函数被覆盖),不会自动设置默认无参构造方法

  2.构造方法可以重载,同一个类中可以有多个重载的构造方法,以参数的个数,类型,顺序

  3.使用this调用重载的构造方法,只能在构造方法中使用,且必须是构造方法的第一条语句

  • 构造方法的作用
  1. 构造函数用来生成并初始化对象
  2. 构造函数可以通过函数的重写给对象赋初始值,简化代码  
package com.ytb;

public class Pepole {
        String  name;    //成员变量
        int age;
        String address;
        Pepole(){    //无参构造方法,可以省略不写
            System.out.println("这是无参构造方法");
        }
        Pepole(String name,int age){    //构造方法重载,有参构造方法
            this.name = name;
            this.age = age;
            System.out.println("这是有参构造方法");
        }
        Pepole(String name,int age,String addrss){    //构造方法重载,有参构造方法
            //this.name = name;
            //this.age = age;
            this(name,age);    //使用this调用其它构造方法,简化代码
            this.address = addrss;
            System.out.println("这是有参构造方法");
        }
        void say(){   //成员方法
            System.out.println("我的名字是:"+this.name+"
"+"年龄是:"+this.age+"
"+"地址是:"+this.address);
        }
        public static void main (String[] args){
            Pepole p = new Pepole();   //创建对象会调用默认构造方法
            p.name = "李明";
            p.age = 20;
            p.address = "北京";
            p.say();

            Pepole pp = new Pepole("李四",50);  //此处不会调用无参构造方法,会调用Pepole(String name,int age)
            pp.address = "西安";
            pp.say();

            Pepole ppp = new Pepole("唐三",18,"斗罗大陆");
            ppp.say();
        }
}
输出结果:

这是无参构造方法
我的名字是:李明
年龄是:20
地址是:北京
这是有参构造方法
我的名字是:李四
年龄是:50
地址是:西安
这是有参构造方法
这是有参构造方法
我的名字是:唐三
年龄是:18
地址是:斗罗大陆

  在后续类的继承中还会说到构造方法,未完待续。。。

六、静态常量、变量和方法

   由static修饰的变量、常量和方法,均属于静态成员,static成员前可以有访问权限限定修饰(private、public、protectd)

  • 静态成员变量属于类所有,区别于个别对象,也就是说,它不依赖类特定的实例,被类的所有实例共享。可以在本类或其他类中使用"类名.静态类成员"调用
  • 静态变量和静态方法的作用: 方便在没有创建对象的情况下来进行调用(方法/变量);为了提供共享数据或方法,比对象优先加载

  注意:1.静态方法中不可以使用this关键字,也不能使用super,因为实例成员与特定的对象关联;

     2.要在static方法中调用非静态的变量或者方法,可以先实现你所想要调用的非静态变量或方法所在的类的对象,然后通过个这对象的引用就可以访问非静态的方法和成员;

     2.在静态方法中不能直接调用非静态方法,不能直接访问所属类的实例变量和方法;

       3.java中规定不能将方法体中的局部变量声明为static;

          4.如果在执行类时,希望先执行类的初始化操作,可用static定义一个静态代码块,当java虚拟机(JVM)加载类时,就会执行该代码块;

package com.ytb;
public class StaticObject {
    private String str1 = "object";
    private  static String str2 = "static";
  static{ //静态代码块,只会在类加载的时候执行一次
    System.out.println("执行静态代码块");
  } StaticObject(){ //构造方法 } public void out(){ //普通方法 System.out.println(str1); System.out.println(str2); //str2是静态成员变量 print(); //非静态成员方法中是可以访问静态成员方法/变量的 } public static void print(){ //静态方法 //System.out.println(str1); //str1是非静态成员变量,无法访问 System.out.println(str2); //out(); //静态方法中不能访问非静态成员方法和非静态成员变量 } public static void main(String[] args){ //main()方法是static方法 StaticObject s = new StaticObject(); s.out(); //通过实例调用非静态方法 //s.print(); //不能调用 StaticObject.print(); //通过类名.方法名调用 } } 输出结果:
执行静态代码块 object static static static
  • static修饰的静态变量 和 没有被static修饰的实例变量

  1.对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态变量分配一次内存,在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(不推荐)

  2.对于实例变量,每创建一个实例,就会为实例变量分配一次内存,实例变量可以在内在中有多个拷贝,互不影响(灵活)

  3.一般在需要实现以下两个功能时使用静态变量:   在对象之间共享值时;方便访问变量时

七、final变量、final方法、final类

  1. final变量(常使用大写字母表示)
    1)final关键字用于声明变量,一旦设定,就不可以再改变变量的值;
    2)final变量必须在声明时对其进行赋值操作
    3)一旦一个对象引用被修饰为final后,它恒定指向一个对象,无法改变让其指向另一个对象,但是它指向的对象的内容是可变的
    4)一个既是final又是static的字段只占据一段不能被改变的存储空间,对于变量,表示一旦给值就不可修改,并且通过类名可以访问;对于方法,表示不可覆盖,并且可以通过类名直接访问
    5)  若方法的某个参数被final修饰了,则代表了该参数是不可改变的
    package com.ytb;
    import java.util.Random;
    public class FinalDta {
        static Random random = new Random();
        private final int VALUE_1 = 9;   //声明一个final常量
        private final int VALUE_2 = 10;
        private final Pepole pe = new Pepole();  //声明一个final的引用
        private Pepole pee = new Pepole();
        private final int[] a = {1,2,3};
        private int BLANK_VALUE;  //声明时没有赋值称为空白final变量
        public FinalDta(){
            BLANK_VALUE = 14;   //构造方法赋值
        }
        int doIt(final int x){   //设置final参数,不可改变x的值
            //x = x+1;     //i报错,x值不能改变
            return x;
        }
        void doSomething(){
            final int i = 7;   //局部变量声明为final,不可以改变i的值
            //System.out.println("i的值:"+i++);    //i++报错,i值不能改变
        }
        public static  void main(String[] args){
            FinalDta fin = new FinalDta();
            //fin.pe = new Pepole(); //不能指向其他引用
            //fin.VALUE_1 = 100;  //不能改变其值
        }
    }

  2. final 方法

  • final方法不能被重写
public class B extends A {
    public static void main(String[] args) {

    }
    public void getName() {    
    }
}
class A {
    /**
     * 因为private修饰,子类中不能继承到此方法,因此,子类中的getName方法是重新定义的、属于子类本身的方法,编译正常
     */
    private final void getName() {       
    }
    /* 因为pblic修饰,子类可以继承到此方法,导致重写了父类的final方法,编译出错
    public final void getName() {   
    }*/
}
/****************在编译期间能确切知道final变量值的情况下,编译器才会进行这样的优化***********************/
public class Test {
    public static void main(String[] args)  {
        String a = "hello2"; 
        final String b = "hello";
        String d = "hello";
        String c = b + 2; 
        String e = d + 2;
        System.out.println((a == c));   //true final变量是基本数据类型以及String类型时,如果在编译期间能知道它的确切值,则编译器会把它当做编译期常量使用。也就是说在用到该final变量的地方,相当于直接访问的这个常量,在使用到b的地方会直接将变量b替换为它的值
        System.out.println((a == e));   //false 变量d的访问需要在运行时通过存储地址来进行
    }
}
/****************************************************************/
public class Test { 
    public static void main(String[] args) { 
        String a = "hello2"; 
        final String b = getHello(); 
        //变量b在这里是使用getHello()方法对其进行初始化,它要在运行期才能知道其值 String c = b + 2;     
        System.out.println((a == c)); //false 
    } 
    public static String getHello() { 
         return "hello"; 
    } 
}    
  • private 方法,子类无法访问,不能被覆盖(方法重写);类的private方法会隐式地被指定为final方法。
  • private final 方法:可以被子类覆盖条件: 一个对象向上转型为它的基本类型并调用相同方法   
package com.ytb;
public class Test {
    public final double i = Math.random();
    public static double j = Math.random();

    public static void main(String[] args)  {
        Test myClass1 = new Test();
        Test myClass2 = new Test();
        //myClass1.i = 10;    报错,不能改变i的值
        System.out.println(myClass1.i);
        System.out.println(myClass1.j);
        System.out.println(myClass2.i);
        //myClass2.j = 14;    j的值可以改变
        System.out.println(myClass2.j);
    }
}  
  • final类:定义为final的类不能被继承,不允许其他人对这个类进行任何改动:final  class  类名{    }
原文地址:https://www.cnblogs.com/yutianbao/p/10480806.html