目录
在Java中一切皆对象,一切都围绕对象进行,找对象、建对象,用对象等
类:把具有相同属性和行为的一类对象抽象为类。类是抽象概念,如人类、犬类等,无法具体到每个实体。
对象:某个类的一个实体,当有了对象后,这些属性便有了属性值,行为也就有了相应的意义。
类是描述某一对象的统称,对象是这个类的一个实例而已。有类之后就能根据这个类来产生具体的对象。一类对象所具备的共同属性和行为(方法)都在类中定义。
class 类名称 {
成员变量/ 实例变量;
成员方法;
}
类名称 引用名称 = new 类名称()
Person per = new Person();
这个对象的引用 对象(在堆中储存)
(相当于给对象起了个名字)(所有类的对象都是引用数据类型)
public class Test {
public static void main(String[] args) {
//创建一个实例化对象
Person per1 = new Person();
//通过对象来调用实例变量、成员方法
per1.name = "小韩";
per1.age = 18;
per1.sex = "女";
per1.print();
Person per2 = new Person();
per2.print();
}
}
class Person{
//成员变量(实例变量),在堆中的每个对象中存储,通过对象调用
String name;//默认值为null
int age;//默认值为0
String sex;//默认值为null
//成员方法(实例方法),在JVM的方法区中存储,通过对象调用
void eat(String food){
System.out.println(name+"正在吃"+food);
}
void print(){
System.out.println("name:"+name+", age:"+age+", sex:"+sex);
}
}
输出结果:

注意事项:
//sex的默认值为null
//sex.length()
System.out.println(per2.sex.length()); 
1.当一个实例变量被static关键字修饰后,它就表示类的属性,该类的所有对象共享此属性,且对象的属性值相同。static修饰的属性在JVM的方法区中存储。
2.static修饰的属性,直接通过类名称就可以访问,无须通过对象。
public class staticTest {
public static void main(String[] args) {
Person per1 = new Person();
Person per2 = new Person();
per1.name = "小韩";
per1.age = 18;
per1.print();
per2.print();
Person.country="日本";
per1.print();
per2.print();
System.out.println(Person.country);
}
}
class Person {
//实例变量,成员方法,必须通过该类的对象来访问
String name;
int age;
String sex;
//静态成员变量,不属于对象,属于类,保存在方法区中
// 调用时通过 类名称.country来进行访问
static String country = "中国";
void print(){
System.out.println("name:"+name+", age:"+age+", country:"+country);
}
}
输出结果:

注意:
Person per = null;
System.out.println(per.country);//相当于Person.country
并不会报空指针异常:static属性称为类属性,通过类名称直接访问,此时没有对象也能调用(包含该类的null引用)
3.final 和 static 的区别
class Person {
final int age = 18;//成员常量,在堆中存储,必须在定义时就赋值
static String country = "中国"//静态变量,在方法区中存储,所有Person类的对象共享
}
若在类中定义了一个常量,通常情况下都会把static 和 final 共同使用,称为类的常量
(因为age属于成员常量,Person类的所有对象都有age这个属性,且值都是18——>天然的共享概念,将它定义为static final,所有Person类的对象共享这个属性,全局唯一。(既节省空间,有对应共享语义))
全局常量的命名规则:所有单词全部大写,多个单词使用下划线分隔
static final String STUDENT_SCHOOL ="清华大学";
问题1:能否在方法中定义一个static变量?
不能。在方法中定义的变量是局部变量,在栈中存储,而 static变量是在方法区中存储,若要在方法中定义一个static变量就会产生矛盾,因为一个变量不可能既在栈中存储,又在方法区中存储。

static修饰的方法通过类名称直接访问方法,没有对象也可以访问。
问题2:为什么static 方法是一个静态方法?
因为主方法是程序的入口,在进入主方法前没有对象, 如果主方法是一个成员方法,需要通过对象调用,就会产生矛盾。要使程序开始执行,只有通过类名称直接调用静态方法,无须产生对象。
问题3:静态方法能否访问成员变量和成员方法?
不能。 静态方法可以通过类名称直接访问,此类中没有对象也可以访问;成员方法和成员变量必须要通过类中的对象来访问。没有对象的方法去调用必须通过对象访问的变量和方法,二者之间矛盾。


