Onde é definida a propriedade length da matriz?

263

Podemos determinar o comprimento de um ArrayList<E>método público size(), como

ArrayList<Integer> arr = new ArrayList(10);
int size = arr.size();

Da mesma forma, podemos determinar o comprimento de um Arrayobjeto usando a lengthpropriedade

String[] str = new String[10];
int size =  str.length;

Enquanto o size()método de ArrayListé definido dentro da ArrayListclasse, onde está essa lengthpropriedade de Arraydefinida?

PATETA
fonte
Em termos de organização das perguntas, eu sugeriria que você colocasse sua pergunta "onde está definida a propriedade length da matriz?" antes de todas as explicações para impedir que sua postagem pareça um tutorial para iniciantes.
NoName 9/07

Respostas:

250

Matrizes são objetos especiais em java, eles têm um atributo simples chamado lengthqual é final.

Não existe uma "definição de classe" de uma matriz (você não pode encontrá-la em nenhum arquivo .class), elas fazem parte da própria linguagem.

10.7 Membros da matriz

Os membros de um tipo de matriz são todos os seguintes:

  • O public finalcampo length, que contém o número de componentes da matriz. lengthpode ser positivo ou zero.
  • O publicmétodo clone, que substitui o método com o mesmo nome na classe Objecte não gera exceções verificadas. O tipo de retorno do clonemétodo de um tipo de matriz T[]é T[].

    Um clone de uma matriz multidimensional é raso, ou seja, ele cria apenas uma única nova matriz. Subarrays são compartilhados.

  • Todos os membros herdados da classe Object; o único método Objectque não é herdado é o seu clonemétodo.

Recursos:

Colin Hebert
fonte
84
Observe também que ArrayList.size()fornece o número de objetos realmente armazenados na matriz, enquanto myArray.length( []) fornece a "capacidade". Ou seja, se for myArray = new int[10];, ele retornará 10. Não é o número de objetos que você colocou na matriz.
Wmorrison365
1
@ Colin Como os objetos de matriz são tão especiais, quero dizer por que os designers precisam torná-la especial e por que não fornecer o arquivo de classe de uma matriz?
Vikas Verma
5
@VikasVerma Por que as matrizes não são como objetos? Por causa da história. Quando o Java foi projetado, a maioria das tentativas de inovação de linguagem falhou quando não era semelhante a C na sintaxe e no estilo. Assim, C ++, Objective-C e Java estavam entre as poucas linguagens que escaparam da obscuridade durante aquela época. O Java foi projetado conscientemente para incluir chaves, primitivos e matrizes simples para parecer familiar aos programadores da época. Veja entrevistas com James Gosling e outras pessoas da Sun. Algumas pessoas aderem ao Collections para obter POO puro e evitam matrizes simples.
Basil Bourque
1
@VikasVerma, em algum momento, o java deve ser construído com tecnologia de nível inferior. Se o java não existir, você não poderá construí-lo com o java. Você precisa usar C ++ (ou qualquer outra coisa, mas C ++ neste caso) para criar uma compilação primitiva para o restante do java ter contexto para sua própria existência. Você não pode ter aulas para tudo sem, eventualmente, chegar ao fundo do poço onde o codifica em C ++. Como exatamente você criaria uma matriz em java? Se você não pode usar um Listporque usa matrizes em suas implementações.
Alexander Pássaro
se você quiser respondê-la como é , então stackoverflow.com/a/50506451/1059372
Eugene
114

É "especial", basicamente, com a sua própria instrução bytecode: arraylength. Portanto, este método:

public static void main(String[] args) {
    int x = args.length;
}

é compilado no bytecode assim:

public static void main(java.lang.String[]);
  Code:
   0:   aload_0
   1:   arraylength
   2:   istore_1
   3:   return

Portanto, não é acessado como se fosse um campo normal. De fato, se você tentar obtê-lo como se fosse um campo normal, assim, ele falhará:

// Fails...
Field field = args.getClass().getField("length");
System.out.println(field.get(args));

Infelizmente, a descrição JLS de cada tipo de matriz com um campo final público lengthé um pouco enganadora :(

Jon Skeet
fonte
1
não me lembro exatamente de uma citação de Albert Einstein, mas o que diz é "as pessoas entendem muito bem uma coisa só podem explicar as coisas de uma maneira muito mais simples", acho que combina com você muito bem :)
JAVA
@ Jon Skeet Como o objeto de matriz é especial, quero dizer por que os designers precisam torná-lo especial e por que não fornecer o arquivo de classe de uma matriz?
Vikas Verma
2
@ VikasVerma: Pense no tamanho de um objeto de matriz. Todos os outros tipos têm um tamanho fixo - cada instância é do mesmo tamanho, enquanto as matrizes variam de acordo com o comprimento. Esse é apenas um exemplo. Se você acha que pode obter os mesmos resultados sem usar nada de especial, como os campos de uma classe de matriz se pareceriam? Como você representaria int[]quando os genéricos não se aplicam a tipos primitivos? (E, diabos, os genéricos não existiam por muito tempo, de qualquer maneira.) Você poderia se livrar sem matrizes usando listas vinculadas para todas as coleções, mas seria péssimo em termos de eficiência.
Jon tiro ao prato
@ JonSkeet Mas e o tipo de classe StringBuffer também tem tamanho fixo? Sim, de fato, eu estava pensando em genéricos, mas você mencionou antes que eu pedisse Obrigado por isso.
Vikas Verma
@VikasVerma: A StringBufferclasse em si, sim - porque contém uma referência a char[](pelo menos; ou não; não sei se ainda existe, de imediato). Portanto, enquanto a StringBuilderé responsável por mais memória, seu tamanho e layout imediatos são corrigidos.
Jon Skeet
18

