Erros em saída - exibe scape na saída de string

public class concatenacao {
public static void main(String[] args) {
String produto1 = “Computador”;
String produto2 = “Mesa de Escritório”;
double valor1 = 2500.50;
double valor2 = 650.00;

//System.out.printf("O %s vale: %.2f%n",produto1,valor1);
System.out.printf("O %s vale: %.2f." + produto1, valor1 + " e a %s tem o preço de: %.2f%n." + produto2,valor2);
	
String name = "John";
int age = 25;
System.out.printf("%nMy name is " + name + " and I am " + age + " years old.%n");//pode também println



String nome = "Cameron";
String site = "Tss";
System.out.printf("Gosto dos artigos que %s escreve no %S. %n" , nome , site + " meu amigo se chama " + name + " e tem " + age + " anos de idade.%n");
 /* Saída: Gosto dos artigos que Cameron escreve no TSS. */ 
}

}
Porque na saída do printf exibe o scape das variáveis e não os valores dentro delas? Quando executo tenho a saída de %S ou %d invés dos valores, númericos ou strings. Obrigado.

Não é assim que se usa printf.

Repare no que vc fez:

System.out.printf("O %s vale: %.2f." + produto1, valor1 + " e a %s tem o preço de: %.2f%n." + produto2, valor2);

Nesta linha, vc passou 3 argumentos para printf. Mudando um pouco a formatação pra ficar mais claro:

System.out.printf(
    "O %s vale: %.2f." + produto1,                          // primeiro argumento
    valor1 + " e a %s tem o preço de: %.2f%n." + produto2,  // segundo argumento
    valor2                                                  // terceiro argumento
);

Note que os argumentos são separados por vírgulas, e no caso acima tem três.

Bom, printf funciona assim: o primeiro argumento é uma string que contém o formato, e todos os demais argumentos são os valores a serem impressos.

Basicamente, para cada especificador de formato (% seguido de alguma coisa) encontrado no primeiro argumento, ele troca pelo valor correspondente (o primeiro %algumacoisa é substituído pelo segundo argumento do printf, o segundo %algumacoisa é substituído pelo terceiro argumento do printf e assim por diante).

Então no caso acima, o formato é a string "O %s vale: %.2f." + produto1. Repare que produto1 é concatenado nesta string, o que quer dizer que o formato é a string O %s vale: %.2f.Computador.

Depois, o %s corresponde ao segundo argumento, que é a string resultante de valor1 + " e a %s tem o preço de: %.2f%n." + produto2, que é o texto "2500.5 e a %s tem o preço de: %.2f%n.Mesa de Escritório". Repare que todo esse texto é o segundo argumento, ou seja, tudo isso será colocado no lugar do %s do formato (“O %s vale etc…”). Mesmo que esse texto contenha %s e tudo mais, como ele é o segundo argumento, não são feitas substituições nele (isso só acontece no primeiro argumento).

A mesma confusão foi feita nos outros exemplos. O correto é que o primeiro argumento contenha todo o texto que vc quer, colocando os especificadores no meio do texto, e os demais argumentos são os respectivos valores.

Ou seja:

String produto1 = "Computador";
String produto2 = "Mesa de Escritório";
double valor1 = 2500.50;
double valor2 = 650.00;

System.out.printf("O %s vale: %.2f e a %s tem o preço de: %.2f.%n", produto1, valor1, produto2, valor2);

String name = "John";
int age = 25;
System.out.printf("%nMy name is %s and I am %d years old.%n", name, age);

String nome = "Cameron";
String site = "Tss";
System.out.printf("Gosto dos artigos que %s escreve no %S. Meu amigo se chama %s e tem %d anos de idade.%n", nome, site, name, age);
1 curtida

Muito obrigado por sua resposta. Vou praticar mais e estudar bem para compreender. Grato.

Entendi o erro. Eu pensei de ter intercalar o texto com as variáveis. O correto é colocar tudo, as strings com seus respectivos valores antes e depois os parâmetros para cada variável. O compilador ajustará o formato de acordo com os scapes e a posição dos parâmetros atribuídos as respectivas variáveis.

Eu pensei de ter separar por cada String com seu respectivo scape e depois o parâmetro e concatenar novamente com a outra variável, mas não é assim o funcionamento como eu vi. A string de saíde tem de ser passada como um parâmetro só com seus respectivos scapes na posição desejada. Muito obrigado novamente.