问题4:成员方法能否访问静态变量和静态方法?
可以。 必须通过对象访问的方法去调用不需要对象就可以访问的变量和方法,逻辑通过
static方法只能调用静态变量和静态方法等,static家族的成员可以相互调用(都属于静态域)
问题5:普通的类能否使用static关键字修饰(不是内部类)?
类定义出来是要产生对象的,用static关键字修饰一个类,这个类不需要对象就能调用,矛盾。

面向对象一共有三大特性:封装、继承和多态(本篇博客主要讨论封装性)
封装:保护性和易用性
封装有很多表现形式,private实现属性和方法的封装只是其中一种。
权限修饰符:在Java中,权限修饰符指的是所修饰的属性、方法或者类可见的范围有多大。
一共有四大访问修饰修饰符,可见的范围由小到大依次为 :
private(私有的):被private 修饰的属性和方法,只在当前类可见,出了类的{ },对外就完全隐藏了,外部不知道有其存在。
default(不需要写这个关键字,什么权限也没有(包访问权限))
protected(继承访问权限)
public(公共的、公开的):被public 修饰的,在当前程序(项目)中都是可见并且可以使用的。
//公共访问权限,主类
public class privateTest {
public static void main(String[] args) {
Bank bank = new Bank();
bank.setPassword();
System.out.println("修改后的密码为:");
System.out.println(bank.getPassword());
System.out.print("银行卡号为:");
System.out.println(bank.getCardNum());
System.out.print("银行卡余额为:");
System.out.println(bank.getBalance());
}
}
//缺省修饰符,包访问权限
class Bank{
//私有属性,只在Bank这个类内部可见
private int cardNum;//卡号,只可取
private double balance;//余额,只可取
private String password = "123456";//密码,既可取也可改
//要在类的外部去使用这些私有属性,需要使用类提供的getter()和setter()方法
//alt + insert 快速生成getter()和setter()方法
//shift+A全选
//get + 属性名称 = 方法命名
public int getCardNum() {
return cardNum;
}
public double getBalance() {
return balance;
}
public String getPassword() {
return password;
}
//设置新密码
public void setPassword() {
//验证旧密码(安全性)
Scanner scan = new Scanner(System.in);
int count = 0;
while(true){
System.out.println("请输入您的旧密码:");
String oldPass = scan.nextLine();
count ++;
if (oldPass.equals(password)) {
System.out.println("验证成功,请输入您的新密码:");
String newPass = scan.nextLine();
password = newPass;
System.out.println("密码修改成功");
break;
}else{
System.out.println("密码错误,请查证后再试!");
if(count == 3){
System.out.println("验证次数过多,银行卡已锁定");
break;
}
}
}
}
}

问题6: private 关键字能否修饰一个类(外部类)?
不能。定义类是为了产生对象,让外部使用的。若用 private 关键字封装此类,则外部根本不知道此类的存在,更不用提使用对象了,矛盾。

1、构造方法:构造方法是类中非常特殊的一类方法,使用关键字new 实例化对象时实际上调用的就是该类的构造方法。
2.构造方法的作用就是产生对象
3.使用new关键字产生一个对象时,大致分为以下两步:
(1)为对象在堆中分配空间(空间大小由该类中成员变量的属性决定)
(2)调用对象的构造方法为对象成员变量赋值(当构造方法调用结束后,该对象初始化完成)
4.构造方法的语法规则
(1)方法名称与类名称完全相同
(2)构造方法没有返回值声明(不是void)
(3)一个类中至少存在一个构造方法,若没有显示定义,编译器会生成一个默认的无参构造。
public class Test {
public static void main(String[] args) {
//当创建一个对象时,默认调用该类的构造方法
Person person = new Person();
}
}
class Person{
String name;
int age;
String sex;
//构造方法名称与类名称完全相同
//没有返回值声明
public Person(){
System.out.println("Person的构造方法");
}
}
输出结果:
若没有定义构造方法,编译器会生成一个默认的无参构造
public class Test {
public static void main(String[] args) {
//当构造对象时,默认调用该类的构造方法
Person person = new Person();
}
}
class Person{
String name;
int age;
String sex;
}

