一、类与对象
1、构造方法
作用:可以通过构造方法实现实例化对象中的属性初始化处理。若类中没有自己定义构造方法,JAVA会默认提供一个无参、什么都不做的构造方法。
定义:方法名称必须和类名称保持一致、不允许设置任何的返回值类型、是在使用关键字new实例化对象时自动调用。
构造方法重载:构造方法既然是属于一个方法,那么肯定具备方法的重载性。
class Person{ //定义一个类,类名称首字母大写
private String name; //定义类的属性
private int age;
public Person(String n,int a) { //自定义有参构造方法
name = n;
age = a;
}
public Person() { //定义无参无返回值构造方法(默认)
}
public Person(String n) { //自定义有参构造方法
name = n;
}
public void Person_print() {
System.out.println(name+"----"+age);
}
}
public class Test{
public static void main(String ages[]) {
Person p1 = new Person("小明",22); //构造方法重载
p1.Person_print();
Person p2 = new Person("小花"); //构造方法重载
p2.Person_print();
Person p3 = new Person(); //构造方法重载
p3.Person_print();
}
}
why?为什么构造方法没有返回值,而不用void值代替呢?
答:编译器为了区分构造方法与普通方法,所以构造方法定义时不写返回值类型。
2、setter和getter
面向对象三大特性:封装、继承、多态。那么通过使用setter和getter来对类中的私有属性进行读取和修改(private修饰体现封装性)。
class Person{ //定义一个类,类名称首字母大写
private String name; //定义类的属性
private int age;
public String getName() { //为类中的私有属性分别设置setter和getter方法
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void Person_print() {
System.out.println(name+"----"+age);
}
}
public class Test{
public static void main(String ages[]) {
Person p1 = new Person();
p1.setName("小明");
p1.setAge(20);
p1.Person_print();
}
}
why?构造方法和setter都可以对类中的属性值进行设置,那么它们的区别是什么?
答:构造方法是在对象实例化时为属性设置初始化内容,而setter除了拥有设置属性初始化功能外,还可以修改数据的功能。
3、匿名对象
在实例化时没有对对象进行地址引用(设置对象名),那么此时实例化出来的对象因为没有引用,故会垃圾回收。
new Person();//匿名对象
二、this关键字
this可以描述:当前类中的属性(this.属性),当前类中的方法(this()、this.方法()),描述当前对象;
class Person{
private String name;
private int age;
public Person() {
this.name = "默认值";
this.age = 20;
};
public Person(String name) {
this(); //this()描述无参构造方法
}
public Person(String name,int age) {
this.name = name; //this描述当前类属性
this.age = age;
this.Person_print(); //this描述当前类方法,构造方法可以调用普通方法,但普通方法不能调用构造方法
}
public void Person_print() {
System.out.println(name+"----"+age + "----" + this);//this描述当前对象
}
}
public class Test{
public static void main(String ages[]) {
Person p1 = new Person();
p1.Person_print();
}
}
定义简单JAVA类原则:
类名具有意义、类中每个属性用private封装、每个属性提供setter和getter方法、至少有一个无参构造方法(默认构造方法)、类中不能有任何输出语句、提供一个返回类信息的方法(可选,如getinfo())
class Person{ //类名要有意义
private String name; //属性用private封装
private int age;
public Person() { //至少定义一个无参构造方法
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void setname(String name) { //为每个属性配置getter和setter方法,不管用得着不
this.name = name;
}
public String getname() {
return this.name;
}
public void setage(int age) {
this.age = age;
}
public int getage() {
return this.age;
}
public String getinfo() { //配置一个返回类信息的方法,可选。类中不能有任何输出语句
return "name:" + this.name + ",age:" + this.age;
}
}
public class Test{
public static void main(String args[]) {
Person p1 = new Person("小明",20);
System.out.println(p1.getinfo());
}
}
三、static关键字
注意:static并不受实例化对象的控制,可以直接调用类使用。这也是在主类中定义类和方法需要加static的原因。
static定义类属性:
在类属性中用static修饰,则此属性就变成公共属性,所有通过此类实例化的对象都受这个static公共属性控制,也就是静态变量作用:
class Person{
public static String name; //name属性设置static修饰
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getinfo() { //
return "name:" + this.name + ",age:" + this.age;
}
}
public class Test{
public static void main(String args[]) {
Person p1 = new Person("小明",22);
Person p2 = new Person("小花",20);
System.out.println(p1.getinfo()); //name:小花,age:22
System.out.println(p2.getinfo()); //name:小花,age:20
//可以看到,static修饰类属性后编变成一个公共属性,只要其中一个对象修改了,那么其它对象中属性也被修改了
Person.name = "张三"; //可以不实例化对象直接调用类和修改类属性,前提是public公开
System.out.println(Person.name);
}
}
static定义类方法:
用static定义的方法和普通方法最大的区别就是可以不实例化直接调用,所以就有了限制:
1、static方法只允许调用类中的static方法和static属性
2、非static方法可以调用类中的static方法和static属性
原因:因为static定义的属性和方法可以在没有实例化对象前调用,所以static定义的方法不能调用普通方法和属性。
public class Test{
public static void main(String args[]) {
getinfo(); //这也解释了为啥在主类中定义方法需要加static关键字,因为不需要实例化就能调用static方法
}
public static String getinfo() {
return "hello world";
}
}
四、代码块
静态代码块:
目的:为类中的静态属性初始化,静态代码块会优先于构造块执行,并不管有多少实例化对象,只执行一次。
class Person{
private String name;
private int age;
private static String addr;
public Person() {}
public Person(String name,int age) {
this.name = name;
this.age = age;
}
static { //静态代码块
Person.addr = "北京";
System.out.println("静态代码块会优先构造块执行");
}
}
public class Test{
public static void main(String args[]) {
Person p1 = new Person("小明",20);
Person p2 = new Person("小花",18);
}
}
普通代码块::
目的:可以在一个方法中进行一些结构的拆分,以防止相同变量名称所带来的影响:
public class Test{
public static void main(String args[]) {
{ //定义普通代码块
int x = 10; //通过普通代码块进行结构拆分 局部变量
}
int x = 2; //全局变量
}
}
构造代码块:
目的:在类中定义,会优先于构造方法执行,且每次实例化对象都会调用构造代码块(和静态代码块的区别):
class Person{
public Person() {
System.out.println("构造方法执行了");
}
{ //定义构造代码块,和普通代码块类似,不管不是定义在方法里,而是在类中
System.out.println("构造代码块执行了");
}
}
public class Test{
public static void main(String args[]) {
new Person();
new Person();
/*
构造代码块执行了
构造方法执行了
构造代码块执行了
构造方法执行了
*/
}
}
五、数组
数组的动态初始化:数据类型 数组名称 [] = new 数据类型 [长度];
数组的静态初始化:数据类型 数组名称 [] = new 数据类型 {数据1,数据2......};
public class Test{
public static void main(String args[]) {
String array1 [] = new String [2]; //数组的动态初始化
array1[0] = "你好";
array1[1] = "世界";
String array2 [] = new String [] {"你好","世界"}; //数组的静态初始化
for(int i = 0;i < array1.length;i++) {
System.out.println(array1[i]);
}
}
}
foreach循环:
为了避免使用for循环操作数组下标越界问题,JDK参考.NET增强了for循环:foreach也可以写成for
public class Test{
public static void main(String args[]) {
String array1 [] = new String [2]; //数组的动态初始化
array1[0] = "你好";
array1[1] = "世界";
for(String s1 : array1) {
System.out.println(s1);
}
}
}
多维数组:一个[]表示一行,两个[]表示行和列(表),三个[]表示三维:xyz坐标
public class Test{
public static void main(String args[]) {
String array1 [][] = new String [2][2]; //创建二行二列的多维数组
array1[0][0] = "aa";
array1[0][1] = "11";
array1[1][0] = "bb";
array1[1][1] = "22";
for(String s1[] : array1) {
for(String s2 : s1) {
System.out.println(s2);
}
}
}
}
数组的引用:数组也是引用类型,所以也可以进行引用传递
public class Test{
public static void main(String args[]) {
int int1 [] = new int [] {1,2,3,4,5,6}; //静态初始化定义一个数组
int int2 [] = new int[10];
int2 = array(int1);
for(int i : int2) {
System.out.println(i);
}
}
public static int [] array(int array_int1 []) { //数组可以当作参数传递,也可以返回数组
for(int i = 0; i < array_int1.length; i++) {
array_int1[i] = array_int1[i] * 2;
}
return array_int1;
}
}
可变参数:当传递的参数个数不确定时可采用可变参数
public class Test{
public static void main(String args[]) {
array(1,2,3,4,5,6); //可变参数可接受普通参数列表及数组引用参数
array(new int [] {1,2,3,4,5});
}
public static void array(int ... int1) { //通过加三个.就是可变参数传递
for(int i : int1) {
System.out.println(i);
}
}
}
对象数组:数组可以保存基本数据类型,当然也可以保存引用类型:类
class Person{
private String name;
private int age;
public Person() {}
public Person(String name,int age) {
this.name = name;
this.age = age;
}
public String getinfo() {
return "姓名:" + this.name + "年龄:" + this.age;
}
}
public class Test{
public static void main(String args[]) {
Person array_person [] = new Person [3];
array_person [0] = new Person("张三",17);
array_person [1] = new Person("李四",20);
array_person [2] = new Person("王五",23);
for(int i = 0; i < array_person.length; i++) {
System.out.println(array_person[i].getinfo());
}
}
}
六、引用传递
类之间可以互相关联,也可以由多个类组合成一个大的类:代码链
class 电脑{
private 主机 主机 []; //一台电脑可以有多个主机 对象数组
private 显示器 显示器; //一个显示器
}
class 主机{
private CPU CPU;
private 硬盘 硬盘;
private 内存 内存;
}
class 显示器{
private 鼠标 鼠标;
private 键盘 键盘;
}
class 鼠标{}
class 键盘{}
class CPU{}
class 硬盘{}
class 内存{}
public class Test{
public static void main(String args[]) {
}
}