目录
什么是类?
什么是对象?
类的成员
类成员的权限修饰符private和public
重写的toString方法
static关键字修饰的成员属性和方法
类的封装:
构造方法:
this关键字:
代码块:
匿名对象:
什么是类?
在生活中我们有很多抽象的东西,比如猫,房子,车子,而类就是生活中一个抽象的东西,所谓类就是抽象的类型,就像普通数据类型一样,有int类,有double类,而在程序中如果想要实现这些抽象的东西,我们就要定义这些类型。
什么是对象?
就是类的实例,如果我们定义了房子类,而房子有大小,有颜色,有一些特征,而类的实例我们可能有大房子,小房子,不同的房子有不同的特征,将类进行实例化,我们就要定义不同的对象,因为房子分为大房子,小房子,我们可以定义一个对象,将它设置为大房子,再定义一个对象,将它设置为小房子。
类的定义:
class 类名
{
属性1;
属性2;
}
类的定义代码:
class House{
String size;
String color;
}
public class ClassDemo {
public static void main(String[] args ){
House house1=new House();
house1.color="blue";
house1.size="大房子";
House house2=new House();
house2.color="red";
house2.size="小房子";
}
}
属性访问符: .
访问类中的属性,我们可以用 对象.属性名
在这里我们将房子类,具体为了两个房子,house1和house2,然后我们分别设置了属性
类的成员
类的成员有属性,方法和代码块,内部类,接口等,这里具体介绍属性,方法,代码块。
我们将类的成员属性和方法可以这样理解为,属性是类的一些特征,而方法就是类的行为,比如定义一个猫类,一个猫可以有年龄,颜色,性别,而它的行为,有吃饭,睡觉等,我们可以这样定义
class Cat{
public int age;
public String color;
public String sex;
public String name;
void eat(){
System.out.println(name+"吃饭");
}
void sleep(){
System.out.println(name+"睡觉");
}
}
类成员的权限修饰符private和public
class Cat{
public int age;
public String color;
public String sex;
private String name;
void eat(){
System.out.println(name+"吃饭");
}
void sleep(){
System.out.println(name+"睡觉");
}
}
public class ClassDemo {
public static void main1(String[] args ){
Cat cat=new Cat();
cat.age=10;
cat.color="黑色";
cat.sex="公";
cat.name="喵喵";//报错,因为这里将属性name设置为了private
}
}
当我们将name设置为了private的话,此时这个属性就变为了私有的,因此我们就不能用成员访问符.来进行访问,如果成员属性或者方法设置为private我们就不能通过成员访问符来进行访问。
如果我们不能直接通过这样的方式来访问,那么我们需要用到set和get方法
class Cat{
public int age;
public String color;
public String sex;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private void eat(){
System.out.println(name+"吃饭");
}
void sleep(){
System.out.println(name+"睡觉");
}
}
public class ClassDemo {
public static void main1(String[] args ){
Cat cat=new Cat();
cat.age=10;
cat.color="黑色";
cat.sex="公";
cat.setName("喵喵");
System.out.println(cat.getName());
}
}
在这里我们通过了set方法给类变量name赋值,通过get方法得到name的值,在这里的set和get方法是可以自动生成的,右键鼠标,选择generate,然后点击setterandgetter,然后选择想要设置的属性,这样就自动生成了get和set方法。
重写的toString方法
如果我们创建了一个对象,我们可以通过重写的toString方法来对对象进行输出
@Override
public String toString() {
return "Cat{" +
"age=" + age +
", color='" + color + ''' +
", sex='" + sex + ''' +
", name='" + name + ''' +
'}';
}
可以自己生成,右击鼠标点击generate,点击toString,选择要打印的属性,然后就生成了toString方法,方法上面的那个是注解,不用管它,它是标明了这是一个重写方法而已。
如果成员方法被private修饰,那么它只能在本类中调用,而不能直接通过对象调用。
static关键字修饰的成员属性和方法
class Dog{
public static int age;
public String name;
//错误:非静态方法中不能定义静态属性,但可以使用静态方法
public void fun1(){
age=10;
fun3();
public static int age3;
}
//错误:静态方法中不能使用非静态属性和定义非静态属性,也不能使用非静态方法
public static void fun2(){
name="喵喵";
public static int age1;
fun1();
}
public static void fun3(){
age=10;
}
}
static修饰成员属性和方法的时候
注意:
1.非静态方法可以使用静态方法,但是不可以定义静态属性,可以使用定义过的静态属性
public void fun1(){
age=10; //已经定义过的静态属性
fun3(); //静态方法
public static int age3;//定义静态属性
}
原因:
静态成员变量是保存在方法区中的,是全局变量,而如果在非静态方法中定义静态变量,因为方法中的变量是局部变量,存放在栈中,这样就矛盾了,而可以使用静态方法,是因为,静态方法是通过类名访问的,跟对象没有关系,而非静态方法虽然是通过对象访问的,但是静态方法跟对象没有关系,所以可以在非静态方法中访问静态方法。
2.静态方法中不可以访问非静态方法,定义静态变量,使用非静态变量
public static void fun2(){
public static int age1; //静态方法中不能定义静态变量
name="喵喵";//静态方法中不能使用非静态变量
fun1(); //静态方法中不能使用非静态方法
}
原因:
方法中定义的变量是局部变量,而static修饰的是全局变量,冲突,java中不允许这样做,报错。在静态方法中不能访问类中的非静态属性,因为非静态属性是通过对象访问的,而静态方法是通过类名访问的,当我们在外面直接通过类名进行访问的时候,并没有涉及到具体的对象,因此矛盾。静态方法内只能使用静态方法,不能使用非静态方法。
类中static的说明
代码如下:
class A{
public int count;
public static int Count;
}
public class ClassDemo2 {
public static void main(String[] args) {
A a1=new A();
a1.count++;
A.Count++;
A a2=new A();
a2.count++;
A.Count++;
System.out.println(a1.count);
System.out.println(a2.count);
System.out.println(A.Count);
}
}
在这里说明的是这样的:
1.同一个类的不同对象使用的是同一个Count,因为它存放在方法区,是一个全局变量
2.不是static修饰的count,对象之间是独立的,它们不是公用一个count
内存解析:
这就是静态Count和不是的区别。
类的封装:
用private来进行封装,因为我们在写程序时为了防止我们写的类中的属性名被别人修改,而造成不便,我们为了将类进行封装起来,我们可以将属性设置为private方法,这样别人就不可以通过对象来进行访问,只能通过set和get方法来对其进行操作,就是让调用者不用管具体,只负责调用即可。
class A{
private int a;
private int b;
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
public int getB() {
return b;
}
public void setB(int b) {
this.b = b;
}
}
public class ClassDemo2 {
public static void main(String[] args) {
A a=new A();
a.setA(1);
a.setB(1);
System.out.println(a.getA()+" "+a.getB());
}
}
当我们所写的内容不想让被人看到,就可以用private进行封装
构造方法:
无参构造方法:
class A{
private int a;
private int b;
A(){
System.out.println("我是无参构造方法");
}
}
public class ClassDemo2 {
public static void main(String[] args) {
A a=new A();
}
}
当我们new一个对象时,如果不给参数,默认调用的时无参构造函数,这里的无参构造方法可以不定义,就算不定义,也会默认的去调用无参构造方法。
有参构造方法
class A{
private int a;
private int b;
A(int a,int b){
this.a=a;
this.b=b;
}
}
public class ClassDemo2 {
public static void main(String[] args) {
A a=new A();
}
}
如果我们不显示的写无参构造方法,而是在类中定义了有参构造方法,此时如果我们定义了一个对象,它没有参数,而我们又没有显示的写无参构造函数,此时程序会报错,找不到该构造函数,因此,当我们在类中定义了有参构造,我们创建对象,使用的是无参,我们需要显示的定义出来。
class A{
private int a;
private int b;
A(){
System.out.println("无参构造");
}
A(int a,int b){
this.a=a;
this.b=b;
}
}
public class ClassDemo2 {
public static void main(String[] args) {
A a=new A();
A a1=new A(1,2);
}
}
this关键字:
A(int a,int b){
a=a;
b=b;
}
错误:因为变量a和变量b在方法的形参中,而此时是自己给自己赋值,而不是给类中的a和b赋值,因为局部变量优先使用。
A(int a,int b){
this.a=a;
this.b=b;
}
这里的this是当对象调用时,这里的this指的是调用该方法对象的引用,谁调用它,这个this就是指谁的引用
class A{
private int a;
private int b;
A(){
this(1,2);
}
A(int a,int b){
this.a=a;
this.b=b;
}
}
public class ClassDemo2 {
public static void main(String[] args) {
A a=new A();
A a1=new A(1,2);
}
}
我们也可以在一个构造方法中通过this调用另一个构造方法,但是注意一点就是this要放在第一行
class A{
private int a;
private int b;
A(){
System.out.println("haha");
this(1,2);//报错
}
A(int a,int b){
this.a=a;
this.b=b;
}
}
public class ClassDemo2 {
public static void main(String[] args) {
A a=new A();
A a1=new A(1,2);
}
}
这样在无参中通过this调用另一个构造函数会报错。
this的错误使用:构成死循环
class A{
private int a;
private int b;
A(){
this(1,2);
}
A(int a,int b){
this(1,2,3);
}
A(int a,int b,int c){
this(1,2);
}
}
public class ClassDemo2 {
public static void main(String[] args) {
A a=new A();
A a1=new A(1,2);
}
}
这样两个调用三个参数的,三个参数的再调用两个参数的,这样就会构成死循环。
代码块:
普通代码块 构造块,静态块,同步代码块(多线程时讲解)
普通代码块:
public class ClassDemo2 {
public static void main(String[] args) {
{
int a=10;
a=a+1;
}
}
}
构造代码块:
再类中定义,不加修饰符,也叫实例代码块,用来对类成员属性进行初始化
class A{
private int a;
private int b;
{
this.a=10;
this.b=20;
}
}
public class ClassDemo2 {
public static void main(String[] args) {
}
}
实例代码块优先于构造方法执行
class A{
public int a;
public int b;
{
this.a=10;
this.b=20;
System.out.println("实例代码块");
}
A(int a,int b){
this.a=a;
this.b=b;
System.out.println("构造函数");
}
}
public class ClassDemo2 {
public static void main(String[] args) {
A a=new A(30,40);
System.out.println(a.a+" "+a.b);
}
}
静态代码块:
用于对静态类成员属性进行赋值
package com.ziyi.javalearn;
class A{
public int a;
public int b;
public static int c;
{
this.a=10;
this.b=20;
System.out.println("实例代码块");
}
static {
c=10;
System.out.println("静态代码块");
}
A(int a,int b){
this.a=a;
this.b=b;
System.out.println("构造函数");
}
}
public class ClassDemo2 {
public static void main(String[] args) {
A a=new A(30,40);
A a1=new A(10,20);
A a2=new A(40,50);
}
}
静态代码块的执行大于构造代码块和构造方法,而且无论创建多少个对象,静态代码块只执行一次并且最先执行。
执行结果如下:
另外一点就是,执行的顺序与在类中书写的位置无关。
匿名对象:
class A{
public int a;
public int b;
public static int c;
A(int a,int b){
this.a=a;
this.b=b;
System.out.println("构造函数");
}
@Override
public String toString() {
return "A{" +
"a=" + a +
", b=" + b +
'}';
}
}
public class ClassDemo2 {
public static void main(String[] args) {
System.out.println(new A(1, 2).toString());
}
}
匿名对象是我们创建了,但是没有具体的对象名字,只是使用一次,如果我们创建一个对象只是为了使用一次,我们可以使用匿名对象。



