• Java 面向对象


     对象创建过程

    1. 首次创建对象时或者对象的静态方法或静态属性被首次访问,Java解释器查找类路径,定位ClassName.class文件
    2. 载入ClassName.class(创建一个对象),所有静态初始化动作执行(首次使用这些动作或属性时),并且所有静态初始化动态只在此时执行一次
    3. 当new ClassName()创建对象时,首先在堆为className对象分配足够的内存空间
    4. 相对应的内存空间清零,className对象的所有基本数据类型设置默认值,引用型设置为NULL,进行初始化
    5. 执行所有出现在字段定义处的初始化动作,例如bowl3被赋予指向Bowl3对象的引用
    6. 执行构造器

    对象

    • 非内部类不能使用private或者protected修饰符
    • 数组是不能指定长度的,只能获取引用
    int[] nums = new int[4];
    
    
    其中 int[] nums里的[]里面不能填入数字
    
    所谓的数组长度其实是一个误区,new int[4]开辟了一个 4*4的内存块,这里才是长度,但这是内存的长度
    
    nums所做的只是获取这个内存的引用,即获取这块内存的位置
    
    所以说数组是无法指定长度的
     所以下面这个数组扩充操作就很容易理解了
    
     通过copyOf()函数实现数组长度扩充 source=Arrays.copyOf(source,source.length+mount) 
    
    eg:
        int[] nums = new int[4];
         
        nums = Arrays.copyOf(nums,nums.length+3);
    
        这里其实是创建了两个数组内存,第一次是new int[4],然后nums获取了这块内存的地址
    
        然后copyOf()创建了新数组内存,长度为原数组长度+3,并获取原数组的地址
        
        然后将新内存的地址重新赋值给nums
    
    
    
    实例代码:
    
    public class Arrays {
        public static void main(String[] args) {
    
    	String[] strings = new String[] { "asd", "fhd", "asd", "fdk" };
    
    	for (int i = 0; i < strings.length; i++) {
    
    	    System.out.println(strings[i] + "的hash值:" + strings[i].hashCode());
    	}
    
    	strings = Arrays.copyOf(strings, strings.length + 1);
    	strings[4] = "1243";
    
    	System.out.println("--------------------------");
    
    	for (int i = 0; i < strings.length; i++) {
    	    System.out.println(strings[i] + "的hash值:" + strings[i].hashCode());
    	}
    
        }
    }
    
    
    结果:
    
    asd的hash值:96882
    fhd的hash值:101346
    asd的hash值:96882
    fdk的hash值:101229
    --------------------------
    asd的hash值:96882
    fhd的hash值:101346
    asd的hash值:96882
    fdk的hash值:101229
    1243的hash值:1509472
    
    
    
    结果分析:
    
    结果符合预期,而且发现原来的string数组元素的hash值和后面的是一样的
    更加说明了java所有变量都是对常量引用
    
    
    
    
    

    属性(类变量)

    • 可以直接在定义时赋值初始化
    class Test{
        public int i = 9;
    }
    
    • 可以通过调用其他函数进行初始化
    • 类变量系统会自动赋值,甚至先于构造函数赋值
    class Test{
    
        public int i;//系统自动赋值i=0;
        
        Test{
            i=8; //i从0重新赋值为8
        }
    
    }
    • 属性(类变量)一定先于方法调用之前赋值,无论变量在哪定义
    class Test{
    
        public int i;//系统自动赋值i=0;
        
        Test{
            i=8; //i从0重新赋值为8
        }
    
        int m = 9; //先于Test()赋值
    
    }
    • 静态成员变量在且仅在第一次使用的时候初始化,初始化顺序为先静态变量,后静态方法,存放在方法区
    • 成员变量和局部变量的变量名可以相同
    • 变量在同名时采取的是就近原则
    
    int i =3;
    
    void fun(){
    
        int i =6;//合法
        
    }
    
    
    
    
    
    
    
    
    int m =3;
    
    void f(int m){
    
        m = m; //m != 3,这里的两个m都是形参带来的m
        
    }

    构造方法

    • 构造方法是超类开始执行的

    示例代码:

    public class PowerOfExtrend {
    	public static void main(String[] args) {
    		son son = new son();
    		
    	}
    
    }
    class grandFather{
    	public grandFather() {
    		System.out.println("grandFather!");
    	}
    }
    
    class father extends grandFather{
    	public father() {
    		System.out.println("father!");
    	}
    	
    }
    
    class son extends father{
    	public son() {
    		System.out.println("son!");
    	}
    }
    
    
    
    结果:grandFather!
         father!
         son!
    
    结果分析:在子类的构造方法内部,系统会自动在最前面添加super();来调用父类的构造方法,所以构造方法的执行是从祖先类开始的,一直到当前类
    
    

    权限

    注意:为了清楚起见,应按public,protected,default,private来排列成员

    • 每个编译单元(文件)都只能有由一个public类,表示没有编译单元都由单一的公共接口(public class),如果出现超过一个,则编译器会报错
    • puiblic class 的名称必须完全和该编译单元的文件名相同,包括大小写
    • 虽然不常用,但一个编译单元是可以没有任何public类,这种情况下可以随意给编译单元命名

    初始化

    初始化的4中方法

    1. 在定义对象的初始化,这意味着变量将在构造器调用被初始化
    2. 在类的构造器中初始化
    3. 在使用对象之前,这种方式被称为惰性初始化,这种方式可以减小额外的负担,使用函数调用来初始化。
      *
      惰性初始化:当需要一个实例的时候才初始化一个对象。
      新建两个简单的类,第二个类中包含第一个类的一个引用,当
      需要第一个类的对象是调用Lazy()方法即可获得第一个类的对象。
      */
      class Object1{
          int i;
      }
      
      public class Object2{
       Object1 oj1 ;
       public void print(){
        if(oj1==null)
            oj1 = new Object();
       }
       public static void main(String[] args){
        Object2 object2 = new Object2();
        object2.print();
       }
      }
      
    4. 使用实例初始化

    继承

    Java中的继承与c++不同,java中的类的变量和方法继承后权限是不变的

    示例代码:

    public class PowerOfExtrend {
    	public static void main(String[] args) {
    		son son = new son();
    		son.power();
    	}
    
    }
    class grandFather{
    	protected int i =18;
    	protected void power(){
    		System.out.println("grandGather!");
    		System.out.println("i="+i);
    	}
    }
    
    class father extends grandFather{
    	
    	
    	@Override
    	protected void power() {
    		System.out.println("father!");
    		System.out.println("i="+i);
    	}
    }
    
    class son extends father{
    	@Override
    	protected void power() {
    		System.out.println("son");
    		System.out.println("i="+i);
    	}
    }
    
    
    结果:
         son
         i=18
    
    结果分析:
            子类father继承了父类grandFather的protected变量i和prote方法power(),
            但father的子类son还是可以访问protected变量i和prote方法power(),
            没有出现因为继承而权限缩小,而导致grandFather类的孙类son无法访问
            grandFather类相关方法和变量的问题
    
    

    方法

    • 静态方法是无法使用静态方法做参数的,会出现编译错误,但可以使用静态变量作为参数

    代码:

    public class Customer {
    	static int m =34;
    	
    	public static void main(String[] args) {		
    		f1();
    	//	f2();
    	}
    	
    	public static int f1() {
    		System.out.println(m);
    		return 1;
    	}
    
    	
            /* 会报错
            public static void f2(int f1()) {
    		System.out.println("1");
    	}
            */
    
    }
    
    
    结果:34
  • 相关阅读:
    推荐系统学习--cb+cf 初见
    耳机的阻抗和灵敏度问题
    java中常见的几种Runtimeexception
    java泛型
    ubuntu安装opencv
    ubuntu12.04静态ip设置问题
    Graph Theory
    SQL简单上手教程
    C++ 构造函数、拷贝构造函数和赋值运算符重载
    C语言函数调用栈
  • 原文地址:https://www.cnblogs.com/jeasion/p/10758344.html
Copyright © 2020-2023  润新知