java成长笔记-SecondDay-am

  • 面向对象之——类和对象

类是所有对象的模板,共同特性的集中体现(包括属性和方法)。三大特性封装,继承,多态都和类的结构和类之间的关系直接相关。

类中有成员属性 ,成员方法(构造方法,抽象方法,一般方法)。成员属性在定义的时候可以不直接初始化,但是在使用的时候一定给成员属性赋值。

使用类中的调用类中的属性和方法的前提是必须实例化对象,否则就会造成空指向异常的发生。

  • 类和对象非常关键的一步

关键词new完成的事:new一个对象的时候,会开辟一块堆内存保存数据,然后栈内存中保存对象的地址指向堆内存。调用本类中的构造方法(完成属性的初始化),之后这个对象才可以调用属性和方法、

  • 对象的引用传递

不同的对象指向一块堆内存空间,若原来的对象指向了一块堆内存,但是后来又被其他对象传递过来了引用,那么它原来的指向就会被清除。两个对象指向了一块堆内存空间,任何一个对象更改属性,调用方法都是有效的。

  • 封装

封装是为了保证开发的私密性,结构严谨性,逻辑的合理性。

  • 构造方法

构造方法存在重载,构造方法只在实例化对象的时候调用一次,定义的时候没有返回值的声明,方法的名字和类的名字一样。

  • 匿名对象

匿名对象的概念是没有实例化的对象指向的一块堆内存保存的属性和方法的堆没存空间。

主要用来作为方法的参数,传递对象的引用的空间。

  • 数组

​​​​​​​数组的概念:就是相同数据的集合,访问和修改是使用数组名字和下标完成的。数组的非常重要的属性:xxx.length,取得数组的长度的属性值。

  • 数组的初始化

​​​​​​​数组的动态的初始化。

int arr[] = new int[3] ;

arr[0] = 12 ;

arr[1] = 13 ;

arr[2] = 14 ;

数组的静态初始化。

int arr[] = {12,13,14} ;

  • 二维数组

​​​​​​​数组中的每一个元素都是一个一维的数组,这样的数组是一个二维的数组。

二维数组的初始化:1)动态的初始化  2)静态的初始化

1)

int arr[][] = new int[行数][列数] ;

2)

int arr[][] = {{x,y,z},{a,b,c},{e,f,g}....}

因为数组也是一个引用的数据类型,所以数组数组也是存在引用的传递操作的。

数组的遍历的操作。


public class ArrayPrint{

    public static void main(String[] args){
        //一维
        
        int arr[] = new int[]{1,2,3,4,5,6};
        //二维
        int arrs[][] =new int[][]{{1,2,3},{4,5,6},{7,8,9}};
        printArray(arr);
        printArrays(arrs);
        
    }
    public static void printArray(int arr[]){
        
        for(int x = 0;x<arr.length;x++){

            System.out.println(arr[x]);
        }
    }
    public static void printArrays(int arrs[][]){
        
        for(int x = 0;x<arrs.length;x++){
        
            for(int y = 0;y<arrs[x].length;y++){
                System.out.print(arrs[x][y]+" ")
            }
            System.out.println();
         }
    }
}

1
2
3
4
5
6
1 2 3 
4 5 6 
7 8 9 

上面就是两个数组的遍历输出就是数组的引用的传递。不同的数组的对象指向了同一个数组堆内存数据。

  • 数组的排序的操作

外循环控制的是循环的总次数,内循环控制的是每次排序的控制。



public class SortArray{

    public static void main(String[] args){
           
        int arr[] = new int[]{2,1,9,3,5,4,7,6,8};
        System.out.println("排序之前的数组中数据的顺序");
        printArray(arr);

        //排序之后
        SortArray(arr);
        printArray(arr);
        
        

    }
    public static void printArray(int temp[]){
        for(int x =0;x<temp.length;x++){
            System.out.print(temp[x]+" ");
        }
    }
    public static void SortArray(int arrs[]){
        for(int x = 0;x<arrs.length;x++){
            for(int y = 0;y<arrs.length-1;y++){
                if(arrs[y] >arrs[y+1]){
                    int t = arrs[y];
                    arrs[y] = arrs[y+1];
                    arrs[y+1] = t ;

                }
            }
        }
    }
}
  • 数组的一个弊端

​​​​​​​数组的长度是固定的,不能更改。

  • 特殊用法

​​​​​​​数组的转置的操作:

public class ArrayDemo{
    public static void main(String[] args){
        
        int data[][] = new int[][]{{1,2,3},{4,5,6},{7,8,9}};
        reverse(data);
        print(data);
        
        
    }
    public static void reverse(int arr[][]){

        for(int x = 0;x<arr.length;x++){
            for(int y = x;y<arr[x].length;y++){
                if(x != y){
                    int temp = arr[x][y] ;
                    arr[x][y] = arr[y][x] ;
                    arr[y][x] = temp ;
                }
            }
        }
    public static void print(int temp[][]){

        for(int x= 0;x<temp.length;x++){
            for(int y = 0;y<temp[x].length;y++){
                System.out.print(temp[x][y]+"、");
                    }
                System.out.println();
                }
             
          }
                System.out.println();
    }

}