É definido na especificação da linguagem Java :

Os membros de um tipo de matriz são todos os seguintes:

  • O public finalcampo length, que contém o número de componentes da matriz. lengthpode ser positivo ou zero.

Como existe um número ilimitado de tipos de matriz (para cada classe, há um tipo de matriz correspondente e, em seguida, há matrizes multidimensionais), elas não podem ser implementadas em um arquivo de classe; a JVM precisa fazer isso rapidamente.

Michael Borgwardt
fonte
15

Mesmo que essa não seja uma resposta direta à pergunta, é uma adição ao argumento .lengthvs. .size()Eu estava pesquisando algo relacionado a essa pergunta e, quando me deparei com ela, percebi que as definições fornecidas aqui

O comprimento do campo final público, que contém o número de componentes da matriz .

não está "exatamente" correto.

O comprimento do campo contém o número de locais disponíveis para colocar um componente, não o número de componentes presentes na matriz. Portanto, representa a memória total disponível alocada para essa matriz, e não quanto dessa memória é preenchida.

Alocação de memória de matriz

Exemplo:

static class StuffClass {
    int stuff;
    StuffClass(int stuff) {
        this.stuff = stuff;
    }
}

public static void main(String[] args) {

    int[] test = new int[5];
    test[0] = 2;
    test[1] = 33;
    System.out.println("Length of int[]:\t" + test.length);

    String[] test2 = new String[5];
    test2[0] = "2";
    test2[1] = "33";    
    System.out.println("Length of String[]:\t" + test2.length);

    StuffClass[] test3 = new StuffClass[5];
    test3[0] = new StuffClass(2);
    test3[1] = new StuffClass(33);
    System.out.println("Length of StuffClass[]:\t" + test3.length);         
}

Resultado:

Length of int[]:        5
Length of String[]:     5
Length of StuffClass[]: 5

No entanto, a .size()propriedade do ArrayListfornece o número de elementos na lista:

ArrayList<Integer> intsList = new ArrayList<Integer>();
System.out.println("List size:\t" + intsList.size());
intsList.add(2);
System.out.println("List size:\t" + intsList.size());
intsList.add(33);
System.out.println("List size:\t" + intsList.size());

Resultado:

List size:  0
List size:  1
List size:  2
nem035
fonte
1
Está correto, pois todos os elementos são inicializados em zero. As matrizes não podem estar "vazias"
Guido
Bem, foi exatamente isso que eu disse. Não está "exatamente" correto. Ele ainda possui 5, mesmo que nada tenha sido adicionado à matriz. Portanto, ele não "exatamente" contém o número de elementos na matriz. Seu comentário é apenas uma adição à minha resposta, não um motivo para torná-lo incorreto.
Nem035 28/05
Pode estar "incorreto" se você tentar fazer uma distinção entre nullelementos não nulos. Mas a distinção não funciona. Afinal, o size()(digamos) a também Listpode incluir nullvalores.
Stephen C
Sim, essencialmente, o que sizequero dizer é que se comporta dinamicamente, enquanto lengthé uma propriedade estática ... o fato de o espaço restante não preenchido em uma matriz ser inicializado como " Não Valores " (dependendo do tipo) não contradiz esse ponto.
nem035
5

é um campo final público, que contém o número de componentes da matriz (o comprimento pode ser positivo ou zero)

Uma matriz, portanto, tem os mesmos campos e métodos públicos que a seguinte classe:

class A implements Cloneable, java.io.Serializable {
    public final int length = X;
    public Object clone() {
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e.getMessage());
        }
    }
}

mais informações em

10.7 Membros da matriz

http://java.sun.com/docs/books/jls/second_edition/html/arrays.doc.html

Massimiliano Peluso
fonte
0

Para responder como está, onde está definida essa propriedade de comprimento da matriz ? Em um especial Object header.

Fácil de ver via JOL

 int [] ints = new int[23];
 System.out.println(ClassLayout.parseInstance(ints).toPrintable());

Uma das linhas desta saída será:

OFFSET  SIZE      TYPE DESCRIPTION
16       4        (object header)   17 00 00 00 (00010111 00000000 00000000 00000000) (23)

Geralmente, os objetos têm dois cabeçalhos (marca e klass), os arrays têm mais um que sempre ocupa 4 bytesem comprimento, como sizeé um int.

Eugene
fonte
-1

O comprimento da palavra-chave atua como um dado arquivado definido. Ao usar em uma matriz, podemos usá-la para acessar quantos elementos em uma matriz. Em relação a String [], podemos invocar o método length () definido na classe String. No que diz respeito ao ArrayList, podemos usar o método size () definido em ArrayList. Observe que, ao criar uma lista de matrizes com ArrayList <> (capacidade), o tamanho inicial () dessa lista de matrizes é zero, pois não há elemento.

Xiaogang
fonte