5.当类中自定义了构造方法,默认的无参构造就不再生成。
public class Test {
public static void main(String[] args) {
//当构造对象时,默认调用该类的构造方法
Person person = new Person();
}
}
class Person{
String name;
int age;
String sex;
public Person(String n){
name = n ;
System.out.println("Person类的有参构造");
}
}
编译出错:

6、构造方法的重载
构造方法是为了类中的成员变量赋值的,此时的重载只可能是参数的个数不同。
public class Test {
public static void main(String[] args) {
//当构造对象时,默认调用该类的构造方法
Person person = new Person();
Person person1 = new Person("小韩");
Person person2 = new Person("小韩",18);
Person person3 = new Person("小韩",18,"女");
}
}
class Person{
String name;
int age;
String sex;
public Person(){
//构造方法首行name = null,age = 0;sex = null(不用写)
System.out.println("Person类的无参构造");
}
public Person(String n){
//首行name = null,age = 0;sex = null;
name = n ;
System.out.println("name:"+name);
System.out.println("Person类的一个参数的有参构造");
}
public Person(String n,int a){
name = n ;
age = a;
System.out.println("name:"+name+", age:"+ age );
System.out.println("Person类的两个参数的有参构造");
}
public Person(String n,int a,String s){
name = n ;
age = a;
sex = s;
System.out.println("name:"+name+", age:"+ age +", sex :"+sex);
System.out.println("Person类的三个参数的有参构造");
}
}

7.问题:能否用一个实例化对象去调用它的构造方法?
不能。 构造方法就是去产生对象,如果用构造方法产生的对象去调用产生它的构造方法,就相当于自己又在自己的构造方法(我生我自己)

注:JVM产生对象时调用构造方法,对象实例化结束,无法在程序中手动调用构造方法再次实例化对象的!!!
(一)this关键字调用当前对象的成员变量
public class Test {
public static void main(String[] args) {
Person person = new Person("小韩",18,"女");
person.print();
}
}
class Person{
//成员变量
String name;
int age;
String sex;
public Person(String name,int age,String sex){//形参
name = name;
age = age;
sex = sex;
System.out.println("Person类的有参构造");
}
public void print(){
System.out.println("name:"+name+", age:"+age+", sex:"+sex);
}
}

问:为什么通过构造方法给成员变量初始化了,但输出结果仍是默认值?
形参名称与成员变量名称相同。程序设计理念:就近匹配原则,编译器会找最近的相同名称的变量在哪

问:如何打破就近匹配原则,从类中找同名变量呢?
使用this关键字
public Person(String name,int age,String sex){
this.name = name;
this.age = age;
this.sex = sex;
System.out.println("Person类的有参构造");
}
(二)this关键字调用当前对象的方法
(1)调用普通的成员方法
public class Test {
public static void main(String[] args) {
Student student = new Student();
student.fun();
}
}
class Student{
String name;
int age;
String sex;
public void test(){
System.out.println("Student类的test成员方法");
}
public void fun(){
//test()方法是成员方法,必须通过对象调用
//this表示对象的引用,调用成员方法时不写,编译时也会自动加上
test();//==this.test();
System.out.println("Student类的fun成员方法");
}
}

(2)构造方法的相互调用

若不同参数的构造方法之间出现了重复的调用,可以使用 this(参数)调用其他的构造方法。
public Student(){
System.out.println("*******");
}
public Student(String name){
//调用无参构造
this();
this.name = name;
}
public Student(String name,int age){
//调用参数为name的一个参数的有参构造
this(name);
this.age = age;
}
注意要点:
1.this调用其他的构造方法必须放在当前构造方法的首行

2.this调用构造方法不能成环(否则构造方法就死循环了)
(三)this关键字表示当前对象的引用
(当前是通过哪个对象调用的属性或者方法,this就指代此对象)
public class Test {
public static void main(String[] args) {
Student student1 = new Student();
System.out.println(student1);
student1.fun();
System.out.println();
Student student2 = new Student();
System.out.println(student2);
student2.fun();
}
}
class Student{
String name;
int age;
String sex;
public void fun(){
System.out.println(this);
}
}