1、4、7、
2、5、8、
3、6、9、
  • 方法返回数组,  (这个做法的意思是把 数组 当做一种数据类型。)

​​​​​​​//要求是:实例化对象由一个方法完成

//然后对返回得到的数组进行遍历的操作

public class ArrayDemo{

    public static void main(String[] args){
        int[] arr = init() ;
        print(arr);
        
    }
    public static int[] init(){
    
        return new int[]{1,2,3};    
    }
    public static void print(int[] arrs){

        for(int x = 0 ;x<arrs.length;x++){
           System.out.println(arrs[x]+" ");
        }
    }
    

}


1 
2 
3 

  • 数组的操作方法

​​​​​​​数组的操作java提供了一些核心的类库:1,数组的复制。2:数组的排序。

1:System.arraycopy()方法

public class Array{

    public static void main(String[] args){
        int arr1[] = new int[]{1,2,3,4,5,6,7} ;
        int arr2[] = new int[]{11,22,33,44,55,66,77} ;
        
        arrayCopy(arr1,arr2);
        print(arr2) ;
        
      

    }
    public static void arrayCopy(int[] temp1,int[]temp2){

        System.arraycopy(temp1,2,temp2,2,3); 


    }
     public static void print(int temp[]){

        for(int x = 0 ;x<temp.length;x++){
                  System.out.print(temp[x]+" ");
            }
       }

}

11 22 3 4 5 66 77 

//上面的输出的结果是就是复制的原理:把被复制的数组的位置上的数据清除掉以后,然后使用复制元素的方法,将想要复制的元素复制到想要复制的数组中去。

2:数组的排序的方法

java.util.Arrays.sort(数组的名字);

对于数组的排序我们可以使用这个系统提供的方法,还可以自己定义的方法实现数组的排序的操作。当我们使用在面试的过程中,应该使用最基本的方法实现,然后最后一句说明一下可以利用系统提供的方法一步实现。

public class Array{

    public static void main(String[] args){
    
    int arr[] = new int[] {10,8,9,2,3,1};
    sort(arr);
    print(arr);
    
    }
    public static void sort(int temp[]) {
    	java.util.Arrays.sort(temp);
    }
    public static void print(int arr[]) {
    	for(int x = 0 ;x<arr.length;x++) {
    		
    		System.out.print(arr[x]+" ");
    	}
    	
    	
    }

}

1 2 3 8 9 10 

但是对于数组的排序的方法只能是对于 int[],double[],float[]的数组的类型。

  • 对象数组

​​​​​​​数组是一个引用的数据类型,而类也是一种引用的数据类型,对象数据就成为了一个引用数据里面包含着引用数据类型的数据结构。

  • 对象数据的动态初始化,静态初始化
package it.com.cast06;

public class Book {
	private String title ;
	private double price ;
	public Book() {}
	public Book(String title,double price) {
		this.title = title ;
		this.price = price ;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public double getPrice() {
		return price;
	}
	public void setPrice(double price) {
		this.price = price;
	}
	public void printAll() {
		System.out.println("名字:"+this.title+"价格:"+this.price);
		
	}

}
package it.com.cast06;

public class Array{
	public static void main(String[] args) {
		//动态的初始化
		Book bks[] = new Book[2] ;
		bks[0] = new Book("java开发",100.0);
		bks[1] = new Book("javaee",102.5);
		//静态初始化
		Book bkss[] = new Book[] {new Book("javaSE",125.5),new Book("javaweb",145.5)};
		
		testArrayObject(bks);
		System.out.println("=======================");
		testArrayObject(bkss);
		
		
		
	}
	public static void testArrayObject(Book temp[]) {
		for(int x =0;x<temp.length;x++) {
			
			temp[x].printAll();
		}
	
	}
 
}

名字:java开发价格:100.0
名字:javaee价格:102.5
=======================
名字:javaSE价格:125.5
名字:javaweb价格:145.5
  • String类

​​​​​​​String类既然是一种类,那么它是一种引用的数据类型,实例化方式有两种:关键字new 的方法,还有就是直接赋值的方式。

关键new的方式是非常好理解的,因为只要是类,就必须可以是通过关键字new完成的,对于直接赋值的方式的理解,我们应该记忆。

new一旦使用就会开辟新的地址空间,用栈内存 的地址来指向这个堆内存的空间形式,所以要想比较两个String类的对象是否是相同的,就必须使用 ==判断,“==”比较的是地址。而要想比较内容是否相同要使用的函数是:public boolean equal(Object){}该方法是String类中定义的一个方法。