代码块:指的是使用{ }括起来的一段代码,称为代码块。根据定义的代码块的位置以及关键字的不同分为以下四种代码块。
(一)普通代码块
定义在方法中,使用{ }括起来的一段代码。
public static void main(String[] args) {
//普通代码块
}
(二)成员代码块
定义在类中,不加任何修饰符的代码块,又称构造块。优先于构造方法执行,有几个对象产生就调用几次构造块。
public class Test {
public static void main(String[] args) {
Student student1 = new Student();
Student student2 = new Student();
}
}
class Student{
String name;
{
//构造块
System.out.println("Student类的构造块");
}
public Student(){
System.out.println("Student类的无参构造");
}
}

(三)静态代码块
定义在类中,使用static修饰的代码块,在类加载时执行一次,与对象无关。无论产生多少对象,静态代码块只在类加载时执行一次。
public class Test {
public static void main(String[] args) {
Student student1 = new Student();
Student student2 = new Student();
}
}
class Student{
String name;
{
//构造块
System.out.println("Student类的构造块");
}
public Student(){
System.out.println("Student类的无参构造");
}
static {
//静态代码块
System.out.println("Student类的静态代码块");
}
}
主类中的静态代码块优先于主方法执行。(JVM要执行主方法,首先要加载主类,主类一加载,静态块就执行了)
public class Test {
static {
System.out.println("主类的静态代码块");
}
public static void main(String[] args) {
System.out.println("进入主方法");
}
}
静态变量存在于方法区中,类定义时就会有初始值(在以下代码中,初始值为10),类此时在方法区中。但此时类只是定义了,还没被加载。当主方法中使用了该类时,就需要把该类从方法区加载到内存中。类加载后,静态代码块就被执行了(age= 10——>age = 100)
public class Test {
public static void main(String[] args) {
Student student = new Student();
System.out.println(student.age);
}
}
class Student{
static int age = 10;
static {
age = 100;
System.out.println("Student类的静态代码块");
}
public Student(){
System.out.println("Student类的无参构造");
}
}

(四)同步代码块(本篇博客暂不涉及)
八、其他
1.匿名对象:new出来的对象,没有引用指向,使用一次后就被JVM销毁。常用于测试类中的某些功能。
如 :new Person();
2、toString方法(注意大小写)
当一个引用类型的变量调用println函数打印时,默认输出的都是引用类型的地址。(不是真正的内存地址,Java中程序员是无法知道任何确认的内存地址)
public class Test {
public static void main(String[] args) {
System.out.println(new Student("小王"));
System.out.println(new Student("小李"));
}
}
class Student{
private String name;
static {
System.out.println("Student类的静态代码块");
}
public Student(){
System.out.println("Student类的无参构造");
}
public Student(String name){
this.name = name;
System.out.println("Person类的有参构造");
}
}

在类中构造一个toString()方法,对象默认调用此方法进行打印。
public String toString(){
String ret = "name:"+this.name;
return ret;
}

总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev
我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss
好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
我在Rails工作并有以下类(class):classPlayer当我运行时bundleexecrailsconsole然后尝试:a=Player.new("me",5.0,"UCLA")我回来了:=>#我不知道为什么Player对象不会在这里初始化。关于可能导致此问题的操作/解释的任何建议?谢谢,马里奥格 最佳答案 havenoideawhythePlayerobjectwouldn'tbeinitializedhere它没有初始化很简单,因为你还没有初始化它!您已经覆盖了ActiveRecord::Base初始化方法,但您没有调
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser
下面例子中的Nested和Child有什么区别?是否只是同一事物的不同语法?classParentclassNested...endendclassChild 最佳答案 不,它们是不同的。嵌套:Computer之外的“Processor”类只能作为Computer::Processor访问。嵌套为内部类(namespace)提供上下文。对于ruby解释器Computer和Computer::Processor只是两个独立的类。classComputerclassProcessor#Tocreateanobjectforthisc
我想让一个yaml对象引用另一个,如下所示:intro:"Hello,dearuser."registration:$introThanksforregistering!new_message:$introYouhaveanewmessage!上面的语法只是它如何工作的一个例子(这也是它在thiscpanmodule中的工作方式。)我正在使用标准的rubyyaml解析器。这可能吗? 最佳答案 一些yaml对象确实引用了其他对象:irb>require'yaml'#=>trueirb>str="hello"#=>"hello"ir