  • String的实例化方式1:关键字new,==比较的是内存的地址是否相同。
public class StringClass {
	public static void main(String[] args) {
		String str = "hello" ;
		String stra = new String("hello");
		String strb = new String("hello");
		String strc = strb ;
		
		System.out.println(str == stra);
		System.out.println(stra ==strb);
		System.out.println(strc == strb);
        
        System.out.println(str.equals( stra));
		System.out.println(stra.equals(strb));
		System.out.println(strc.equals(strb));
		
		
	}
}

false
false
true
true
true
true

每一个字符串的匿名对象,会首先在堆内存中开辟一块空间保存字符串,然后呢使用关键字new的时候,会另外开辟一个新的堆内存的空间,而之前定义字符串常量的堆内存的空间将不会有任何的指向,成为了垃圾,使用构造方法开辟的字符串对象实际上会开辟两个堆内存的空间,其中一块将会成为垃圾。

除了造成了内存空间的浪费之外,如果使用构造方法实例化对象,由于关键字new永远代表开辟新的堆内存的空间,所以其内容将不会保存在 对象池中。

如果想要将new实例化的对象入池操作的话,需要使用手工入池的方式完成,这个当出现新的直接定义的方式的String对象的时候,就会将这个堆内存的引用传递给新的栈内存的指向。

 

  • String的实例化方式2:直接赋值的方式

​​​​​​​//下面举证说明直接赋值实例化的方式的String 对象是一个匿名的对象


public class StringClass {
	public static void main(String[] args) {
		String str = "hello" ;
		System.out.println(str.equals("hello"));
	}

}

//因为直接赋值的字符串变量str可以调用equal()方法,说明str是String类的一个对象,但是这种方式没有通过new来实例化,所以直接赋值String类对象的方法就是一种匿名对象形式。
//在实际的字符串中,我们可能会需要用户输入数据,特别是字符串的类型,这个时候我们需要字符换进行比较
//例如很多密码的输入的操作的时候,我们需要的就是对用用户输入的字符串进行判断和比较。
//除了要判断字符串的输入是否正确以外,我们还要防止用户输入了空的字符串。
//但是我们还要保证即使字符串的输入时空的,我们也不能报错。

import java.util.Scanner;

public class ScannerString {
	public static void main(String[] args) {
	
		
		boolean result = isCorrect(null);
		System.out.println(result);
	}
	public static boolean isCorrect(String strs) {
		boolean flag = false;
		if(strs.equals("admin")) {
			flag = true ;
		}
		
		return flag ;
	}

}

Exception in thread "main" java.lang.NullPointerException
	at ScannerString.isCorrect(ScannerString.java:14)
	at ScannerString.main(ScannerString.java:9)

//标准的做法是 "admin".equal(strs),这样就能够避免空指向的异常出现

//下面是改正之后的更严谨的做法

import java.util.Scanner;

public class ScannerString {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in) ;
		System.out.println("请你输入你的字符串");
		String str = sc.nextLine() ;
		
		boolean result = isCorrect(str);
		System.out.println(result);
	}
	public static boolean isCorrect(String strs) {
		boolean flag = false;
		if("admin".equals(strs)) {
			flag = true ;
		}
		
		return flag ;
	}

}

请你输入你的字符串
ad
false



String类的匿名对象是由系统自动生成的,不再由用户自己创建,匿名对象系统创建的时候,只会生成一个堆内存的空间,并且这个空间可以被重用。

采用再接赋值的方式定义的String类的对象,当出现内容相同的时候吗,不会开辟新的堆内存的空间,而会直接指向现有的堆内存。

public class StringIstance{

    public static void main(String[] args){
        String stra = "hello" ;
        String strb = "hello" ;
        String strc = "hello" ;
        String strd = "ytook" ;

        System.out.println(stra ==strb);
        System.out.println(stra == strc) ;
        System.out.println(stra == strd) ;
    }
}

true
true
false

JVM底层会存在一个对象池,(不一定是保存String的对象),当代码中出现了使用直接赋值的方式定义一个String类对象的时候。会将此字符串使用的匿名对象入池保存,如果后续还有其他的String类对象也采用了直接赋值的方式,并且设置了同样的内存的时候。将不会开辟新的堆内存的空间,而是使用已有的对象进行进行引用的分配,从而继续使用。

  • 面试题:String类对象的两种实例化的方式的区别

​​​​​​​直接赋值的方式实例化的对象,只会开辟一块堆内存的空间,并且会将字符串对象自动入池的操作。

而new构造方法的实例化的方式,会先开辟两块堆内存的空间,其中匿名对象方式的会成为垃圾,并且不会自动入池,需要手工入池的方式完成将来的数据的共享。

在所有的开发中,涉及到字符串的时候,都是使用直接赋值的方式完成String类的实例化完成。

 

猜你喜欢

转载自blog.csdn.net/weixin_41839432/article/details/84431918
am